@@ -153,6 +153,7 @@ trace-events-y += hw/alpha/trace-events
trace-events-y += ui/trace-events
trace-events-y += audio/trace-events
trace-events-y += net/trace-events
+trace-events-y += target-i386/trace-events
trace-events-y += target-sparc/trace-events
trace-events-y += target-s390x/trace-events
trace-events-y += target-ppc/trace-events
@@ -2167,6 +2167,12 @@ do_not_translate:
return 0;
}
+static int vtd_int_remap(X86IOMMUState *iommu, MSIMessage *src,
+ MSIMessage *dst, uint16_t sid)
+{
+ return vtd_interrupt_remap_msi(INTEL_IOMMU_DEVICE(iommu), src, dst);
+}
+
static MemTxResult vtd_mem_ir_read(void *opaque, hwaddr addr,
uint64_t *data, unsigned size,
MemTxAttrs attrs)
@@ -2412,6 +2418,7 @@ static void vtd_class_init(ObjectClass *klass, void *data)
dc->hotpluggable = false;
x86_class->realize = vtd_realize;
x86_class->find_add_as = vtd_find_add_as;
+ x86_class->int_remap = vtd_int_remap;
}
static const TypeInfo vtd_info = {
@@ -26,6 +26,7 @@
#include "hw/i386/x86-iommu.h"
#include "hw/i386/ioapic.h"
#include "hw/pci/msi.h"
+#include "hw/sysbus.h"
#define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
#define INTEL_IOMMU_DEVICE(obj) \
@@ -22,6 +22,7 @@
#include "hw/sysbus.h"
#include "exec/memory.h"
+#include "hw/pci/pci.h"
#define TYPE_X86_IOMMU_DEVICE ("x86-iommu")
#define X86_IOMMU_DEVICE(obj) \
@@ -32,6 +33,7 @@
OBJECT_GET_CLASS(X86IOMMUClass, obj, TYPE_X86_IOMMU_DEVICE)
#define X86_IOMMU_PCI_DEVFN_MAX 256
+#define X86_IOMMU_SID_INVALID (0xffff)
typedef struct X86IOMMUState X86IOMMUState;
typedef struct X86IOMMUClass X86IOMMUClass;
@@ -42,6 +44,9 @@ struct X86IOMMUClass {
DeviceRealize realize;
/* Find/Add IOMMU address space for specific PCI device */
AddressSpace *(*find_add_as)(X86IOMMUState *s, PCIBus *bus, int devfn);
+ /* MSI-based interrupt remapping */
+ int (*int_remap)(X86IOMMUState *iommu, MSIMessage *src,
+ MSIMessage *dst, uint16_t sid);
};
struct X86IOMMUState {
@@ -35,6 +35,7 @@
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
#include "hw/i386/apic-msidef.h"
+#include "hw/i386/intel_iommu.h"
#include "exec/ioport.h"
#include "standard-headers/asm-x86/hyperv.h"
@@ -42,6 +43,7 @@
#include "hw/pci/msi.h"
#include "migration/migration.h"
#include "exec/memattrs.h"
+#include "trace.h"
//#define DEBUG_KVM
@@ -3323,6 +3325,31 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id)
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint64_t address, uint32_t data, PCIDevice *dev)
{
+ X86IOMMUState *iommu = x86_iommu_get_default();
+
+ if (iommu) {
+ int ret;
+ MSIMessage src, dst;
+ X86IOMMUClass *class = X86_IOMMU_GET_CLASS(iommu);
+
+ src.address = route->u.msi.address_hi;
+ src.address <<= VTD_MSI_ADDR_HI_SHIFT;
+ src.address |= route->u.msi.address_lo;
+ src.data = route->u.msi.data;
+
+ ret = class->int_remap(iommu, &src, &dst, dev ? \
+ pci_requester_id(dev) : \
+ X86_IOMMU_SID_INVALID);
+ if (ret) {
+ trace_kvm_x86_fixup_msi_error(route->gsi);
+ return 1;
+ }
+
+ route->u.msi.address_hi = dst.address >> VTD_MSI_ADDR_HI_SHIFT;
+ route->u.msi.address_lo = dst.address & VTD_MSI_ADDR_LO_MASK;
+ route->u.msi.data = dst.data;
+ }
+
return 0;
}
new file mode 100644
@@ -0,0 +1,4 @@
+# See docs/trace-events.txt for syntax documentation.
+
+# target-i386/kvm.c
+kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" PRIu32