diff options
author | Peter Xu <peterx@redhat.com> | 2016-07-14 13:56:22 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2016-07-20 19:31:04 +0300 |
commit | 651e4cefeee8e388919e51f4e299033ab2a8b87d (patch) | |
tree | c9eb2dedbfb664eb17b89b2b9983febd081ee20f /include | |
parent | a4ca297e848a3eda39acaec6941fed4eb35916df (diff) |
intel_iommu: Add support for PCI MSI remap
This patch enables interrupt remapping for PCI devices.
To play the trick, one memory region "iommu_ir" is added as child region
of the original iommu memory region, covering range 0xfeeXXXXX (which is
the address range for APIC). All the writes to this range will be taken
as MSI, and translation is carried out only when IR is enabled.
Idea suggested by Paolo Bonzini.
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>
Diffstat (limited to 'include')
-rw-r--r-- | include/hw/i386/intel_iommu.h | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 260aa8ebf3..cdbbddd79e 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -24,6 +24,8 @@ #include "hw/qdev.h" #include "sysemu/dma.h" #include "hw/i386/x86-iommu.h" +#include "hw/i386/ioapic.h" +#include "hw/pci/msi.h" #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" #define INTEL_IOMMU_DEVICE(obj) \ @@ -46,6 +48,10 @@ #define DMAR_REPORT_F_INTR (1) +#define VTD_MSI_ADDR_HI_MASK (0xffffffff00000000ULL) +#define VTD_MSI_ADDR_HI_SHIFT (32) +#define VTD_MSI_ADDR_LO_MASK (0x00000000ffffffffULL) + typedef struct VTDContextEntry VTDContextEntry; typedef struct VTDContextCacheEntry VTDContextCacheEntry; typedef struct IntelIOMMUState IntelIOMMUState; @@ -54,6 +60,8 @@ typedef struct VTDIOTLBEntry VTDIOTLBEntry; typedef struct VTDBus VTDBus; typedef union VTD_IRTE VTD_IRTE; typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress; +typedef struct VTDIrq VTDIrq; +typedef struct VTD_MSIMessage VTD_MSIMessage; /* Context-Entry */ struct VTDContextEntry { @@ -74,6 +82,7 @@ struct VTDAddressSpace { uint8_t devfn; AddressSpace as; MemoryRegion iommu; + MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */ IntelIOMMUState *iommu_state; VTDContextCacheEntry context_cache_entry; }; @@ -161,6 +170,63 @@ union VTD_IR_MSIAddress { uint32_t data; }; +/* Generic IRQ entry information */ +struct VTDIrq { + /* Used by both IOAPIC/MSI interrupt remapping */ + uint8_t trigger_mode; + uint8_t vector; + uint8_t delivery_mode; + uint32_t dest; + uint8_t dest_mode; + + /* only used by MSI interrupt remapping */ + uint8_t redir_hint; + uint8_t msi_addr_last_bits; +}; + +struct VTD_MSIMessage { + union { + struct { +#ifdef HOST_WORDS_BIGENDIAN + uint32_t __addr_head:12; /* 0xfee */ + uint32_t dest:8; + uint32_t __reserved:8; + uint32_t redir_hint:1; + uint32_t dest_mode:1; + uint32_t __not_used:2; +#else + uint32_t __not_used:2; + uint32_t dest_mode:1; + uint32_t redir_hint:1; + uint32_t __reserved:8; + uint32_t dest:8; + uint32_t __addr_head:12; /* 0xfee */ +#endif + uint32_t __addr_hi:32; + } QEMU_PACKED; + uint64_t msi_addr; + }; + union { + struct { +#ifdef HOST_WORDS_BIGENDIAN + uint16_t trigger_mode:1; + uint16_t level:1; + uint16_t __resved:3; + uint16_t delivery_mode:3; + uint16_t vector:8; +#else + uint16_t vector:8; + uint16_t delivery_mode:3; + uint16_t __resved:3; + uint16_t level:1; + uint16_t trigger_mode:1; +#endif + uint16_t __resved1:16; + } QEMU_PACKED; + uint32_t msi_data; + }; +}; + /* When IR is enabled, all MSI/MSI-X data bits should be zero */ #define VTD_IR_MSI_DATA (0) |