intel-iommu: introduce Intel IOMMU (VT-d) emulation
Add support for emulating Intel IOMMU according to the VT-d specification for the q35 chipset machine. Implement the logics for DMAR (DMA remapping) without PASID support. The emulation supports register-based invalidation and primary fault logging. Signed-off-by: Le Tan <tamlokveer@gmail.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									8d7b8cb9c2
								
							
						
					
					
						commit
						1da12ec4c8
					
				| @ -2,6 +2,7 @@ obj-$(CONFIG_KVM) += kvm/ | ||||
| obj-y += multiboot.o smbios.o | ||||
| obj-y += pc.o pc_piix.o pc_q35.o | ||||
| obj-y += pc_sysfw.o | ||||
| obj-y += intel_iommu.o | ||||
| obj-$(CONFIG_XEN) += ../xenpv/ xen/ | ||||
| 
 | ||||
| obj-y += kvmvapic.o | ||||
|  | ||||
							
								
								
									
										1257
									
								
								hw/i386/intel_iommu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1257
									
								
								hw/i386/intel_iommu.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										333
									
								
								hw/i386/intel_iommu_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								hw/i386/intel_iommu_internal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,333 @@ | ||||
| /*
 | ||||
|  * QEMU emulation of an Intel IOMMU (VT-d) | ||||
|  *   (DMA Remapping device) | ||||
|  * | ||||
|  * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com> | ||||
|  * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
| 
 | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
| 
 | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * Lots of defines copied from kernel/include/linux/intel-iommu.h: | ||||
|  *   Copyright (C) 2006-2008 Intel Corporation | ||||
|  *   Author: Ashok Raj <ashok.raj@intel.com> | ||||
|  *   Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef HW_I386_INTEL_IOMMU_INTERNAL_H | ||||
| #define HW_I386_INTEL_IOMMU_INTERNAL_H | ||||
| #include "hw/i386/intel_iommu.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Intel IOMMU register specification | ||||
|  */ | ||||
| #define DMAR_VER_REG            0x0  /* Arch version supported by this IOMMU */ | ||||
| #define DMAR_CAP_REG            0x8  /* Hardware supported capabilities */ | ||||
| #define DMAR_CAP_REG_HI         0xc  /* High 32-bit of DMAR_CAP_REG */ | ||||
| #define DMAR_ECAP_REG           0x10 /* Extended capabilities supported */ | ||||
| #define DMAR_ECAP_REG_HI        0X14 | ||||
| #define DMAR_GCMD_REG           0x18 /* Global command */ | ||||
| #define DMAR_GSTS_REG           0x1c /* Global status */ | ||||
| #define DMAR_RTADDR_REG         0x20 /* Root entry table */ | ||||
| #define DMAR_RTADDR_REG_HI      0X24 | ||||
| #define DMAR_CCMD_REG           0x28 /* Context command */ | ||||
| #define DMAR_CCMD_REG_HI        0x2c | ||||
| #define DMAR_FSTS_REG           0x34 /* Fault status */ | ||||
| #define DMAR_FECTL_REG          0x38 /* Fault control */ | ||||
| #define DMAR_FEDATA_REG         0x3c /* Fault event interrupt data */ | ||||
| #define DMAR_FEADDR_REG         0x40 /* Fault event interrupt addr */ | ||||
| #define DMAR_FEUADDR_REG        0x44 /* Upper address */ | ||||
| #define DMAR_AFLOG_REG          0x58 /* Advanced fault control */ | ||||
| #define DMAR_AFLOG_REG_HI       0X5c | ||||
| #define DMAR_PMEN_REG           0x64 /* Enable protected memory region */ | ||||
| #define DMAR_PLMBASE_REG        0x68 /* PMRR low addr */ | ||||
| #define DMAR_PLMLIMIT_REG       0x6c /* PMRR low limit */ | ||||
| #define DMAR_PHMBASE_REG        0x70 /* PMRR high base addr */ | ||||
| #define DMAR_PHMBASE_REG_HI     0X74 | ||||
| #define DMAR_PHMLIMIT_REG       0x78 /* PMRR high limit */ | ||||
| #define DMAR_PHMLIMIT_REG_HI    0x7c | ||||
| #define DMAR_IQH_REG            0x80 /* Invalidation queue head */ | ||||
| #define DMAR_IQH_REG_HI         0X84 | ||||
| #define DMAR_IQT_REG            0x88 /* Invalidation queue tail */ | ||||
| #define DMAR_IQT_REG_HI         0X8c | ||||
| #define DMAR_IQA_REG            0x90 /* Invalidation queue addr */ | ||||
| #define DMAR_IQA_REG_HI         0x94 | ||||
| #define DMAR_ICS_REG            0x9c /* Invalidation complete status */ | ||||
| #define DMAR_IRTA_REG           0xb8 /* Interrupt remapping table addr */ | ||||
| #define DMAR_IRTA_REG_HI        0xbc | ||||
| #define DMAR_IECTL_REG          0xa0 /* Invalidation event control */ | ||||
| #define DMAR_IEDATA_REG         0xa4 /* Invalidation event data */ | ||||
| #define DMAR_IEADDR_REG         0xa8 /* Invalidation event address */ | ||||
| #define DMAR_IEUADDR_REG        0xac /* Invalidation event address */ | ||||
| #define DMAR_PQH_REG            0xc0 /* Page request queue head */ | ||||
| #define DMAR_PQH_REG_HI         0xc4 | ||||
| #define DMAR_PQT_REG            0xc8 /* Page request queue tail*/ | ||||
| #define DMAR_PQT_REG_HI         0xcc | ||||
| #define DMAR_PQA_REG            0xd0 /* Page request queue address */ | ||||
| #define DMAR_PQA_REG_HI         0xd4 | ||||
| #define DMAR_PRS_REG            0xdc /* Page request status */ | ||||
| #define DMAR_PECTL_REG          0xe0 /* Page request event control */ | ||||
| #define DMAR_PEDATA_REG         0xe4 /* Page request event data */ | ||||
| #define DMAR_PEADDR_REG         0xe8 /* Page request event address */ | ||||
| #define DMAR_PEUADDR_REG        0xec /* Page event upper address */ | ||||
| #define DMAR_MTRRCAP_REG        0x100 /* MTRR capability */ | ||||
| #define DMAR_MTRRCAP_REG_HI     0x104 | ||||
| #define DMAR_MTRRDEF_REG        0x108 /* MTRR default type */ | ||||
| #define DMAR_MTRRDEF_REG_HI     0x10c | ||||
| 
 | ||||
| /* IOTLB registers */ | ||||
| #define DMAR_IOTLB_REG_OFFSET   0xf0 /* Offset to the IOTLB registers */ | ||||
| #define DMAR_IVA_REG            DMAR_IOTLB_REG_OFFSET /* Invalidate address */ | ||||
| #define DMAR_IVA_REG_HI         (DMAR_IVA_REG + 4) | ||||
| /* IOTLB invalidate register */ | ||||
| #define DMAR_IOTLB_REG          (DMAR_IOTLB_REG_OFFSET + 0x8) | ||||
| #define DMAR_IOTLB_REG_HI       (DMAR_IOTLB_REG + 4) | ||||
| 
 | ||||
| /* FRCD */ | ||||
| #define DMAR_FRCD_REG_OFFSET    0x220 /* Offset to the fault recording regs */ | ||||
| /* NOTICE: If you change the DMAR_FRCD_REG_NR, please remember to change the
 | ||||
|  * DMAR_REG_SIZE in include/hw/i386/intel_iommu.h. | ||||
|  * #define DMAR_REG_SIZE   (DMAR_FRCD_REG_OFFSET + 16 * DMAR_FRCD_REG_NR) | ||||
|  */ | ||||
| #define DMAR_FRCD_REG_NR        1ULL /* Num of fault recording regs */ | ||||
| 
 | ||||
| #define DMAR_FRCD_REG_0_0       0x220 /* The 0th fault recording regs */ | ||||
| #define DMAR_FRCD_REG_0_1       0x224 | ||||
| #define DMAR_FRCD_REG_0_2       0x228 | ||||
| #define DMAR_FRCD_REG_0_3       0x22c | ||||
| 
 | ||||
| /* Interrupt Address Range */ | ||||
| #define VTD_INTERRUPT_ADDR_FIRST    0xfee00000ULL | ||||
| #define VTD_INTERRUPT_ADDR_LAST     0xfeefffffULL | ||||
| 
 | ||||
| /* IOTLB_REG */ | ||||
| #define VTD_TLB_GLOBAL_FLUSH        (1ULL << 60) /* Global invalidation */ | ||||
| #define VTD_TLB_DSI_FLUSH           (2ULL << 60) /* Domain-selective */ | ||||
| #define VTD_TLB_PSI_FLUSH           (3ULL << 60) /* Page-selective */ | ||||
| #define VTD_TLB_FLUSH_GRANU_MASK    (3ULL << 60) | ||||
| #define VTD_TLB_GLOBAL_FLUSH_A      (1ULL << 57) | ||||
| #define VTD_TLB_DSI_FLUSH_A         (2ULL << 57) | ||||
| #define VTD_TLB_PSI_FLUSH_A         (3ULL << 57) | ||||
| #define VTD_TLB_FLUSH_GRANU_MASK_A  (3ULL << 57) | ||||
| #define VTD_TLB_IVT                 (1ULL << 63) | ||||
| 
 | ||||
| /* GCMD_REG */ | ||||
| #define VTD_GCMD_TE                 (1UL << 31) | ||||
| #define VTD_GCMD_SRTP               (1UL << 30) | ||||
| #define VTD_GCMD_SFL                (1UL << 29) | ||||
| #define VTD_GCMD_EAFL               (1UL << 28) | ||||
| #define VTD_GCMD_WBF                (1UL << 27) | ||||
| #define VTD_GCMD_QIE                (1UL << 26) | ||||
| #define VTD_GCMD_IRE                (1UL << 25) | ||||
| #define VTD_GCMD_SIRTP              (1UL << 24) | ||||
| #define VTD_GCMD_CFI                (1UL << 23) | ||||
| 
 | ||||
| /* GSTS_REG */ | ||||
| #define VTD_GSTS_TES                (1UL << 31) | ||||
| #define VTD_GSTS_RTPS               (1UL << 30) | ||||
| #define VTD_GSTS_FLS                (1UL << 29) | ||||
| #define VTD_GSTS_AFLS               (1UL << 28) | ||||
| #define VTD_GSTS_WBFS               (1UL << 27) | ||||
| #define VTD_GSTS_QIES               (1UL << 26) | ||||
| #define VTD_GSTS_IRES               (1UL << 25) | ||||
| #define VTD_GSTS_IRTPS              (1UL << 24) | ||||
| #define VTD_GSTS_CFIS               (1UL << 23) | ||||
| 
 | ||||
| /* CCMD_REG */ | ||||
| #define VTD_CCMD_ICC                (1ULL << 63) | ||||
| #define VTD_CCMD_GLOBAL_INVL        (1ULL << 61) | ||||
| #define VTD_CCMD_DOMAIN_INVL        (2ULL << 61) | ||||
| #define VTD_CCMD_DEVICE_INVL        (3ULL << 61) | ||||
| #define VTD_CCMD_CIRG_MASK          (3ULL << 61) | ||||
| #define VTD_CCMD_GLOBAL_INVL_A      (1ULL << 59) | ||||
| #define VTD_CCMD_DOMAIN_INVL_A      (2ULL << 59) | ||||
| #define VTD_CCMD_DEVICE_INVL_A      (3ULL << 59) | ||||
| #define VTD_CCMD_CAIG_MASK          (3ULL << 59) | ||||
| 
 | ||||
| /* RTADDR_REG */ | ||||
| #define VTD_RTADDR_RTT              (1ULL << 11) | ||||
| #define VTD_RTADDR_ADDR_MASK        (VTD_HAW_MASK ^ 0xfffULL) | ||||
| 
 | ||||
| /* ECAP_REG */ | ||||
| /* (offset >> 4) << 8 */ | ||||
| #define VTD_ECAP_IRO                (DMAR_IOTLB_REG_OFFSET << 4) | ||||
| #define VTD_ECAP_QI                 (1ULL << 1) | ||||
| 
 | ||||
| /* CAP_REG */ | ||||
| /* (offset >> 4) << 24 */ | ||||
| #define VTD_CAP_FRO                 (DMAR_FRCD_REG_OFFSET << 20) | ||||
| #define VTD_CAP_NFR                 ((DMAR_FRCD_REG_NR - 1) << 40) | ||||
| #define VTD_DOMAIN_ID_SHIFT         16  /* 16-bit domain id for 64K domains */ | ||||
| #define VTD_CAP_ND                  (((VTD_DOMAIN_ID_SHIFT - 4) / 2) & 7ULL) | ||||
| #define VTD_MGAW                    39  /* Maximum Guest Address Width */ | ||||
| #define VTD_CAP_MGAW                (((VTD_MGAW - 1) & 0x3fULL) << 16) | ||||
| 
 | ||||
| /* Supported Adjusted Guest Address Widths */ | ||||
| #define VTD_CAP_SAGAW_SHIFT         8 | ||||
| #define VTD_CAP_SAGAW_MASK          (0x1fULL << VTD_CAP_SAGAW_SHIFT) | ||||
|  /* 39-bit AGAW, 3-level page-table */ | ||||
| #define VTD_CAP_SAGAW_39bit         (0x2ULL << VTD_CAP_SAGAW_SHIFT) | ||||
|  /* 48-bit AGAW, 4-level page-table */ | ||||
| #define VTD_CAP_SAGAW_48bit         (0x4ULL << VTD_CAP_SAGAW_SHIFT) | ||||
| #define VTD_CAP_SAGAW               VTD_CAP_SAGAW_39bit | ||||
| 
 | ||||
| /* IQT_REG */ | ||||
| #define VTD_IQT_QT(val)             (((val) >> 4) & 0x7fffULL) | ||||
| 
 | ||||
| /* IQA_REG */ | ||||
| #define VTD_IQA_IQA_MASK            (VTD_HAW_MASK ^ 0xfffULL) | ||||
| #define VTD_IQA_QS                  0x7ULL | ||||
| 
 | ||||
| /* IQH_REG */ | ||||
| #define VTD_IQH_QH_SHIFT            4 | ||||
| #define VTD_IQH_QH_MASK             0x7fff0ULL | ||||
| 
 | ||||
| /* ICS_REG */ | ||||
| #define VTD_ICS_IWC                 1UL | ||||
| 
 | ||||
| /* IECTL_REG */ | ||||
| #define VTD_IECTL_IM                (1UL << 31) | ||||
| #define VTD_IECTL_IP                (1UL << 30) | ||||
| 
 | ||||
| /* FSTS_REG */ | ||||
| #define VTD_FSTS_FRI_MASK       0xff00UL | ||||
| #define VTD_FSTS_FRI(val)       ((((uint32_t)(val)) << 8) & VTD_FSTS_FRI_MASK) | ||||
| #define VTD_FSTS_IQE            (1UL << 4) | ||||
| #define VTD_FSTS_PPF            (1UL << 1) | ||||
| #define VTD_FSTS_PFO            1UL | ||||
| 
 | ||||
| /* FECTL_REG */ | ||||
| #define VTD_FECTL_IM            (1UL << 31) | ||||
| #define VTD_FECTL_IP            (1UL << 30) | ||||
| 
 | ||||
| /* Fault Recording Register */ | ||||
| /* For the high 64-bit of 128-bit */ | ||||
| #define VTD_FRCD_F              (1ULL << 63) | ||||
| #define VTD_FRCD_T              (1ULL << 62) | ||||
| #define VTD_FRCD_FR(val)        (((val) & 0xffULL) << 32) | ||||
| #define VTD_FRCD_SID_MASK       0xffffULL | ||||
| #define VTD_FRCD_SID(val)       ((val) & VTD_FRCD_SID_MASK) | ||||
| /* For the low 64-bit of 128-bit */ | ||||
| #define VTD_FRCD_FI(val)        ((val) & (((1ULL << VTD_MGAW) - 1) ^ 0xfffULL)) | ||||
| 
 | ||||
| /* DMA Remapping Fault Conditions */ | ||||
| typedef enum VTDFaultReason { | ||||
|     VTD_FR_RESERVED = 0,        /* Reserved for Advanced Fault logging */ | ||||
|     VTD_FR_ROOT_ENTRY_P = 1,    /* The Present(P) field of root-entry is 0 */ | ||||
|     VTD_FR_CONTEXT_ENTRY_P,     /* The Present(P) field of context-entry is 0 */ | ||||
|     VTD_FR_CONTEXT_ENTRY_INV,   /* Invalid programming of a context-entry */ | ||||
|     VTD_FR_ADDR_BEYOND_MGAW,    /* Input-address above (2^x-1) */ | ||||
|     VTD_FR_WRITE,               /* No write permission */ | ||||
|     VTD_FR_READ,                /* No read permission */ | ||||
|     /* Fail to access a second-level paging entry (not SL_PML4E) */ | ||||
|     VTD_FR_PAGING_ENTRY_INV, | ||||
|     VTD_FR_ROOT_TABLE_INV,      /* Fail to access a root-entry */ | ||||
|     VTD_FR_CONTEXT_TABLE_INV,   /* Fail to access a context-entry */ | ||||
|     /* Non-zero reserved field in a present root-entry */ | ||||
|     VTD_FR_ROOT_ENTRY_RSVD, | ||||
|     /* Non-zero reserved field in a present context-entry */ | ||||
|     VTD_FR_CONTEXT_ENTRY_RSVD, | ||||
|     /* Non-zero reserved field in a second-level paging entry with at lease one
 | ||||
|      * Read(R) and Write(W) or Execute(E) field is Set. | ||||
|      */ | ||||
|     VTD_FR_PAGING_ENTRY_RSVD, | ||||
|     /* Translation request or translated request explicitly blocked dut to the
 | ||||
|      * programming of the Translation Type (T) field in the present | ||||
|      * context-entry. | ||||
|      */ | ||||
|     VTD_FR_CONTEXT_ENTRY_TT, | ||||
|     /* This is not a normal fault reason. We use this to indicate some faults
 | ||||
|      * that are not referenced by the VT-d specification. | ||||
|      * Fault event with such reason should not be recorded. | ||||
|      */ | ||||
|     VTD_FR_RESERVED_ERR, | ||||
|     VTD_FR_MAX,                 /* Guard */ | ||||
| } VTDFaultReason; | ||||
| 
 | ||||
| /* Masks for Queued Invalidation Descriptor */ | ||||
| #define VTD_INV_DESC_TYPE           0xf | ||||
| #define VTD_INV_DESC_CC             0x1 /* Context-cache Invalidate Desc */ | ||||
| #define VTD_INV_DESC_IOTLB          0x2 | ||||
| #define VTD_INV_DESC_WAIT           0x5 /* Invalidation Wait Descriptor */ | ||||
| #define VTD_INV_DESC_NONE           0   /* Not an Invalidate Descriptor */ | ||||
| 
 | ||||
| /* Pagesize of VTD paging structures, including root and context tables */ | ||||
| #define VTD_PAGE_SHIFT              12 | ||||
| #define VTD_PAGE_SIZE               (1ULL << VTD_PAGE_SHIFT) | ||||
| 
 | ||||
| #define VTD_PAGE_SHIFT_4K           12 | ||||
| #define VTD_PAGE_MASK_4K            (~((1ULL << VTD_PAGE_SHIFT_4K) - 1)) | ||||
| #define VTD_PAGE_SHIFT_2M           21 | ||||
| #define VTD_PAGE_MASK_2M            (~((1ULL << VTD_PAGE_SHIFT_2M) - 1)) | ||||
| #define VTD_PAGE_SHIFT_1G           30 | ||||
| #define VTD_PAGE_MASK_1G            (~((1ULL << VTD_PAGE_SHIFT_1G) - 1)) | ||||
| 
 | ||||
| struct VTDRootEntry { | ||||
|     uint64_t val; | ||||
|     uint64_t rsvd; | ||||
| }; | ||||
| typedef struct VTDRootEntry VTDRootEntry; | ||||
| 
 | ||||
| /* Masks for struct VTDRootEntry */ | ||||
| #define VTD_ROOT_ENTRY_P            1ULL | ||||
| #define VTD_ROOT_ENTRY_CTP          (~0xfffULL) | ||||
| 
 | ||||
| #define VTD_ROOT_ENTRY_NR           (VTD_PAGE_SIZE / sizeof(VTDRootEntry)) | ||||
| #define VTD_ROOT_ENTRY_RSVD         (0xffeULL | ~VTD_HAW_MASK) | ||||
| 
 | ||||
| /* Context-Entry */ | ||||
| struct VTDContextEntry { | ||||
|     uint64_t lo; | ||||
|     uint64_t hi; | ||||
| }; | ||||
| typedef struct VTDContextEntry VTDContextEntry; | ||||
| 
 | ||||
| /* Masks for struct VTDContextEntry */ | ||||
| /* lo */ | ||||
| #define VTD_CONTEXT_ENTRY_P         (1ULL << 0) | ||||
| #define VTD_CONTEXT_ENTRY_FPD       (1ULL << 1) /* Fault Processing Disable */ | ||||
| #define VTD_CONTEXT_ENTRY_TT        (3ULL << 2) /* Translation Type */ | ||||
| #define VTD_CONTEXT_TT_MULTI_LEVEL  0 | ||||
| #define VTD_CONTEXT_TT_DEV_IOTLB    1 | ||||
| #define VTD_CONTEXT_TT_PASS_THROUGH 2 | ||||
| /* Second Level Page Translation Pointer*/ | ||||
| #define VTD_CONTEXT_ENTRY_SLPTPTR   (~0xfffULL) | ||||
| #define VTD_CONTEXT_ENTRY_RSVD_LO   (0xff0ULL | ~VTD_HAW_MASK) | ||||
| /* hi */ | ||||
| #define VTD_CONTEXT_ENTRY_AW        7ULL /* Adjusted guest-address-width */ | ||||
| #define VTD_CONTEXT_ENTRY_DID       (0xffffULL << 8) /* Domain Identifier */ | ||||
| #define VTD_CONTEXT_ENTRY_RSVD_HI   0xffffffffff000080ULL | ||||
| 
 | ||||
| #define VTD_CONTEXT_ENTRY_NR        (VTD_PAGE_SIZE / sizeof(VTDContextEntry)) | ||||
| 
 | ||||
| /* Paging Structure common */ | ||||
| #define VTD_SL_PT_PAGE_SIZE_MASK    (1ULL << 7) | ||||
| /* Bits to decide the offset for each level */ | ||||
| #define VTD_SL_LEVEL_BITS           9 | ||||
| 
 | ||||
| /* Second Level Paging Structure */ | ||||
| #define VTD_SL_PML4_LEVEL           4 | ||||
| #define VTD_SL_PDP_LEVEL            3 | ||||
| #define VTD_SL_PD_LEVEL             2 | ||||
| #define VTD_SL_PT_LEVEL             1 | ||||
| #define VTD_SL_PT_ENTRY_NR          512 | ||||
| 
 | ||||
| /* Masks for Second Level Paging Entry */ | ||||
| #define VTD_SL_RW_MASK              3ULL | ||||
| #define VTD_SL_R                    1ULL | ||||
| #define VTD_SL_W                    (1ULL << 1) | ||||
| #define VTD_SL_PT_BASE_ADDR_MASK    (~(VTD_PAGE_SIZE - 1) & VTD_HAW_MASK) | ||||
| #define VTD_SL_IGN_COM              0xbff0000000000000ULL | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										89
									
								
								include/hw/i386/intel_iommu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								include/hw/i386/intel_iommu.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| /*
 | ||||
|  * QEMU emulation of an Intel IOMMU (VT-d) | ||||
|  *   (DMA Remapping device) | ||||
|  * | ||||
|  * Copyright (C) 2013 Knut Omang, Oracle <knut.omang@oracle.com> | ||||
|  * Copyright (C) 2014 Le Tan, <tamlokveer@gmail.com> | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
| 
 | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
| 
 | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program; if not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #ifndef INTEL_IOMMU_H | ||||
| #define INTEL_IOMMU_H | ||||
| #include "hw/qdev.h" | ||||
| #include "sysemu/dma.h" | ||||
| 
 | ||||
| #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu" | ||||
| #define INTEL_IOMMU_DEVICE(obj) \ | ||||
|      OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) | ||||
| 
 | ||||
| /* DMAR Hardware Unit Definition address (IOMMU unit) */ | ||||
| #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed90000ULL | ||||
| 
 | ||||
| #define VTD_PCI_BUS_MAX             256 | ||||
| #define VTD_PCI_SLOT_MAX            32 | ||||
| #define VTD_PCI_FUNC_MAX            8 | ||||
| #define VTD_PCI_DEVFN_MAX           256 | ||||
| #define VTD_PCI_SLOT(devfn)         (((devfn) >> 3) & 0x1f) | ||||
| #define VTD_PCI_FUNC(devfn)         ((devfn) & 0x07) | ||||
| 
 | ||||
| #define DMAR_REG_SIZE               0x230 | ||||
| #define VTD_HOST_ADDRESS_WIDTH      39 | ||||
| #define VTD_HAW_MASK                ((1ULL << VTD_HOST_ADDRESS_WIDTH) - 1) | ||||
| 
 | ||||
| typedef struct IntelIOMMUState IntelIOMMUState; | ||||
| typedef struct VTDAddressSpace VTDAddressSpace; | ||||
| 
 | ||||
| struct VTDAddressSpace { | ||||
|     uint8_t bus_num; | ||||
|     uint8_t devfn; | ||||
|     AddressSpace as; | ||||
|     MemoryRegion iommu; | ||||
|     IntelIOMMUState *iommu_state; | ||||
| }; | ||||
| 
 | ||||
| /* The iommu (DMAR) device state struct */ | ||||
| struct IntelIOMMUState { | ||||
|     SysBusDevice busdev; | ||||
|     MemoryRegion csrmem; | ||||
|     uint8_t csr[DMAR_REG_SIZE];     /* register values */ | ||||
|     uint8_t wmask[DMAR_REG_SIZE];   /* R/W bytes */ | ||||
|     uint8_t w1cmask[DMAR_REG_SIZE]; /* RW1C(Write 1 to Clear) bytes */ | ||||
|     uint8_t womask[DMAR_REG_SIZE];  /* WO (write only - read returns 0) */ | ||||
|     uint32_t version; | ||||
| 
 | ||||
|     dma_addr_t root;                /* Current root table pointer */ | ||||
|     bool root_extended;             /* Type of root table (extended or not) */ | ||||
|     bool dmar_enabled;              /* Set if DMA remapping is enabled */ | ||||
| 
 | ||||
|     uint16_t iq_head;               /* Current invalidation queue head */ | ||||
|     uint16_t iq_tail;               /* Current invalidation queue tail */ | ||||
|     dma_addr_t iq;                  /* Current invalidation queue pointer */ | ||||
|     uint16_t iq_size;               /* IQ Size in number of entries */ | ||||
|     bool qi_enabled;                /* Set if the QI is enabled */ | ||||
|     uint8_t iq_last_desc_type;      /* The type of last completed descriptor */ | ||||
| 
 | ||||
|     /* The index of the Fault Recording Register to be used next.
 | ||||
|      * Wraps around from N-1 to 0, where N is the number of FRCD_REG. | ||||
|      */ | ||||
|     uint16_t next_frcd_reg; | ||||
| 
 | ||||
|     uint64_t cap;                   /* The value of capability reg */ | ||||
|     uint64_t ecap;                  /* The value of extended capability reg */ | ||||
| 
 | ||||
|     MemoryRegionIOMMUOps iommu_ops; | ||||
|     VTDAddressSpace **address_spaces[VTD_PCI_BUS_MAX]; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Le Tan
						Le Tan