* [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost
@ 2012-05-14 21:07 Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 01/11] msix: Factor out msix_get_message Jan Kiszka
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
This series is another major milestone of merging qemu-kvm into
upstream. It implements the required interfaces and logic to directly
inject MSI-X interrupts generated by the vhost-net kernel module into
the KVM in-kernel irqchip. This involves
- establishing MSI vector notifiers, so far triggered on relevant MSI-X
configuration changes of subscribed PCI devices
- support for static vIRQ-to-MSI routes
- an API for linking an IRQFD with such a vIRQ
- the usage of these services in virtio-pci to enable direct injection
The series also contains some smaller refactorings of the KVM IRQ
routing API such as automatic committing of route changes. It applies on
top of the KVM MSI support series [1] posted recently. The complete
stack is available at
git://git.kiszka.org/qemu-kvm.git queues/kvm-msi-irqfd
If the proposes API is acceptable, I will also provide some morphing
patches for qemu-kvm to make the merge of both trees smoother.
After this series, to only reasons to still use qemu-kvm for production
purposes will be PCI device assignment and potential dependencies on
legacy command line switches as well as vmstate formats (when requiring
backward migration support). However, the majority of users should be
able to switch to upstream QEMU seamlessly and finally receive the same
level of performance on x86.
[1] http://thread.gmane.org/gmane.comp.emulators.kvm.devel/90651
Jan Kiszka (11):
msix: Factor out msix_get_message
msix: Invoke msix_handle_mask_update on msix_mask_all
msix: Introduce vector notifiers
kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route
kvm: Introduce kvm_irqchip_add_msi_route
kvm: Publicize kvm_release_gsi as kvm_irqchip_release_virq
kvm: Make kvm_irqchip_commit_routes an internal service
kvm: Introduce kvm_irqchip_add/remove_irqfd
kvm: Enable use of kvm_irqchip_in_kernel in hwlib code
msix: Add msix_nr_vectors_allocated
virtio/vhost: Add support for KVM in-kernel MSI injection
hw/msix.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++---
hw/msix.h | 6 +++
hw/pc_piix.c | 14 ++----
hw/pci.h | 8 ++++
hw/virtio-pci.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-pci.h | 6 +++
kvm-all.c | 97 +++++++++++++++++++++++++++++++++++-------
kvm-stub.c | 23 ++++++++++
kvm.h | 17 +++++---
9 files changed, 375 insertions(+), 38 deletions(-)
--
1.7.3.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 01/11] msix: Factor out msix_get_message
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 02/11] msix: Invoke msix_handle_mask_update on msix_mask_all Jan Kiszka
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
This helper will also be used by the upcoming config notifier.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/msix.c | 19 +++++++++++++------
1 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index 3835eaa..3197465 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -35,6 +35,15 @@
#define MSIX_PAGE_PENDING (MSIX_PAGE_SIZE / 2)
#define MSIX_MAX_ENTRIES 32
+static MSIMessage msix_get_message(PCIDevice *dev, unsigned vector)
+{
+ uint8_t *table_entry = dev->msix_table_page + vector * PCI_MSIX_ENTRY_SIZE;
+ MSIMessage msg;
+
+ msg.address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
+ msg.data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
+ return msg;
+}
/* Add MSI-X capability to the config space for the device. */
/* Given a bar and its size, add MSI-X table on top of it
@@ -352,9 +361,7 @@ uint32_t msix_bar_size(PCIDevice *dev)
/* Send an MSI-X message */
void msix_notify(PCIDevice *dev, unsigned vector)
{
- uint8_t *table_entry = dev->msix_table_page + vector * PCI_MSIX_ENTRY_SIZE;
- uint64_t address;
- uint32_t data;
+ MSIMessage msg;
if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector])
return;
@@ -363,9 +370,9 @@ void msix_notify(PCIDevice *dev, unsigned vector)
return;
}
- address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
- data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
- stl_le_phys(address, data);
+ msg = msix_get_message(dev, vector);
+
+ stl_le_phys(msg.address, msg.data);
}
void msix_reset(PCIDevice *dev)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 02/11] msix: Invoke msix_handle_mask_update on msix_mask_all
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 01/11] msix: Factor out msix_get_message Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 03/11] msix: Introduce vector notifiers Jan Kiszka
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
In preparation of firing vector notifiers on mask changes, call
msix_handle_mask_update also from msix_mask_all. So far, this will have
no real effect.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/msix.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index 3197465..e1a7d92 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -231,10 +231,14 @@ static void msix_mmio_setup(PCIDevice *d, MemoryRegion *bar)
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
{
int vector;
+
for (vector = 0; vector < nentries; ++vector) {
unsigned offset =
vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
+ bool was_masked = msix_is_masked(dev, vector);
+
dev->msix_table_page[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
+ msix_handle_mask_update(dev, vector, was_masked);
}
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 03/11] msix: Introduce vector notifiers
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 01/11] msix: Factor out msix_get_message Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 02/11] msix: Invoke msix_handle_mask_update on msix_mask_all Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-15 13:31 ` [Qemu-devel] [PATCH 12/11] msix: Trigger vector mask update check after vmload Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 04/11] kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route Jan Kiszka
` (7 subsequent siblings)
10 siblings, 1 reply; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Vector notifiers shall be triggered by the MSI/MSI-X core whenever a
relevant configuration change is programmed by the guest. In case of
MSI-X, changes are reported when the effective mask (global &&
per-vector) alters its state. On unmask, the current vector
configuration is included in the event report. This allows users - e.g.
virtio-pci layer - to transfer this information to external MSI-X
routing subsystems - like vhost + KVM in-kernel irqchip.
This implementation only provides MSI-X support, but extension to MSI is
feasible and will be provided later on when adding support for KVM PCI
device assignment.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/msix.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/msix.h | 4 +++
hw/pci.h | 8 +++++
3 files changed, 100 insertions(+), 0 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index e1a7d92..c6968aa 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -139,13 +139,34 @@ static bool msix_is_masked(PCIDevice *dev, int vector)
return msix_vector_masked(dev, vector, dev->msix_function_masked);
}
+static void msix_fire_vector_notifier(PCIDevice *dev,
+ unsigned int vector, bool is_masked)
+{
+ MSIMessage msg;
+ int ret;
+
+ if (!dev->msix_vector_use_notifier) {
+ return;
+ }
+ if (is_masked) {
+ dev->msix_vector_release_notifier(dev, vector);
+ } else {
+ msg = msix_get_message(dev, vector);
+ ret = dev->msix_vector_use_notifier(dev, vector, msg);
+ assert(ret >= 0);
+ }
+}
+
static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked)
{
bool is_masked = msix_is_masked(dev, vector);
+
if (is_masked == was_masked) {
return;
}
+ msix_fire_vector_notifier(dev, vector, is_masked);
+
if (!is_masked && msix_is_pending(dev, vector)) {
msix_clr_pending(dev, vector);
msix_notify(dev, vector);
@@ -425,3 +446,70 @@ void msix_unuse_all_vectors(PCIDevice *dev)
return;
msix_free_irq_entries(dev);
}
+
+static int msix_set_notifier_for_vector(PCIDevice *dev, unsigned int vector)
+{
+ MSIMessage msg;
+
+ if (msix_is_masked(dev, vector)) {
+ return 0;
+ }
+ msg = msix_get_message(dev, vector);
+ return dev->msix_vector_use_notifier(dev, vector, msg);
+}
+
+static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector)
+{
+ if (msix_is_masked(dev, vector)) {
+ return;
+ }
+ dev->msix_vector_release_notifier(dev, vector);
+}
+
+int msix_set_vector_notifiers(PCIDevice *dev,
+ MSIVectorUseNotifier use_notifier,
+ MSIVectorReleaseNotifier release_notifier)
+{
+ int vector, ret;
+
+ assert(use_notifier && release_notifier);
+
+ dev->msix_vector_use_notifier = use_notifier;
+ dev->msix_vector_release_notifier = release_notifier;
+
+ if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
+ (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
+ for (vector = 0; vector < dev->msix_entries_nr; vector++) {
+ ret = msix_set_notifier_for_vector(dev, vector);
+ if (ret < 0) {
+ goto undo;
+ }
+ }
+ }
+ return 0;
+
+undo:
+ while (--vector >= 0) {
+ msix_unset_notifier_for_vector(dev, vector);
+ }
+ dev->msix_vector_use_notifier = NULL;
+ dev->msix_vector_release_notifier = NULL;
+ return ret;
+}
+
+void msix_unset_vector_notifiers(PCIDevice *dev)
+{
+ int vector;
+
+ assert(dev->msix_vector_use_notifier &&
+ dev->msix_vector_release_notifier);
+
+ if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
+ (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
+ for (vector = 0; vector < dev->msix_entries_nr; vector++) {
+ msix_unset_notifier_for_vector(dev, vector);
+ }
+ }
+ dev->msix_vector_use_notifier = NULL;
+ dev->msix_vector_release_notifier = NULL;
+}
diff --git a/hw/msix.h b/hw/msix.h
index 5aba22b..f33f18b 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -29,4 +29,8 @@ void msix_notify(PCIDevice *dev, unsigned vector);
void msix_reset(PCIDevice *dev);
+int msix_set_vector_notifiers(PCIDevice *dev,
+ MSIVectorUseNotifier use_notifier,
+ MSIVectorReleaseNotifier release_notifier);
+void msix_unset_vector_notifiers(PCIDevice *dev);
#endif
diff --git a/hw/pci.h b/hw/pci.h
index 8d0aa49..c3cacce 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -173,6 +173,10 @@ typedef struct PCIDeviceClass {
const char *romfile;
} PCIDeviceClass;
+typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
+ MSIMessage msg);
+typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
+
struct PCIDevice {
DeviceState qdev;
/* PCI config space */
@@ -243,6 +247,10 @@ struct PCIDevice {
bool has_rom;
MemoryRegion rom;
uint32_t rom_bar;
+
+ /* MSI-X notifiers */
+ MSIVectorUseNotifier msix_vector_use_notifier;
+ MSIVectorReleaseNotifier msix_vector_release_notifier;
};
void pci_register_bar(PCIDevice *pci_dev, int region_num,
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 04/11] kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (2 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 03/11] msix: Introduce vector notifiers Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 05/11] kvm: Introduce kvm_irqchip_add_msi_route Jan Kiszka
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
We will add kvm_irqchip_add_msi_route, so let's make the difference
clearer.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/pc_piix.c | 8 ++++----
kvm-all.c | 2 +-
kvm.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 6a75718..c17f906 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -63,17 +63,17 @@ static void kvm_piix3_setup_irq_routing(bool pci_enabled)
if (i == 2) {
continue;
}
- kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
+ kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
}
for (i = 8; i < 16; ++i) {
- kvm_irqchip_add_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
+ kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
}
if (pci_enabled) {
for (i = 0; i < 24; ++i) {
if (i == 0) {
- kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
+ kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
} else if (i != 2) {
- kvm_irqchip_add_route(s, i, KVM_IRQCHIP_IOAPIC, i);
+ kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
}
}
}
diff --git a/kvm-all.c b/kvm-all.c
index 8f8cec5..8ab83db 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -935,7 +935,7 @@ static void kvm_add_routing_entry(KVMState *s,
set_gsi(s, entry->gsi);
}
-void kvm_irqchip_add_route(KVMState *s, int irq, int irqchip, int pin)
+void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin)
{
struct kvm_irq_routing_entry e;
diff --git a/kvm.h b/kvm.h
index 7857dbf..8b061bd 100644
--- a/kvm.h
+++ b/kvm.h
@@ -134,7 +134,7 @@ void kvm_arch_init_irq_routing(KVMState *s);
int kvm_irqchip_set_irq(KVMState *s, int irq, int level);
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
-void kvm_irqchip_add_route(KVMState *s, int gsi, int irqchip, int pin);
+void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
int kvm_irqchip_commit_routes(KVMState *s);
void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 05/11] kvm: Introduce kvm_irqchip_add_msi_route
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (3 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 04/11] kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 06/11] kvm: Publicize kvm_release_gsi as kvm_irqchip_release_virq Jan Kiszka
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Add a service that establishes a static route from a virtual IRQ line to
an MSI message. Will be used for IRQFD and device assignment. As we will
use this service outside of CONFIG_KVM protected code, stub it properly.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 31 +++++++++++++++++++++++++++++++
kvm-stub.c | 8 ++++++++
kvm.h | 10 ++++++----
3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 8ab83db..f45b852 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1080,6 +1080,32 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
return kvm_irqchip_set_irq(s, route->kroute.gsi, 1);
}
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
+{
+ struct kvm_irq_routing_entry kroute;
+ int gsi;
+
+ if (!kvm_irqchip_in_kernel()) {
+ return -ENOSYS;
+ }
+
+ gsi = kvm_get_pseudo_gsi(s);
+ if (gsi < 0) {
+ return gsi;
+ }
+
+ kroute.gsi = gsi;
+ kroute.type = KVM_IRQ_ROUTING_MSI;
+ kroute.flags = 0;
+ kroute.u.msi.address_lo = (uint32_t)msg.address;
+ kroute.u.msi.address_hi = msg.address >> 32;
+ kroute.u.msi.data = msg.data;
+
+ kvm_add_routing_entry(s, &kroute);
+
+ return gsi;
+}
+
#else /* !KVM_CAP_IRQ_ROUTING */
static void kvm_init_irq_routing(KVMState *s)
@@ -1090,6 +1116,11 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
{
abort();
}
+
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
+{
+ abort();
+}
#endif /* !KVM_CAP_IRQ_ROUTING */
static int kvm_irqchip_create(KVMState *s)
diff --git a/kvm-stub.c b/kvm-stub.c
index 47c573d..db3a7dc 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -12,10 +12,13 @@
#include "qemu-common.h"
#include "hw/hw.h"
+#include "hw/msi.h"
#include "cpu.h"
#include "gdbstub.h"
#include "kvm.h"
+KVMState *kvm_state;
+
int kvm_init_vcpu(CPUArchState *env)
{
return -ENOSYS;
@@ -128,3 +131,8 @@ int kvm_on_sigbus(int code, void *addr)
{
return 1;
}
+
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
+{
+ return -ENOSYS;
+}
diff --git a/kvm.h b/kvm.h
index 8b061bd..67df1f1 100644
--- a/kvm.h
+++ b/kvm.h
@@ -44,6 +44,10 @@ typedef struct KVMCapabilityInfo {
#define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP }
#define KVM_CAP_LAST_INFO { NULL, 0 }
+struct KVMState;
+typedef struct KVMState KVMState;
+extern KVMState *kvm_state;
+
/* external API */
int kvm_init(void);
@@ -88,10 +92,6 @@ int kvm_on_sigbus(int code, void *addr);
/* internal API */
-struct KVMState;
-typedef struct KVMState KVMState;
-extern KVMState *kvm_state;
-
int kvm_ioctl(KVMState *s, int type, ...);
int kvm_vm_ioctl(KVMState *s, int type, ...);
@@ -213,4 +213,6 @@ int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
uint32_t size);
int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
+
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 06/11] kvm: Publicize kvm_release_gsi as kvm_irqchip_release_virq
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (4 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 05/11] kvm: Introduce kvm_irqchip_add_msi_route Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 07/11] kvm: Make kvm_irqchip_commit_routes an internal service Jan Kiszka
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
This allows to drop routes created by kvm_irqchip_add_irq/msi_route
again.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 8 ++++----
kvm-stub.c | 4 ++++
kvm.h | 1 +
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index f45b852..e3ffc91 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -955,19 +955,19 @@ int kvm_irqchip_commit_routes(KVMState *s)
return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
}
-static void kvm_release_gsi(KVMState *s, int gsi)
+void kvm_irqchip_release_virq(KVMState *s, int virq)
{
struct kvm_irq_routing_entry *e;
int i;
for (i = 0; i < s->irq_routes->nr; i++) {
e = &s->irq_routes->entries[i];
- if (e->gsi == gsi) {
+ if (e->gsi == virq) {
s->irq_routes->nr--;
*e = s->irq_routes->entries[s->irq_routes->nr];
}
}
- clear_gsi(s, gsi);
+ clear_gsi(s, virq);
}
static unsigned int kvm_hash_msi(uint32_t data)
@@ -984,7 +984,7 @@ static void kvm_flush_dynamic_msi_routes(KVMState *s)
for (hash = 0; hash < KVM_MSI_HASHTAB_SIZE; hash++) {
QTAILQ_FOREACH_SAFE(route, &s->msi_hashtab[hash], entry, next) {
- kvm_release_gsi(s, route->kroute.gsi);
+ kvm_irqchip_release_virq(s, route->kroute.gsi);
QTAILQ_REMOVE(&s->msi_hashtab[hash], route, entry);
g_free(route);
}
diff --git a/kvm-stub.c b/kvm-stub.c
index db3a7dc..ec351d9 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -136,3 +136,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
{
return -ENOSYS;
}
+
+void kvm_irqchip_release_virq(KVMState *s, int virq)
+{
+}
diff --git a/kvm.h b/kvm.h
index 67df1f1..1779e73 100644
--- a/kvm.h
+++ b/kvm.h
@@ -215,4 +215,5 @@ int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign,
int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
+void kvm_irqchip_release_virq(KVMState *s, int virq);
#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 07/11] kvm: Make kvm_irqchip_commit_routes an internal service
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (5 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 06/11] kvm: Publicize kvm_release_gsi as kvm_irqchip_release_virq Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 08/11] kvm: Introduce kvm_irqchip_add/remove_irqfd Jan Kiszka
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Automatically commit route changes after kvm_add_routing_entry and
kvm_irqchip_release_virq. There is no performance relevant use case for
which collecting multiple route changes is beneficial. This makes
kvm_irqchip_commit_routes an internal service which assert()s that the
corresponding IOCTL will always succeed.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/pc_piix.c | 6 +-----
kvm-all.c | 26 ++++++++++++++------------
kvm.h | 1 -
3 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c17f906..044dfcb 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -56,7 +56,7 @@ static void kvm_piix3_setup_irq_routing(bool pci_enabled)
{
#ifdef CONFIG_KVM
KVMState *s = kvm_state;
- int ret, i;
+ int i;
if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
for (i = 0; i < 8; ++i) {
@@ -77,10 +77,6 @@ static void kvm_piix3_setup_irq_routing(bool pci_enabled)
}
}
}
- ret = kvm_irqchip_commit_routes(s);
- if (ret < 0) {
- hw_error("KVM IRQ routing setup failed");
- }
}
#endif /* CONFIG_KVM */
}
diff --git a/kvm-all.c b/kvm-all.c
index e3ffc91..24027a4 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -908,6 +908,15 @@ static void kvm_init_irq_routing(KVMState *s)
kvm_arch_init_irq_routing(s);
}
+static void kvm_irqchip_commit_routes(KVMState *s)
+{
+ int ret;
+
+ s->irq_routes->flags = 0;
+ ret = kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
+ assert(ret == 0);
+}
+
static void kvm_add_routing_entry(KVMState *s,
struct kvm_irq_routing_entry *entry)
{
@@ -933,6 +942,8 @@ static void kvm_add_routing_entry(KVMState *s,
new->u = entry->u;
set_gsi(s, entry->gsi);
+
+ kvm_irqchip_commit_routes(s);
}
void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin)
@@ -949,12 +960,6 @@ void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin)
kvm_add_routing_entry(s, &e);
}
-int kvm_irqchip_commit_routes(KVMState *s)
-{
- s->irq_routes->flags = 0;
- return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes);
-}
-
void kvm_irqchip_release_virq(KVMState *s, int virq)
{
struct kvm_irq_routing_entry *e;
@@ -968,6 +973,8 @@ void kvm_irqchip_release_virq(KVMState *s, int virq)
}
}
clear_gsi(s, virq);
+
+ kvm_irqchip_commit_routes(s);
}
static unsigned int kvm_hash_msi(uint32_t data)
@@ -1049,7 +1056,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
route = kvm_lookup_msi_route(s, msg);
if (!route) {
- int gsi, ret;
+ int gsi;
gsi = kvm_get_pseudo_gsi(s);
if (gsi < 0) {
@@ -1068,11 +1075,6 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
QTAILQ_INSERT_TAIL(&s->msi_hashtab[kvm_hash_msi(msg.data)], route,
entry);
-
- ret = kvm_irqchip_commit_routes(s);
- if (ret < 0) {
- return ret;
- }
}
assert(route->kroute.type == KVM_IRQ_ROUTING_MSI);
diff --git a/kvm.h b/kvm.h
index 1779e73..f0d0c53 100644
--- a/kvm.h
+++ b/kvm.h
@@ -135,7 +135,6 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level);
int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg);
void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin);
-int kvm_irqchip_commit_routes(KVMState *s);
void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 08/11] kvm: Introduce kvm_irqchip_add/remove_irqfd
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (6 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 07/11] kvm: Make kvm_irqchip_commit_routes an internal service Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 09/11] kvm: Enable use of kvm_irqchip_in_kernel in hwlib code Jan Kiszka
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Add services to associate an eventfd file descriptor as input with an
IRQ line as output. Such a line can be an input pin of an in-kernel
irqchip or a virtual line returned by kvm_irqchip_add_route.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-all.c | 30 ++++++++++++++++++++++++++++++
kvm-stub.c | 10 ++++++++++
kvm.h | 3 +++
3 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/kvm-all.c b/kvm-all.c
index 24027a4..4d2dbc6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1108,6 +1108,21 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
return gsi;
}
+static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
+{
+ struct kvm_irqfd irqfd = {
+ .fd = fd,
+ .gsi = virq,
+ .flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
+ };
+
+ if (!kvm_irqchip_in_kernel()) {
+ return -ENOSYS;
+ }
+
+ return kvm_vm_ioctl(s, KVM_IRQFD, &irqfd);
+}
+
#else /* !KVM_CAP_IRQ_ROUTING */
static void kvm_init_irq_routing(KVMState *s)
@@ -1123,8 +1138,23 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
{
abort();
}
+
+static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
+{
+ abort();
+}
#endif /* !KVM_CAP_IRQ_ROUTING */
+int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq)
+{
+ return kvm_irqchip_assign_irqfd(s, fd, virq, true);
+}
+
+int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq)
+{
+ return kvm_irqchip_assign_irqfd(s, fd, virq, false);
+}
+
static int kvm_irqchip_create(KVMState *s)
{
QemuOptsList *list = qemu_find_opts("machine");
diff --git a/kvm-stub.c b/kvm-stub.c
index ec351d9..b4cf03f 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -140,3 +140,13 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
void kvm_irqchip_release_virq(KVMState *s, int virq)
{
}
+
+int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq)
+{
+ return -ENOSYS;
+}
+
+int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq)
+{
+ return -ENOSYS;
+}
diff --git a/kvm.h b/kvm.h
index f0d0c53..9c7b0ea 100644
--- a/kvm.h
+++ b/kvm.h
@@ -215,4 +215,7 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
void kvm_irqchip_release_virq(KVMState *s, int virq);
+
+int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq);
+int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq);
#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 09/11] kvm: Enable use of kvm_irqchip_in_kernel in hwlib code
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (7 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 08/11] kvm: Introduce kvm_irqchip_add/remove_irqfd Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 10/11] msix: Add msix_nr_vectors_allocated Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 11/11] virtio/vhost: Add support for KVM in-kernel MSI injection Jan Kiszka
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Provide a dummy kvm_kernel_irqchip so that kvm_irqchip_in_kernel can be
used by code that is not under CONFIG_KVM protection.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
kvm-stub.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kvm-stub.c b/kvm-stub.c
index b4cf03f..ec9a364 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -18,6 +18,7 @@
#include "kvm.h"
KVMState *kvm_state;
+bool kvm_kernel_irqchip;
int kvm_init_vcpu(CPUArchState *env)
{
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 10/11] msix: Add msix_nr_vectors_allocated
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (8 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 09/11] kvm: Enable use of kvm_irqchip_in_kernel in hwlib code Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 11/11] virtio/vhost: Add support for KVM in-kernel MSI injection Jan Kiszka
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Analogously to msi_nr_vectors_allocated, add a service for MSI-X. Will
be used by the virtio-pci layer.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/msix.c | 5 +++++
hw/msix.h | 2 ++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index c6968aa..2114b99 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -447,6 +447,11 @@ void msix_unuse_all_vectors(PCIDevice *dev)
msix_free_irq_entries(dev);
}
+unsigned int msix_nr_vectors_allocated(const PCIDevice *dev)
+{
+ return dev->msix_entries_nr;
+}
+
static int msix_set_notifier_for_vector(PCIDevice *dev, unsigned int vector)
{
MSIMessage msg;
diff --git a/hw/msix.h b/hw/msix.h
index f33f18b..50aee82 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -13,6 +13,8 @@ void msix_write_config(PCIDevice *pci_dev, uint32_t address,
int msix_uninit(PCIDevice *d, MemoryRegion *bar);
+unsigned int msix_nr_vectors_allocated(const PCIDevice *dev);
+
void msix_save(PCIDevice *dev, QEMUFile *f);
void msix_load(PCIDevice *dev, QEMUFile *f);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC][PATCH 11/11] virtio/vhost: Add support for KVM in-kernel MSI injection
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
` (9 preceding siblings ...)
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 10/11] msix: Add msix_nr_vectors_allocated Jan Kiszka
@ 2012-05-14 21:07 ` Jan Kiszka
10 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-14 21:07 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
Make use of the new vector notifier to track changes of the MSI-X
configuration of virtio PCI devices. On enabling events, we establish
the required virtual IRQ to MSI-X message route and link the signaling
eventfd file descriptor to this vIRQ line. That way, vhost-generated
interrupts can be directly delivered to an in-kernel MSI-X consumer like
the x86 APIC.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
hw/virtio-pci.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-pci.h | 6 +++
2 files changed, 132 insertions(+), 0 deletions(-)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 4a4413d..01f5b92 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -24,6 +24,7 @@
#include "virtio-scsi.h"
#include "pci.h"
#include "qemu-error.h"
+#include "msi.h"
#include "msix.h"
#include "net.h"
#include "loader.h"
@@ -539,6 +540,107 @@ static void virtio_pci_guest_notifier_read(void *opaque)
}
}
+static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
+ unsigned int queue_no,
+ unsigned int vector,
+ MSIMessage msg)
+{
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+ int fd, ret;
+
+ fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq));
+
+ if (irqfd->users == 0) {
+ ret = kvm_irqchip_add_msi_route(kvm_state, msg);
+ if (ret < 0) {
+ return ret;
+ }
+ irqfd->virq = ret;
+ }
+ irqfd->users++;
+
+ ret = kvm_irqchip_add_irqfd(kvm_state, fd, irqfd->virq);
+ if (ret < 0) {
+ if (--irqfd->users == 0) {
+ kvm_irqchip_release_virq(kvm_state, irqfd->virq);
+ }
+ return ret;
+ }
+
+ qemu_set_fd_handler(fd, NULL, NULL, NULL);
+
+ return 0;
+}
+
+static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
+ unsigned int queue_no,
+ unsigned int vector)
+{
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+ int fd, ret;
+
+ fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vq));
+
+ ret = kvm_irqchip_remove_irqfd(kvm_state, fd, irqfd->virq);
+ assert(ret == 0);
+
+ if (--irqfd->users == 0) {
+ kvm_irqchip_release_virq(kvm_state, irqfd->virq);
+ }
+
+ qemu_set_fd_handler(fd, virtio_pci_guest_notifier_read, NULL, vq);
+}
+
+static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
+ MSIMessage msg)
+{
+ VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
+ VirtIODevice *vdev = proxy->vdev;
+ int ret, queue_no;
+
+ for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ break;
+ }
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector, msg);
+ if (ret < 0) {
+ goto undo;
+ }
+ }
+ return 0;
+
+undo:
+ while (--queue_no >= 0) {
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
+ }
+ return ret;
+}
+
+static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
+{
+ VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
+ VirtIODevice *vdev = proxy->vdev;
+ int queue_no;
+
+ for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ break;
+ }
+ if (virtio_queue_vector(vdev, queue_no) != vector) {
+ continue;
+ }
+ kvm_virtio_pci_vq_vector_release(proxy, queue_no, vector);
+ }
+}
+
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
@@ -555,6 +657,9 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
} else {
qemu_set_fd_handler(event_notifier_get_fd(notifier),
NULL, NULL, NULL);
+ /* Test and clear notifier before closing it,
+ * in case poll callback didn't have time to run. */
+ virtio_pci_guest_notifier_read(vq);
event_notifier_cleanup(notifier);
}
@@ -573,6 +678,13 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
VirtIODevice *vdev = proxy->vdev;
int r, n;
+ /* Must unset vector notifier while guest notifier is still assigned */
+ if (kvm_irqchip_in_kernel() && !assign) {
+ msix_unset_vector_notifiers(&proxy->pci_dev);
+ g_free(proxy->vector_irqfd);
+ proxy->vector_irqfd = NULL;
+ }
+
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
if (!virtio_queue_get_num(vdev, n)) {
break;
@@ -584,10 +696,24 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
}
}
+ /* Must set vector notifier after guest notifier has been assigned */
+ if (kvm_irqchip_in_kernel() && assign) {
+ proxy->vector_irqfd =
+ g_malloc0(sizeof(*proxy->vector_irqfd) *
+ msix_nr_vectors_allocated(&proxy->pci_dev));
+ r = msix_set_vector_notifiers(&proxy->pci_dev,
+ kvm_virtio_pci_vector_use,
+ kvm_virtio_pci_vector_release);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+
return 0;
assign_error:
/* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
+ assert(assign);
while (--n >= 0) {
virtio_pci_set_guest_notifier(opaque, n, !assign);
}
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index e560428..8d28d4b 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -25,6 +25,11 @@
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
typedef struct {
+ int virq;
+ unsigned int users;
+} VirtIOIRQFD;
+
+typedef struct {
PCIDevice pci_dev;
VirtIODevice *vdev;
MemoryRegion bar;
@@ -44,6 +49,7 @@ typedef struct {
VirtIOSCSIConf scsi;
bool ioeventfd_disabled;
bool ioeventfd_started;
+ VirtIOIRQFD *vector_irqfd;
} VirtIOPCIProxy;
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 12/11] msix: Trigger vector mask update check after vmload
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 03/11] msix: Introduce vector notifiers Jan Kiszka
@ 2012-05-15 13:31 ` Jan Kiszka
0 siblings, 0 replies; 13+ messages in thread
From: Jan Kiszka @ 2012-05-15 13:31 UTC (permalink / raw)
To: Avi Kivity, Marcelo Tosatti; +Cc: qemu-devel, kvm, Michael S. Tsirkin
In case we load a PCI device with active vectors, we have to process
them and invoke potential notifiers.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
This amends the QEMU series but should be equally relevant as bug fix
for qemu-kvm.
hw/msix.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/hw/msix.c b/hw/msix.c
index 2114b99..59c7a83 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -351,6 +351,7 @@ void msix_save(PCIDevice *dev, QEMUFile *f)
void msix_load(PCIDevice *dev, QEMUFile *f)
{
unsigned n = dev->msix_entries_nr;
+ unsigned int vector;
if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) {
return;
@@ -360,6 +361,10 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
qemu_get_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
msix_update_function_masked(dev);
+
+ for (vector = 0; vector < n; vector++) {
+ msix_handle_mask_update(dev, vector, true);
+ }
}
/* Does device support MSI-X? */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-05-15 13:32 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-14 21:07 [Qemu-devel] [RFC][PATCH 00/11] uq/master: irqfd-based interrupt injection for virtio/vhost Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 01/11] msix: Factor out msix_get_message Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 02/11] msix: Invoke msix_handle_mask_update on msix_mask_all Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 03/11] msix: Introduce vector notifiers Jan Kiszka
2012-05-15 13:31 ` [Qemu-devel] [PATCH 12/11] msix: Trigger vector mask update check after vmload Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 04/11] kvm: Rename kvm_irqchip_add_route to kvm_irqchip_add_irq_route Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 05/11] kvm: Introduce kvm_irqchip_add_msi_route Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 06/11] kvm: Publicize kvm_release_gsi as kvm_irqchip_release_virq Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 07/11] kvm: Make kvm_irqchip_commit_routes an internal service Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 08/11] kvm: Introduce kvm_irqchip_add/remove_irqfd Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 09/11] kvm: Enable use of kvm_irqchip_in_kernel in hwlib code Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 10/11] msix: Add msix_nr_vectors_allocated Jan Kiszka
2012-05-14 21:07 ` [Qemu-devel] [RFC][PATCH 11/11] virtio/vhost: Add support for KVM in-kernel MSI injection Jan Kiszka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).