kvm-irqchip: x86: add msi route notify fn
One more IEC notifier is added to let msi routes know about the IEC changes. When interrupt invalidation happens, all registered msi routes will be updated for all PCI devices. Since both vfio and vhost are possible gsi route consumers, this patch will go one step further to keep them safe in split irqchip mode and when irqfd is enabled. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> [move trace-events lines into target-i386/trace-events] Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
38d87493f3
commit
e1d4fb2de5
15
hw/pci/pci.c
15
hw/pci/pci.c
|
@ -2596,6 +2596,21 @@ PCIDevice *pci_get_function_0(PCIDevice *pci_dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
|
||||||
|
{
|
||||||
|
MSIMessage msg;
|
||||||
|
if (msix_enabled(dev)) {
|
||||||
|
msg = msix_get_message(dev, vector);
|
||||||
|
} else if (msi_enabled(dev)) {
|
||||||
|
msg = msi_get_message(dev, vector);
|
||||||
|
} else {
|
||||||
|
/* Should never happen */
|
||||||
|
error_report("%s: unknown interrupt type", __func__);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo pci_device_type_info = {
|
static const TypeInfo pci_device_type_info = {
|
||||||
.name = TYPE_PCI_DEVICE,
|
.name = TYPE_PCI_DEVICE,
|
||||||
.parent = TYPE_DEVICE,
|
.parent = TYPE_DEVICE,
|
||||||
|
|
|
@ -805,4 +805,6 @@ extern const VMStateDescription vmstate_pci_device;
|
||||||
.offset = vmstate_offset_pointer(_state, _field, PCIDevice), \
|
.offset = vmstate_offset_pointer(_state, _field, PCIDevice), \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
kvm-all.c
10
kvm-all.c
|
@ -1246,15 +1246,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
|
||||||
MSIMessage msg = {0, 0};
|
MSIMessage msg = {0, 0};
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if (msix_enabled(dev)) {
|
msg = pci_get_msi_message(dev, vector);
|
||||||
msg = msix_get_message(dev, vector);
|
|
||||||
} else if (msi_enabled(dev)) {
|
|
||||||
msg = msi_get_message(dev, vector);
|
|
||||||
} else {
|
|
||||||
/* Should never happen */
|
|
||||||
error_report("%s: unknown interrupt type", __func__);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_gsi_direct_mapping()) {
|
if (kvm_gsi_direct_mapping()) {
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "hw/i386/apic_internal.h"
|
#include "hw/i386/apic_internal.h"
|
||||||
#include "hw/i386/apic-msidef.h"
|
#include "hw/i386/apic-msidef.h"
|
||||||
#include "hw/i386/intel_iommu.h"
|
#include "hw/i386/intel_iommu.h"
|
||||||
|
#include "hw/i386/x86-iommu.h"
|
||||||
|
|
||||||
#include "exec/ioport.h"
|
#include "exec/ioport.h"
|
||||||
#include "standard-headers/asm-x86/hyperv.h"
|
#include "standard-headers/asm-x86/hyperv.h"
|
||||||
|
@ -3413,9 +3414,26 @@ struct MSIRouteEntry {
|
||||||
static QLIST_HEAD(, MSIRouteEntry) msi_route_list = \
|
static QLIST_HEAD(, MSIRouteEntry) msi_route_list = \
|
||||||
QLIST_HEAD_INITIALIZER(msi_route_list);
|
QLIST_HEAD_INITIALIZER(msi_route_list);
|
||||||
|
|
||||||
|
static void kvm_update_msi_routes_all(void *private, bool global,
|
||||||
|
uint32_t index, uint32_t mask)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
MSIRouteEntry *entry;
|
||||||
|
MSIMessage msg;
|
||||||
|
/* TODO: explicit route update */
|
||||||
|
QLIST_FOREACH(entry, &msi_route_list, list) {
|
||||||
|
cnt++;
|
||||||
|
msg = pci_get_msi_message(entry->dev, entry->vector);
|
||||||
|
kvm_irqchip_update_msi_route(kvm_state, entry->virq,
|
||||||
|
msg, entry->dev);
|
||||||
|
}
|
||||||
|
trace_kvm_x86_update_msi_routes(cnt);
|
||||||
|
}
|
||||||
|
|
||||||
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
|
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
|
||||||
int vector, PCIDevice *dev)
|
int vector, PCIDevice *dev)
|
||||||
{
|
{
|
||||||
|
static bool notify_list_inited = false;
|
||||||
MSIRouteEntry *entry;
|
MSIRouteEntry *entry;
|
||||||
|
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
|
@ -3432,6 +3450,18 @@ int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
|
||||||
QLIST_INSERT_HEAD(&msi_route_list, entry, list);
|
QLIST_INSERT_HEAD(&msi_route_list, entry, list);
|
||||||
|
|
||||||
trace_kvm_x86_add_msi_route(route->gsi);
|
trace_kvm_x86_add_msi_route(route->gsi);
|
||||||
|
|
||||||
|
if (!notify_list_inited) {
|
||||||
|
/* For the first time we do add route, add ourselves into
|
||||||
|
* IOMMU's IEC notify list if needed. */
|
||||||
|
X86IOMMUState *iommu = x86_iommu_get_default();
|
||||||
|
if (iommu) {
|
||||||
|
x86_iommu_iec_register_notifier(iommu,
|
||||||
|
kvm_update_msi_routes_all,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
notify_list_inited = true;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" PRIu32
|
kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" PRIu32
|
||||||
kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
|
kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
|
||||||
kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
|
kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
|
||||||
|
kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
|
||||||
|
|
Loading…
Reference in a new issue