Changeset 84170 in vbox
- Timestamp:
- May 6, 2020 4:50:36 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 137775
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/err.h
r83474 r84170 2967 2967 #define VERR_SHCLPB_MAX_EVENTS_REACHED (-7106) 2968 2968 /** @} */ 2969 2970 /** @name Virtual IOMMU Status Codes 2971 * @{ 2972 */ 2973 /** Internal processing error \#1 in the IOMMU device code. */ 2974 #define VERR_IOMMU_IPE_1 (-7201) 2975 /** Internal processing error \#2 in the IOMMU device code. */ 2976 #define VERR_IOMMU_IPE_2 (-7202) 2977 /** Address translation failed. */ 2978 #define VERR_IOMMU_ADDR_TRANSLATION_FAILED (-7203) 2979 /** Access denied for the address. */ 2980 #define VERR_IOMMU_ADDR_ACCESS_DENIED (-7204) 2981 /** @} */ 2982 2969 2983 /* SED-END */ 2970 2984 -
trunk/include/VBox/vmm/pdmdev.h
r83987 r84170 1261 1261 * @param pDevIns The IOMMU device instance. 1262 1262 * @param uDevId The device identifier (bus, device, function). 1263 * @param u Dva The devicevirtual address being read.1263 * @param uIova The I/O virtual address being read. 1264 1264 * @param cbRead The number of bytes being read. 1265 * @param pGCPhys Out Where to store the translatedphysical address.1265 * @param pGCPhysSpa Where to store the translated system physical address. 1266 1266 * 1267 1267 * @thread Any. 1268 1268 */ 1269 DECLR0CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbRead,1270 PRTGCPHYS pGCPhys Out));1269 DECLR0CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbRead, 1270 PRTGCPHYS pGCPhysSpa)); 1271 1271 1272 1272 /** … … 1276 1276 * @param pDevIns The IOMMU device instance. 1277 1277 * @param uDevId The device identifier (bus, device, function). 1278 * @param u Dva The devicevirtual address being written.1278 * @param uIova The I/O virtual address being written. 1279 1279 * @param cbRead The number of bytes being written. 1280 * @param pGCPhys Out Where to store the translatedphysical address.1280 * @param pGCPhysSpa Where to store the translated system physical address. 1281 1281 * 1282 1282 * @thread Any. 1283 1283 */ 1284 DECLR0CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbWrite,1285 PRTGCPHYS pGCPhys Out));1284 DECLR0CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbWrite, 1285 PRTGCPHYS pGCPhysSpa)); 1286 1286 1287 1287 /** Just a safety precaution. */ … … 1312 1312 * @param pDevIns The IOMMU device instance. 1313 1313 * @param uDevId The device identifier (bus, device, function). 1314 * @param u Dva The device virtual address.1314 * @param uIova The I/O virtual address being read. 1315 1315 * @param cbRead The number of bytes being read. 1316 * @param pGCPhys Out Where to store the translatedphysical address.1316 * @param pGCPhysSpa Where to store the translated system physical address. 1317 1317 * 1318 1318 * @thread Any. 1319 1319 */ 1320 DECLRCCALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbRead,1321 PRTGCPHYS pGCPhys Out));1320 DECLRCCALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbRead, 1321 PRTGCPHYS pGCPhysSpa)); 1322 1322 1323 1323 /** … … 1327 1327 * @param pDevIns The IOMMU device instance. 1328 1328 * @param uDevId The device identifier (bus, device, function). 1329 * @param u Dva The devicevirtual address being written.1329 * @param uIova The I/O virtual address being written. 1330 1330 * @param cbRead The number of bytes being written. 1331 * @param pGCPhys Out Where to store the translatedphysical address.1331 * @param pGCPhysSpa Where to store the translated system physical address. 1332 1332 * 1333 1333 * @thread Any. 1334 1334 */ 1335 DECLRCCALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbWrite,1336 PRTGCPHYS pGCPhys Out));1335 DECLRCCALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbWrite, 1336 PRTGCPHYS pGCPhysSpa)); 1337 1337 1338 1338 /** Just a safety precaution. */ … … 1363 1363 * @param pDevIns The IOMMU device instance. 1364 1364 * @param uDevId The device identifier (bus, device, function). 1365 * @param u Dva The devicevirtual address being read.1365 * @param uIova The I/O virtual address being read. 1366 1366 * @param cbRead The number of bytes being read. 1367 * @param pGCPhys Out Where to store the translatedphysical address.1367 * @param pGCPhysSpa Where to store the translated system physical address. 1368 1368 * 1369 1369 * @thread Any. 1370 1370 */ 1371 DECLR3CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbRead,1372 PRTGCPHYS pGCPhys Out));1371 DECLR3CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbRead, 1372 PRTGCPHYS pGCPhysSpa)); 1373 1373 1374 1374 /** … … 1378 1378 * @param pDevIns The IOMMU device instance. 1379 1379 * @param uDevId The device identifier (bus, device, function). 1380 * @param u Dva The devicevirtual address being written.1380 * @param uIova The I/O virtual address being written. 1381 1381 * @param cbWrite The number of bytes being written. 1382 * @param pGCPhys Out Where to store the translatedphysical address.1382 * @param pGCPhysSpa Where to store the translated system physical address. 1383 1383 * 1384 1384 * @thread Any. 1385 1385 */ 1386 DECLR3CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbWrite,1387 PRTGCPHYS pGCPhys Out));1386 DECLR3CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbWrite, 1387 PRTGCPHYS pGCPhysSpa)); 1388 1388 1389 1389 /** Just a safety precaution. */ -
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r84134 r84170 419 419 /** @} */ 420 420 421 /** @name IOMMU_ PERM_XXX: IOMMU I/O access permissions bits.421 /** @name IOMMU_IO_PERM_XXX: IOMMU I/O access permissions bits. 422 422 * In accordance with the AMD spec. 423 423 * … … 426 426 * 427 427 * @{ */ 428 #define IOMMU_IO_PERM_READ RT_BIT_64(0) 429 #define IOMMU_IO_PERM_WRITE RT_BIT_64(1) 430 #define IOMMU_IO_PERM_SHIFT 61 431 #define IOMMU_IO_PERM_MASK 0x3 428 #define IOMMU_IO_PERM_NONE (0) 429 #define IOMMU_IO_PERM_READ RT_BIT_64(0) 430 #define IOMMU_IO_PERM_WRITE RT_BIT_64(1) 431 #define IOMMU_IO_PERM_READ_WRITE (IOMMU_IO_PERM_READ | IOMMU_IO_PERM_WRITE) 432 #define IOMMU_IO_PERM_SHIFT 61 433 #define IOMMU_IO_PERM_MASK 0x3 434 /** @} */ 435 436 /** @name SYSMGT_TYPE_XXX: System Management Message Enable Types. 437 * In accordance with the AMD spec. 438 * @{ */ 439 #define SYSMGTTYPE_DMA_DENY (0) 440 #define SYSMGTTYPE_MSG_ALL_ALLOW (1) 441 #define SYSMGTTYPE_MSG_INT_ALLOW (2) 442 #define SYSMGTTYPE_DMA_ALLOW (3) 432 443 /** @} */ 433 444 … … 545 556 RT_GCC_EXTENSION uint64_t u1GstIoValid : 1; /**< Bit 54 - GIoV: Guest I/O Protection Valid. */ 546 557 RT_GCC_EXTENSION uint64_t u1GstTranslateValid : 1; /**< Bit 55 - GV: Guest translation Valid. */ 547 RT_GCC_EXTENSION uint64_t u2Gst Cr3RootTblTranslated : 2; /**< Bits 57:56 - GLX: Guest Levels Translated. */558 RT_GCC_EXTENSION uint64_t u2GstMode : 2; /**< Bits 57:56 - GLX: Guest Paging mode levels. */ 548 559 RT_GCC_EXTENSION uint64_t u3GstCr3TableRootPtrLo : 2; /**< Bits 60:58 - GCR3 TRP: Guest CR3 Table Root Ptr (Lo). */ 549 560 RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */ … … 587 598 } DTE_T; 588 599 AssertCompileSize(DTE_T, 32); 589 #define IOMMU_DTE_QWORD_0_VALID_MASK UINT64_C(0x7fffffffffffff83)590 #define IOMMU_DTE_QWORD_1_VALID_MASK UINT64_C(0xfffffbffffffffff)591 #define IOMMU_DTE_QWORD_2_VALID_MASK UINT64_C(0xf70fffffffffffff)592 #define IOMMU_DTE_QWORD_3_VALID_MASK UINT64_C(0xffc0000000000000)593 600 /** Pointer to a device table entry. */ 594 601 typedef DTE_T *PDTE_T; 595 602 /** Pointer to a const device table entry. */ 596 603 typedef DTE_T const *PCDTE_T; 604 605 /** Mask of valid bits for EPHSUP (Enhanced Peripheral Page Request Handling 606 * Support) features (bits 52:53). */ 607 #define IOMMU_DTE_QWORD_0_FEAT_EPHSUP_MASK UINT64_C(0x0030000000000000) 608 609 /** Mask of valid bits for GTSup (Guest Translation Support) features (bits 610 * 55:60, bits 80:95). */ 611 #define IOMMU_DTE_QWORD_0_FEAT_GTSUP_MASK UINT64_C(0x1f80000000000000) 612 #define IOMMU_DTE_QWORD_1_FEAT_GTSUP_MASK UINT64_C(0x00000000ffff0000) 613 614 /* Mask of valid bits for GIoSup (Guest I/O Protection Support) features (bit 54). */ 615 #define IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK UINT64_C(0x0040000000000000) 616 617 /* Mask of all valid DTE feature bits. */ 618 #define IOMMU_DTE_QWORD_0_FEAT_MASK ( IOMMU_DTE_QWORD_0_FEAT_EPHSUP_MASK \ 619 | IOMMU_DTE_QWORD_0_FEAT_GTSUP_MASK \ 620 | IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK) 621 #define IOMMU_DTE_QWORD_1_FEAT_MASK (IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK) 622 623 /* Mask of all valid DTE bits. */ 624 #define IOMMU_DTE_QWORD_0_VALID_MASK UINT64_C(0x7fffffffffffff83) 625 #define IOMMU_DTE_QWORD_1_VALID_MASK UINT64_C(0xfffffbffffffffff) 626 #define IOMMU_DTE_QWORD_2_VALID_MASK UINT64_C(0xf70fffffffffffff) 627 #define IOMMU_DTE_QWORD_3_VALID_MASK UINT64_C(0xffc0000000000000) 597 628 598 629 /** … … 646 677 } IOPDE_T; 647 678 AssertCompileSize(IOPDE_T, 8); 679 680 /** 681 * I/O Page Table Generic Entity. 682 * In accordance with the AMD spec. 683 * 684 * This a common subset of a page table entry. 685 * Can be either an IOPTE_T or and IOPDE_T. 686 */ 687 typedef union 688 { 689 struct 690 { 691 RT_GCC_EXTENSION uint64_t u1Present : 1; /**< Bit 0 - PR: Present. */ 692 RT_GCC_EXTENSION uint64_t u4Ign0 : 4; /**< Bits 4:1 - Ignored. */ 693 RT_GCC_EXTENSION uint64_t u1Accessed : 1; /**< Bit 5 - A: Accessed. */ 694 RT_GCC_EXTENSION uint64_t u3Ign0 : 3; /**< Bits 8:6 - Ignored. */ 695 RT_GCC_EXTENSION uint64_t u3NextLevel : 3; /**< Bits 11:9 - Next Level: Next page translation level. */ 696 RT_GCC_EXTENSION uint64_t u40PageAddr : 40; /**< Bits 51:12 - Page address. */ 697 RT_GCC_EXTENSION uint64_t u9Rsvd0 : 9; /**< Bits 60:52 - Reserved. */ 698 RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */ 699 RT_GCC_EXTENSION uint64_t u1IoWrite : 1; /**< Bit 62 - IW: I/O Wead permission. */ 700 RT_GCC_EXTENSION uint64_t u1Ign0 : 1; /**< Bit 63 - Ignored. */ 701 } n; 702 } IOPTENTITY_T; 703 AssertCompileSize(IOPDE_T, 8); 704 /** Pointer to an IOPT_ENTITY_T struct. */ 705 typedef IOPTENTITY_T *PIOPTENTITY_T; 706 /** Pointer to a const IOPT_ENTITY_T struct. */ 707 typedef IOPTENTITY_T const *PCIOPTENTITY_T; 648 708 649 709 /** … … 903 963 uint16_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write. */ 904 964 uint16_t u1Rsvd1 : 1; /**< Bit 54 - Reserved. */ 905 uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero or invalid level encoding. */965 uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero (0=invalid level encoding). */ 906 966 uint16_t u1Translation : 1; /**< Bit 56 - TN: Translation. */ 907 967 uint16_t u3Rsvd0 : 3; /**< Bits 59:57 - Reserved. */ 908 968 uint16_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */ 909 uint64_t u64Addr; /**< Bits 127:64 - Address: Device Virtual Address. */969 uint64_t u64Addr; /**< Bits 127:64 - Address: I/O Virtual Address (IOVA). */ 910 970 } n; 911 971 /** The 32-bit unsigned integer view. */ … … 934 994 uint16_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write. */ 935 995 uint16_t u1Perm : 1; /**< Bit 54 - PE: Permission Indicator. */ 936 uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero or invalid level encoding. */996 uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero (0=invalid level encoding). */ 937 997 uint16_t u1Translation : 1; /**< Bit 56 - TN: Translation. */ 938 998 uint16_t u3Rsvd0 : 3; /**< Bit 59:57 - Reserved. */ 939 999 uint16_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */ 940 uint64_t u64Addr; /**< Bits 127:64 - Address: Device Virtual Address. */1000 uint64_t u64Addr; /**< Bits 127:64 - Address: I/O Virtual Address (IOVA). */ 941 1001 } n; 942 1002 /** The 32-bit unsigned integer view. */ … … 944 1004 } EVT_IO_PAGE_FAULT_T; 945 1005 AssertCompileSize(EVT_IO_PAGE_FAULT_T, 16); 1006 /** Pointer to an I/O page fault event. */ 1007 typedef EVT_IO_PAGE_FAULT_T *PEVT_IO_PAGE_FAULT_T; 946 1008 947 1009 /** … … 1343 1405 uint32_t u1X2ApicSup : 1; /**< Bit 2 - XTSup: x2Apic Support. */ 1344 1406 uint32_t u1NoExecuteSup : 1; /**< Bit 3 - NXSup: No-Execute and Privilege Level Support. */ 1345 uint32_t u1GstTranslateSup : 1; /**< Bit 4 - GTSup: Guest Translations Support. */1407 uint32_t u1GstTranslateSup : 1; /**< Bit 4 - GTSup: Guest Translations (for GVAs) Support. */ 1346 1408 uint32_t u1Rsvd0 : 1; /**< Bit 5 - Reserved. */ 1347 1409 uint32_t u1InvAllSup : 1; /**< Bit 6 - IASup: Invalidate-All Support. */ … … 2002 2064 2003 2065 /** 2004 * IOMMU operation types. 2066 * ILLEGAL_DEV_TABLE_ENTRY Event Types. 2067 * In accordance with the AMD spec. 2068 */ 2069 typedef enum EVT_ILLEGAL_DTE_TYPE_T 2070 { 2071 kIllegalDteType_RsvdNotZero = 0, 2072 kIllegalDteType_RsvdIntTab, 2073 kIllegalDteType_RsvdIoCtl, 2074 kIllegalDteType_RsvdIntCtl 2075 } EVT_ILLEGAL_DTE_TYPE_T; 2076 2077 /** 2078 * ILLEGAL_DEV_TABLE_ENTRY Event Types. 2079 * In accordance with the AMD spec. 2080 */ 2081 typedef enum EVT_IO_PAGE_FAULT_TYPE_T 2082 { 2083 /* Memory transaction. */ 2084 kIoPageFaultType_DteRsvdPagingMode = 0, 2085 kIoPageFaultType_PteInvalidPageSize, 2086 kIoPageFaultType_PteInvalidLvlEncoding, 2087 kIoPageFaultType_InvalidSkippedPageLvl, 2088 kIoPageFaultType_PteRsvdNotZero, 2089 kIoPageFaultType_PteValidNotSet, 2090 kIoPageFaultType_DteTranslationDisabled, 2091 kIoPageFaultType_PasidInvalidRange, 2092 kIoPageFaultType_ReadProtect, 2093 kIoPageFaultType_WriteProtect, 2094 kIoPageFaultType_ExecuteProtect, 2095 kIoPageFaultType_UserSupervisor, 2096 /* Interrupt remapping */ 2097 kIoPageFaultType_IrteAddrInvalid, 2098 kIoPageFaultType_IrteRsvdNotZero, 2099 kIoPageFaultType_IrteRemapEn, 2100 kIoPageFaultType_IrteRsvdIntType, 2101 kIoPageFaultType_IntrReqAborted, 2102 kIoPageFaultType_IntrWithPasid, 2103 kIoPageFaultType_SmiFilterMismatch, 2104 /* Memory transaction or interrupt remapping. */ 2105 kIoPageFaultType_DevId_Invalid 2106 } EVT_IO_PAGE_FAULT_TYPE_T; 2107 2108 /** 2109 * DEV_TAB_HARDWARE_ERROR Event Types. 2110 * In accordance with the AMD spec. 2111 */ 2112 typedef enum EVT_DEV_TAB_HW_ERROR_TYPE_T 2113 { 2114 kDevTabHwErrType_MasterAbort = 0, 2115 kDevTabHwErrType_TargetAbort, 2116 kDevTabHwErrType_PoisonedData 2117 } EVT_DEV_TAB_HW_ERROR_TYPE_T; 2118 2119 /** 2120 * PAGE_TAB_HARDWARE_ERROR Even Types. 2121 * In accordance with the AMD spec. 2122 */ 2123 typedef enum EVT_PAGE_TAB_HW_ERR_TYPE_T 2124 { 2125 kPageTabHwErrType_MasterAbort = 0, 2126 kPageTabHwErrType_TargetAbort, 2127 kPageTabHwErrType_PoisonedData, 2128 } EVT_PAGE_TAB_HW_ERR_TYPE_T; 2129 2130 /** 2131 * COMMAND_HARDWARE_ERROR Event Types. 2132 * In accordance with the AMD spec. 2133 */ 2134 typedef enum EVT_CMD_HW_ERROR_TYPE_T 2135 { 2136 kCmdHwErrType_MasterAbort = 0, 2137 kCmdHwErrType_TargetAbort, 2138 kCmdHwErrType_PoisonedData 2139 } EVT_CMD_HW_ERROR_TYPE_T; 2140 2141 /** 2142 * ILLEGAL_COMMAND_ERROR Event Types. 2143 * In accordance with the AMD spec. 2144 */ 2145 typedef enum EVT_ILLEGAL_CMD_ERR_TYPE_T 2146 { 2147 kIllegalCmdErrType_RsvdNotZero = 0, 2148 kIllegalCmdErrType_CmdNotSupported, 2149 kIllegalCmdErrType_IotlbNotSupported 2150 } EVT_ILLEGAL_CMD_ERR_TYPE_T; 2151 2152 /** 2153 * IOTLB_INV_TIMEOUT Event Types. 2154 * In accordance with the AMD spec. 2155 */ 2156 typedef enum EVT_IOTLB_INV_TIMEOUT_TYPE_T 2157 { 2158 InvTimeoutType_NoResponse = 0 2159 } EVT_IOTLB_INV_TIMEOUT_TYPE_T; 2160 2161 /** 2162 * INVALID_DEVICE_REQUEST Event Types. 2163 * In accordance with the AMD spec. 2164 */ 2165 typedef enum EVT_INVALID_DEV_REQ_TYPE_T 2166 { 2167 /* Access. */ 2168 kInvalidDevReqType_ReadOrNonPostedWrite = 0, 2169 kInvalidDevReqType_PretranslatedTransaction, 2170 kInvalidDevReqType_PortIo, 2171 kInvalidDevReqType_SysMgt, 2172 kInvalidDevReqType_IntrRange, 2173 kInvalidDevReqType_RsvdIntrRange, 2174 kInvalidDevReqType_SysMgtAddr, 2175 /* Translation Request. */ 2176 kInvalidDevReqType_TrAccessInvalid, 2177 kInvalidDevReqType_TrDisabled, 2178 kInvalidDevReqType_DevIdInvalid, 2179 } EVT_INVALID_DEV_REQ_TYPE_T; 2180 2181 /** 2182 * INVALID_PPR_REQUEST Event Types. 2183 * In accordance with the AMD spec. 2184 */ 2185 typedef enum EVT_INVALID_PPR_REQ_TYPE_T 2186 { 2187 kInvalidPprReqType_PriNotSupported, 2188 kInvalidPprReqType_GstTranslateDisabled 2189 } EVT_INVALID_PPR_REQ_TYPE_T; 2190 2191 /** 2192 * IOMMU operations (transaction) types. 2005 2193 */ 2006 2194 typedef enum IOMMUOP … … 2014 2202 /** Interrupt request. */ 2015 2203 IOMMUOP_INTR_REQ, 2016 /** Command request. */2204 /** Command. */ 2017 2205 IOMMUOP_CMD 2018 2206 } IOMMUOP; 2019 2207 AssertCompileSize(IOMMUOP, 4); 2208 2209 /** 2210 * IOMMU I/O TLB Entry. 2211 * @note Update iommuAmdInitIotlbe() when changes are made. 2212 */ 2213 typedef struct 2214 { 2215 /** The device ID. */ 2216 uint16_t uDevId; 2217 /** The domain ID. */ 2218 uint16_t uDomainId; 2219 /** @todo Shouldn't we also store how many bits are the offset into the page for 2220 * pages > 4K? */ 2221 /** The I/O virtual address. */ 2222 uint64_t uIova; 2223 /** The translated system physical address. */ 2224 RTGCPHYS GCPhysSpa; 2225 /** The I/O access permissions (IOMMU_IO_PERM_XXX). */ 2226 uint8_t fIoPerm; 2227 /** Alignment padding. */ 2228 uint8_t fRsvd0; 2229 /** Reserved for future (eviction hints?). */ 2230 uint32_t uPadding0; 2231 } IOTLBE_T; 2232 AssertCompileSizeAlignment(IOTLBE_T, 8); 2233 /** Pointer to an IOMMU I/O TLB entry struct. */ 2234 typedef IOTLBE_T *PIOTLBE_T; 2235 /** Pointer to a const IOMMU I/O TLB entry struct. */ 2236 typedef IOTLBE_T const *PCIOTLBE_T; 2020 2237 2021 2238 /** … … 3323 3540 3324 3541 /** 3325 * Constructs a DEV_TAB_HARDWARE_ERROR event.3542 * Initializes a DEV_TAB_HARDWARE_ERROR event. 3326 3543 * 3327 3544 * @param uDevId The device ID. 3328 3545 * @param GCPhysDte The system physical address of the failed device table 3329 3546 * access. 3330 * @param enmOp The operation being performed.3331 * @param pEvent Where to store the constructed event.3547 * @param enmOp The IOMMU operation being performed. 3548 * @param pEvent Where to store the initialized event. 3332 3549 * 3333 3550 * @thread Any. 3334 3551 */ 3335 static void iommuAmd MakeDevTabHwErrorEvent(uint16_t uDevId, RTGCPHYS GCPhysDte, IOMMUOP enmOp, PEVT_GENERIC_T pEvent)3552 static void iommuAmdInitDevTabHwErrorEvent(uint16_t uDevId, RTGCPHYS GCPhysDte, IOMMUOP enmOp, PEVT_GENERIC_T pEvent) 3336 3553 { 3337 3554 memset(pEvent, 0, sizeof(*pEvent)); … … 3340 3557 pDevTabHwErr->n.u16DevId = uDevId; 3341 3558 pDevTabHwErr->n.u1Intr = RT_BOOL(enmOp == IOMMUOP_INTR_REQ); 3559 /** @todo r=ramshankar: Any other transaction type that can set read/write bit? */ 3342 3560 pDevTabHwErr->n.u1ReadWrite = RT_BOOL(enmOp == IOMMUOP_MEM_WRITE); 3343 3561 pDevTabHwErr->n.u1Translation = RT_BOOL(enmOp == IOMMUOP_TRANSLATE_REQ); … … 3355 3573 * @param GCPhysDte The system physical address of the failed device table 3356 3574 * access. 3357 * @param enmOp The operation being performed by the IOMMU. 3358 */ 3359 static void iommuAmdRaiseDevTabHwErrorEvent(PPDMDEVINS pDevIns, uint16_t uDevId, RTGCPHYS GCPhysDte, IOMMUOP enmOp) 3575 * @param enmOp The IOMMU operation being performed. 3576 * @param enmEvtType The device table hardware error event type. 3577 */ 3578 static void iommuAmdRaiseDevTabHwErrorEvent(PPDMDEVINS pDevIns, uint16_t uDevId, RTGCPHYS GCPhysDte, IOMMUOP enmOp, 3579 EVT_DEV_TAB_HW_ERROR_TYPE_T enmEvtType) 3360 3580 { 3361 3581 EVT_GENERIC_T Event; 3362 iommuAmd MakeDevTabHwErrorEvent(uDevId, GCPhysDte, enmOp, &Event);3582 iommuAmdInitDevTabHwErrorEvent(uDevId, GCPhysDte, enmOp, &Event); 3363 3583 iommuAmdSetHwError(pDevIns, &Event); 3364 3584 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3365 3585 if (enmOp != IOMMUOP_CMD) 3366 3586 iommuAmdSetPciTargetAbort(pDevIns); 3367 } 3368 3369 3370 /** 3371 * Constructs an ILLEGAL_DEV_TAB_ENTRY event. 3587 3588 Log((IOMMU_LOG_PFX ": Raised DEV_TAB_HARDWARE_ERROR. uDevId=%#x GCPhysDte=%#RGp enmOp=%u enmType=%u\n", uDevId, GCPhysDte, 3589 enmOp, enmEvtType)); 3590 NOREF(enmEvtType); 3591 } 3592 3593 3594 /** 3595 * Initializes an ILLEGAL_DEV_TABLE_ENTRY event. 3372 3596 * 3373 3597 * @param uDevId The device ID. 3374 * @param u Dva The devicevirtual address.3375 * @param fRsvdNotZero Whether reserved bits in the device table entry were not3376 * zero.3377 * @param enmOp The operation being performed.3378 * @param pEvent Where to store the constructed event.3379 */ 3380 static void iommuAmdMakeIllegalDteEvent(uint16_t uDevId, uint64_t uDva, bool fRsvdNotZero, IOMMUOP enmOp,PEVT_GENERIC_T pEvent)3598 * @param uIova The I/O virtual address. 3599 * @param enmOp The IOMMU operation being performed. 3600 * @param enmEvtType The illegal DTE event type. 3601 * @param pEvent Where to store the initialized event. 3602 */ 3603 static void iommuAmdInitIllegalDteEvent(uint16_t uDevId, uint64_t uIova, IOMMUOP enmOp, EVT_ILLEGAL_DTE_TYPE_T enmEvtType, 3604 PEVT_GENERIC_T pEvent) 3381 3605 { 3382 3606 memset(pEvent, 0, sizeof(*pEvent)); … … 3386 3610 pIllegalDteErr->n.u1Interrupt = RT_BOOL(enmOp == IOMMUOP_INTR_REQ); 3387 3611 pIllegalDteErr->n.u1ReadWrite = RT_BOOL(enmOp == IOMMUOP_MEM_WRITE); 3388 pIllegalDteErr->n.u1RsvdNotZero = fRsvdNotZero;3612 pIllegalDteErr->n.u1RsvdNotZero = RT_BOOL(enmEvtType == kIllegalDteType_RsvdNotZero); 3389 3613 pIllegalDteErr->n.u1Translation = RT_BOOL(enmOp == IOMMUOP_TRANSLATE_REQ); 3390 3614 pIllegalDteErr->n.u4EvtCode = IOMMU_EVT_ILLEGAL_DEV_TAB_ENTRY; 3391 pIllegalDteErr->n.u64Addr = u Dva & ~UINT64_C(0x3);3615 pIllegalDteErr->n.u64Addr = uIova & ~UINT64_C(0x3); 3392 3616 /** @todo r=ramshankar: Not sure why the last 2 bits are marked as reserved by the 3393 3617 * IOMMU spec here but not for this field for I/O page fault event. */ 3394 Assert(!(u Dva & UINT64_C(0x3)));3395 } 3396 3397 3398 /** 3399 * Raises an ILLEGAL_DEV_TAB _ENTRY event.3618 Assert(!(uIova & UINT64_C(0x3))); 3619 } 3620 3621 3622 /** 3623 * Raises an ILLEGAL_DEV_TABLE_ENTRY event. 3400 3624 * 3401 3625 * @param pDevIns The IOMMU instance data. 3402 3626 * @param uDevId The device ID. 3403 * @param u Dva The devicevirtual address.3404 * @param fRsvdNotZero Whether reserved bits in the device table entry were not3405 * zero.3406 * @param enmOp The operation being performed.3407 */ 3408 static void iommuAmdRaiseIllegalDteEvent(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, bool fRsvdNotZero, IOMMUOP enmOp)3627 * @param uIova The I/O virtual address. 3628 * @param enmOp The IOMMU operation being performed. 3629 * @param enmEvtType The illegal DTE event type. 3630 */ 3631 static void iommuAmdRaiseIllegalDteEvent(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, IOMMUOP enmOp, 3632 EVT_ILLEGAL_DTE_TYPE_T enmEvtType) 3409 3633 { 3410 3634 EVT_GENERIC_T Event; 3411 iommuAmd MakeIllegalDteEvent(uDevId, uDva, fRsvdNotZero, enmOp, &Event);3635 iommuAmdInitIllegalDteEvent(uDevId, uIova, enmOp, enmEvtType, &Event); 3412 3636 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3413 3637 if (enmOp != IOMMUOP_CMD) 3414 3638 iommuAmdSetPciTargetAbort(pDevIns); 3415 } 3416 3417 3418 /** 3419 * Returns whether the device virtual address is allowed to be excluded from 3420 * translation and permission checks. 3639 3640 Log((IOMMU_LOG_PFX ": Raised ILLEGAL_DTE_EVENT. uDevId=%#x uIova=%#RX64 enmOp=%u enmType=%u\n", uDevId, uIova, enmOp, 3641 enmEvtType)); 3642 NOREF(enmEvtType); 3643 } 3644 3645 3646 /** 3647 * Initializes an IO_PAGE_FAULT event. 3648 * 3649 * @param uDevId The device ID. 3650 * @param uDomainId The domain ID. 3651 * @param uIova The I/O virtual address being accessed. 3652 * @param fPresent Transaction to a page marked as present (including 3653 * DTE.V=1) or interrupt marked as remapped 3654 * (IRTE.RemapEn=1). 3655 * @param enmOp The IOMMU operation being performed. 3656 * @param enmEvtType The I/O page fault event type. 3657 * @param pEvent Where to store the initialized event. 3658 */ 3659 static void iommuAmdInitIoPageFaultEvent(uint16_t uDevId, uint16_t uDomainId, uint64_t uIova, bool fPresent, 3660 IOMMUOP enmOp, EVT_IO_PAGE_FAULT_TYPE_T enmEvtType, PEVT_GENERIC_T pEvent) 3661 { 3662 memset(pEvent, 0, sizeof(*pEvent)); 3663 AssertCompile(sizeof(EVT_IO_PAGE_FAULT_T) == sizeof(EVT_GENERIC_T)); 3664 PEVT_IO_PAGE_FAULT_T pIoPageFault = (PEVT_IO_PAGE_FAULT_T)pEvent; 3665 pIoPageFault->n.u16DevId = uDevId; 3666 //pIoPageFault->n.u4PasidHi = 0; 3667 pIoPageFault->n.u16DomainOrPasidLo = uDomainId; 3668 //pIoPageFault->n.u1GuestOrNested = 0; 3669 //pIoPageFault->n.u1NoExecute = 0; 3670 //pIoPageFault->n.u1User = 0; 3671 pIoPageFault->n.u1Interrupt = RT_BOOL(enmOp == IOMMUOP_INTR_REQ); 3672 pIoPageFault->n.u1Present = fPresent; 3673 pIoPageFault->n.u1ReadWrite = RT_BOOL(enmOp == IOMMUOP_MEM_WRITE); 3674 //pIoPageFault->n.u1PermIndicator = 0; 3675 pIoPageFault->n.u1RsvdNotZero = RT_BOOL( enmEvtType == kIoPageFaultType_PteRsvdNotZero 3676 || enmEvtType == kIoPageFaultType_IrteRemapEn); 3677 pIoPageFault->n.u1Translation = RT_BOOL(enmOp == IOMMUOP_TRANSLATE_REQ); 3678 pIoPageFault->n.u4EvtCode = IOMMU_EVT_IO_PAGE_FAULT; 3679 pIoPageFault->n.u64Addr = uIova; 3680 } 3681 3682 3683 /** 3684 * Raises an IO_PAGE_FAULT event. 3685 * 3686 * @param pDevIns The IOMMU instance data. 3687 * @param uDevId The device ID. 3688 * @param uDomainId The domain ID. 3689 * @param uIova The I/O virtual address being accessed. 3690 * @param fPresentOrValid Transaction to a page marked as present (including 3691 * DTE.V=1) or interrupt marked as remapped 3692 * (IRTE.RemapEn=1). 3693 * @param enmOp The IOMMU operation being performed. 3694 * @param enmEvtType The I/O page fault event type. 3695 */ 3696 static void iommuAmdRaiseIoPageFaultEvent(PPDMDEVINS pDevIns, uint16_t uDevId, uint16_t uDomainId, uint64_t uIova, 3697 bool fPresentOrValid, IOMMUOP enmOp, EVT_IO_PAGE_FAULT_TYPE_T enmEvtType) 3698 { 3699 EVT_GENERIC_T Event; 3700 iommuAmdInitIoPageFaultEvent(uDevId, uDomainId, uIova, fPresentOrValid, enmOp, enmEvtType, &Event); 3701 3702 switch (enmEvtType) 3703 { 3704 case kIoPageFaultType_ReadProtect: 3705 case kIoPageFaultType_WriteProtect: 3706 case kIoPageFaultType_ExecuteProtect: 3707 { 3708 /* Cannot be triggered by a command. */ 3709 Assert(enmOp != IOMMUOP_CMD); 3710 RT_FALL_THRU(); 3711 } 3712 case kIoPageFaultType_DteRsvdPagingMode: 3713 case kIoPageFaultType_PteInvalidPageSize: 3714 case kIoPageFaultType_PteInvalidLvlEncoding: 3715 case kIoPageFaultType_InvalidSkippedPageLvl: 3716 case kIoPageFaultType_PteRsvdNotZero: 3717 case kIoPageFaultType_PteValidNotSet: 3718 case kIoPageFaultType_DteTranslationDisabled: 3719 case kIoPageFaultType_PasidInvalidRange: 3720 { 3721 /* 3722 * For a translation request, the IOMMU doesn't signal an I/O page fault nor does it 3723 * create an event log entry. See AMD spec. 2.1.3.2 "I/O Page Faults". 3724 */ 3725 if (enmOp != IOMMUOP_TRANSLATE_REQ) 3726 { 3727 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3728 if (enmOp != IOMMUOP_CMD) 3729 iommuAmdSetPciTargetAbort(pDevIns); 3730 } 3731 break; 3732 } 3733 3734 case kIoPageFaultType_UserSupervisor: 3735 { 3736 /* Access is blocked and only creates an event log entry. */ 3737 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3738 break; 3739 } 3740 3741 case kIoPageFaultType_IrteAddrInvalid: 3742 case kIoPageFaultType_IrteRsvdNotZero: 3743 case kIoPageFaultType_IrteRemapEn: 3744 case kIoPageFaultType_IrteRsvdIntType: 3745 case kIoPageFaultType_IntrReqAborted: 3746 case kIoPageFaultType_IntrWithPasid: 3747 { 3748 /* Only trigerred by interrupt requests. */ 3749 Assert(enmOp == IOMMUOP_INTR_REQ); 3750 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3751 iommuAmdSetPciTargetAbort(pDevIns); 3752 break; 3753 } 3754 3755 case kIoPageFaultType_SmiFilterMismatch: 3756 { 3757 /* Not supported and probably will never be, assert. */ 3758 AssertMsgFailed(("kIoPageFaultType_SmiFilterMismatch - Upstream SMI requests not supported/implemented.")); 3759 break; 3760 } 3761 3762 case kIoPageFaultType_DevId_Invalid: 3763 { 3764 /* Cannot be triggered by a command. */ 3765 Assert(enmOp != IOMMUOP_CMD); 3766 Assert(enmOp != IOMMUOP_TRANSLATE_REQ); /** @todo IOMMU: We don't support translation requests yet. */ 3767 iommuAmdWriteEvtLogEntry(pDevIns, &Event); 3768 if ( enmOp == IOMMUOP_MEM_READ 3769 || enmOp == IOMMUOP_MEM_WRITE) 3770 iommuAmdSetPciTargetAbort(pDevIns); 3771 break; 3772 } 3773 } 3774 3775 3776 } 3777 3778 3779 /** 3780 * Initializes an IOTLB entry. 3781 * 3782 * @param uDevId The device ID. 3783 * @param uDomainId The domain ID. 3784 * @param fIoPerm The I/O access permissions (IOMMU_IO_PERM_XXX). 3785 * @param uIova The I/O virtual address. 3786 * @param GCPhysSpa The translated system physical address. 3787 * @param pIotlbe Where to store the initialized IOTLB entry. 3788 */ 3789 static void iommuAmdInitIotlbe(uint16_t uDevId, uint16_t uDomainId, uint8_t fIoPerm, uint64_t uIova, RTGCPHYS GCPhysSpa, 3790 PIOTLBE_T pIotlbe) 3791 { 3792 pIotlbe->uDevId = uDevId; 3793 pIotlbe->uDomainId = uDomainId; 3794 pIotlbe->fIoPerm = fIoPerm; 3795 pIotlbe->fRsvd0 = 0; 3796 pIotlbe->uPadding0 = 0; 3797 pIotlbe->uIova = uIova; 3798 pIotlbe->GCPhysSpa = GCPhysSpa; 3799 } 3800 3801 3802 /** 3803 * Returns whether the I/O virtual address is to be excluded from translation and 3804 * permission checks. 3421 3805 * 3422 3806 * @returns @c true if the DVA is excluded, @c false otherwise. 3423 3807 * @param pThis The IOMMU device state. 3424 3808 * @param pDte The device table entry. 3425 * @param uDva The device virtual address. 3426 */ 3427 static bool iommuAmdIsDvaSubjectToExclRange(PCIOMMU pThis, PCDTE_T pDte, uint64_t uDva) 3428 { 3429 /* Check if the exclusion range is enabled. */ 3430 if (pThis->ExclRangeBaseAddr.n.u1ExclEnable) 3431 { 3432 /* Check if the device virtual address falls within the exclusion range. */ 3433 uint64_t const uDvaExclFirst = pThis->ExclRangeBaseAddr.n.u40ExclRangeBase << X86_PAGE_4K_SHIFT; 3434 uint64_t const uDvaExclLast = pThis->ExclRangeLimit.n.u52ExclLimit; 3435 if (uDvaExclLast - uDva >= uDvaExclFirst) 3436 { 3437 /* Check if device access to addresses in the exclusion range can be forwarded untranslated. */ 3438 if ( pThis->ExclRangeBaseAddr.n.u1AllowAll 3439 || pDte->n.u1AllowExclusion) 3440 return true; 3441 } 3809 * @param uIova The I/O virtual address. 3810 * 3811 * @remarks Ensure the exclusion range is enabled prior to calling this function. 3812 */ 3813 static bool iommuAmdIsDvaInExclRange(PCIOMMU pThis, PCDTE_T pDte, uint64_t uIova) 3814 { 3815 /* Ensure the exclusion range is enabled. */ 3816 Assert(pThis->ExclRangeBaseAddr.n.u1ExclEnable); 3817 3818 /* Check if the IOVA falls within the exclusion range. */ 3819 uint64_t const uIovaExclFirst = pThis->ExclRangeBaseAddr.n.u40ExclRangeBase << X86_PAGE_4K_SHIFT; 3820 uint64_t const uIovaExclLast = pThis->ExclRangeLimit.n.u52ExclLimit; 3821 if (uIovaExclLast - uIova >= uIovaExclFirst) 3822 { 3823 /* Check if device access to addresses in the exclusion range can be forwarded untranslated. */ 3824 if ( pThis->ExclRangeBaseAddr.n.u1AllowAll 3825 || pDte->n.u1AllowExclusion) 3826 return true; 3442 3827 } 3443 3828 return false; … … 3451 3836 * @param pDevIns The IOMMU device instance. 3452 3837 * @param uDevId The device ID. 3453 * @param enmOp The operation being performed by the IOMMU.3838 * @param enmOp The IOMMU operation being performed. 3454 3839 * @param pDte Where to store the device table entry. 3455 3840 * … … 3475 3860 if (RT_FAILURE(rc)) 3476 3861 { 3477 Log((IOMMU_LOG_PFX ": Failed to read device table entry at %#RGp. rc=%Rrc \n", GCPhysDte, rc));3478 iommuAmdRaiseDevTabHwErrorEvent(pDevIns, uDevId, GCPhysDte, enmOp );3862 Log((IOMMU_LOG_PFX ": Failed to read device table entry at %#RGp. rc=%Rrc -> DevTabHwError\n", GCPhysDte, rc)); 3863 iommuAmdRaiseDevTabHwErrorEvent(pDevIns, uDevId, GCPhysDte, enmOp, kDevTabHwErrType_TargetAbort); 3479 3864 } 3480 3865 … … 3483 3868 3484 3869 3485 #if 0 3486 /** 3487 * Walks the I/O page tables to translate the given device virtual address and 3488 * associated data. 3870 /** 3871 * Walks the I/O page table(s) to translate the I/O virtual address to a system 3872 * physical address. 3489 3873 * 3490 3874 * @returns VBox status code. 3491 3875 * @param pDevIns The IOMMU device instance. 3492 * @param uDva The device virtual address. 3493 * @param cbRead The size of the access. 3494 * @param fPerms The access permissions (IOMMU_PERM_XXX). 3495 * @param pGCPhys Where to store the translated address. 3496 */ 3497 static int iommuAmdWalkIoPageTable(PPDMDEVINS pDevIns, uint64_t uDva, size_t cbRead, uint32_t fAccess, PRTGCPHYS pGCPhys) 3498 { 3499 3500 } 3501 #endif 3502 3503 3504 /** 3505 * Memory read translation request from a device. 3876 * @param uIova The I/O virtual address to translate. 3877 * @param uDevId The device ID. 3878 * @param cbAccess The size of the access. 3879 * @param fAccess The access permissions (IOMMU_IO_PERM_XXX). This is the 3880 * permissions for the access being made. 3881 * @param enmOp The IOMMU operation being performed. 3882 * @param pGCPhysSpa Where to store the system physical address. 3883 * @param pfIoPerm Where to store the I/O access permissions. This is the 3884 * permission of what access is allowed. 3885 */ 3886 static int iommuAmdWalkIoPageTables(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, uint8_t fAccess, 3887 PCDTE_T pDte, IOMMUOP enmOp, PRTGCPHYS pGCPhysSpa, uint8_t *pfIoPerm) 3888 { 3889 NOREF(pDevIns); 3890 Assert(pDte->n.u1Valid); 3891 Assert(pDte->n.u1TranslationValid); 3892 Assert(cbAccess > 0); 3893 3894 if (pDte->n.u1TranslationValid) 3895 { /* likely */ } 3896 else 3897 { 3898 iommuAmdRaiseIoPageFaultEvent(pDevIns, uDevId, pDte->n.u16DomainId, uIova, true /* fPresentOrValid */, 3899 enmOp, kIoPageFaultType_DteTranslationDisabled); 3900 *pGCPhysSpa = 0; 3901 *pfIoPerm = 0; 3902 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 3903 } 3904 3905 /* If the page table depth is 0, translation is disabled and access is controlled by IR and IW bits. */ 3906 if (pDte->n.u3Mode == 0) 3907 { 3908 uint8_t const fDtePerm = (pDte->au64[0] >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK; 3909 if ((fAccess & fDtePerm) != fAccess) 3910 { 3911 Log((IOMMU_LOG_PFX ": Access denied for IOVA (%#RX64). fAccess=%#x fDtePerm=%#x\n", uIova, fAccess, fDtePerm)); 3912 return VERR_IOMMU_ADDR_ACCESS_DENIED; 3913 } 3914 *pGCPhysSpa = uIova; 3915 *pfIoPerm = fDtePerm; 3916 return VINF_SUCCESS; 3917 } 3918 3919 /* If the paging mode exceeds the host-address translation levels, translation fails. */ 3920 if (pDte->n.u3Mode > IOMMU_MAX_HOST_PT_LEVEL) 3921 { 3922 /** @todo r=ramshankar: I cannot make out from the AMD IOMMU spec. if I should be 3923 * raising an ILLEGAL_DEV_TABLE_ENTRY event or an IO_PAGE_FAULT event here. 3924 * I'm just going with this one... */ 3925 *pGCPhysSpa = 0; 3926 *pfIoPerm = IOMMU_IO_PERM_NONE; 3927 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 3928 } 3929 3930 /** @todo IOMMU: page walk. */ 3931 3932 return VERR_NOT_IMPLEMENTED; 3933 } 3934 3935 /** 3936 * Looks up an I/O virtual address from the device table(s). 3937 * 3938 * @returns VBox status code. 3939 * @param pDevIns The IOMMU instance data. 3940 * @param uDevId The device ID. 3941 * @param uIova The I/O virtual address to lookup. 3942 * @param cbAccess The size of the access. 3943 * @param enmOp The IOMMU operation being performed. 3944 * @param pIotlbe The IOTLBE to update. 3945 * 3946 * @remarks Only the translated address and permission bits are updated in @a 3947 * pIotlbe when this function returns VINF_SUCCESS. Caller is expected to 3948 * know and fill in the rest already. 3949 */ 3950 static int iommuAmdLookupDeviceTables(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbAccess, IOMMUOP enmOp, 3951 PIOTLBE_T pIotlbe) 3952 { 3953 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU); 3954 3955 /* Read the device table entry. */ 3956 DTE_T Dte; 3957 int rc = iommuAmdReadDte(pDevIns, uDevId, enmOp, &Dte); 3958 if (RT_SUCCESS(rc)) 3959 { 3960 RTGCPHYS GCPhysSpa = 0; 3961 uint8_t fIoPerm = IOMMU_IO_PERM_NONE; 3962 3963 if (Dte.n.u1Valid) 3964 { 3965 /* Validate bits 127:0 of the device table entry when DTE.V is 1. */ 3966 uint64_t const fRsvdQword0 = Dte.au64[0] & ~(IOMMU_DTE_QWORD_0_VALID_MASK & ~IOMMU_DTE_QWORD_0_FEAT_MASK); 3967 uint64_t const fRsvdQword1 = Dte.au64[1] & ~(IOMMU_DTE_QWORD_1_VALID_MASK & ~IOMMU_DTE_QWORD_1_FEAT_MASK); 3968 if ( fRsvdQword0 3969 || fRsvdQword1) 3970 { 3971 Log((IOMMU_LOG_PFX ": Invalid reserved bits in DTE (u64[0]=%#RX64 u64[1]=%#RX64) -> Illegal DTE\n", fRsvdQword0, 3972 fRsvdQword1)); 3973 iommuAmdRaiseIllegalDteEvent(pDevIns, uDevId, uIova, enmOp, kIllegalDteType_RsvdNotZero); 3974 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 3975 } 3976 3977 /* Ensure the IOVA is not in the exclusion range. */ 3978 if ( !pThis->ExclRangeBaseAddr.n.u1ExclEnable 3979 || !iommuAmdIsDvaInExclRange(pThis, &Dte, uIova)) 3980 { 3981 rc = iommuAmdWalkIoPageTables(pDevIns, uDevId, uIova, cbAccess, IOMMU_IO_PERM_READ, &Dte, enmOp, &GCPhysSpa, 3982 &fIoPerm); 3983 if (RT_FAILURE(rc)) 3984 Log((IOMMU_LOG_PFX ": I/O page table walk failed. rc=%Rrc\n")); 3985 } 3986 else 3987 { 3988 /* If the IOVA is subject to address exclusion, addresses are forwarded without translation. */ 3989 GCPhysSpa = uIova; 3990 fIoPerm = IOMMU_IO_PERM_READ_WRITE; 3991 } 3992 } 3993 else 3994 { 3995 /* Addresses are forwarded without translation when DTE.V is 0. */ 3996 GCPhysSpa = uIova; 3997 fIoPerm = IOMMU_IO_PERM_READ_WRITE; 3998 } 3999 4000 pIotlbe->GCPhysSpa = GCPhysSpa; 4001 pIotlbe->fIoPerm = fIoPerm; 4002 } 4003 else 4004 { 4005 Log((IOMMU_LOG_PFX ": Failed to read device table entry. uDevId=%#x rc=%Rrc\n", uDevId, rc)); 4006 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 4007 } 4008 4009 return rc; 4010 } 4011 4012 4013 /** 4014 * Memory read request from a device. 3506 4015 * 3507 4016 * @returns VBox status code. 3508 4017 * @param pDevIns The IOMMU device instance. 3509 4018 * @param uDevId The device ID (bus, device, function). 3510 * @param u Dva The devicevirtual address being read.4019 * @param uIova The I/O virtual address being read. 3511 4020 * @param cbRead The number of bytes being read. 3512 * @param pGCPhys Out Where to store the translatedphysical address.4021 * @param pGCPhysSpa Where to store the translated system physical address. 3513 4022 * 3514 4023 * @thread Any. 3515 4024 */ 3516 static int iommuAmdDeviceMemRead(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbRead, PRTGCPHYS pGCPhysOut) 3517 { 3518 RT_NOREF(pDevIns, uDevId, uDva, cbRead, pGCPhysOut); 3519 4025 static int iommuAmdDeviceMemRead(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbRead, PRTGCPHYS pGCPhysSpa) 4026 { 3520 4027 Assert(pDevIns); 3521 Assert(pGCPhysOut); 4028 Assert(pGCPhysSpa); 4029 Assert(cbRead > 0); 3522 4030 3523 4031 PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU); 3524 IOMMUOP const enmOp = IOMMUOP_TRANSLATE_REQ;3525 4032 3526 4033 /* Addresses are forwarded without translation when the IOMMU is disabled. */ … … 3528 4035 if (Ctrl.n.u1IommuEn) 3529 4036 { 3530 /** @todo IOTLB cache lookup. */ 3531 3532 /* Read the device table entry. */ 3533 DTE_T Dte; 3534 int rc = iommuAmdReadDte(pDevIns, uDevId, enmOp, &Dte); 3535 if (RT_SUCCESS(rc)) 3536 { 3537 /* Addresses are forwarded without translation when DTE.V is 0. */ 3538 if (Dte.n.u1Valid) 3539 { 3540 /* Validate bits 127:0 of the device table entry when DTE.V is 1. */ 3541 uint64_t const fRsvdQword0 = Dte.au64[0] & ~IOMMU_DTE_QWORD_0_VALID_MASK; 3542 uint64_t const fRsvdQword1 = Dte.au64[1] & ~IOMMU_DTE_QWORD_1_VALID_MASK; 3543 if ( fRsvdQword0 3544 || fRsvdQword1) 3545 { 3546 Log((IOMMU_LOG_PFX ":DTE invalid reserved bits ([0]=%#RX64 [1]=%#RX64)\n", fRsvdQword0, fRsvdQword1)); 3547 iommuAmdRaiseIllegalDteEvent(pDevIns, uDevId, uDva, true /* fRsvdNotZero */, enmOp); 3548 return VERR_GENERAL_FAILURE; /** @todo IOMMU: Change this. */ 3549 } 3550 3551 /* Check if the device virtual address is subject to address exclusion. */ 3552 if (!iommuAmdIsDvaSubjectToExclRange(pThis, &Dte, uDva)) 3553 { 3554 /** @todo IOMMU: Traverse the I/O page table and translate. */ 3555 3556 return VERR_NOT_IMPLEMENTED; 3557 } 3558 } 3559 } 3560 else 3561 { 3562 Log((IOMMU_LOG_PFX ":Failed to read device table entry. uDevId=%#x rc=%Rrc\n", uDevId, rc)); 3563 return VERR_GENERAL_FAILURE; /** @todo IOMMU: Change this. */ 3564 } 3565 } 3566 3567 *pGCPhysOut = uDva; 4037 IOTLBE_T Iotlbe; 4038 iommuAmdInitIotlbe(uDevId, 0 /* uDomainId */, IOMMU_IO_PERM_NONE, uIova, 0 /* GCPhySpa */, &Iotlbe); 4039 4040 /** @todo IOMMU: IOTLB cache lookup. */ 4041 4042 /* Lookup the IOVA from the device tables. */ 4043 int rc = iommuAmdLookupDeviceTables(pDevIns, uDevId, uIova, cbRead, IOMMUOP_MEM_READ, &Iotlbe); 4044 4045 /** @todo IOMMU: Cache translation. */ 4046 4047 *pGCPhysSpa = Iotlbe.GCPhysSpa; 4048 return rc; 4049 } 4050 4051 *pGCPhysSpa = uIova; 3568 4052 return VINF_SUCCESS; 3569 4053 } … … 3571 4055 3572 4056 /** 3573 * Memory write translationrequest from a device.4057 * Memory write request from a device. 3574 4058 * 3575 4059 * @returns VBox status code. 3576 4060 * @param pDevIns The IOMMU device instance. 3577 4061 * @param uDevId The device ID (bus, device, function). 3578 * @param u Dva The devicevirtual address being written.4062 * @param uIova The I/O virtual address being written. 3579 4063 * @param cbWrite The number of bytes being written. 3580 * @param pGCPhys OutWhere to store the translated physical address.4064 * @param pGCPhysSpa Where to store the translated physical address. 3581 4065 * 3582 4066 * @thread Any. 3583 4067 */ 3584 static int iommuAmdDeviceMemWrite(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t u Dva, size_t cbWrite, PRTGCPHYS pGCPhysOut)3585 { 3586 RT_NOREF(pDevIns, uDevId, u Dva, cbWrite, pGCPhysOut);4068 static int iommuAmdDeviceMemWrite(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uIova, size_t cbWrite, PRTGCPHYS pGCPhysSpa) 4069 { 4070 RT_NOREF(pDevIns, uDevId, uIova, cbWrite, pGCPhysSpa); 3587 4071 return VERR_NOT_IMPLEMENTED; 3588 4072 } … … 3731 4215 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); 3732 4216 3733 LogFlow((IOMMU_LOG_PFX ": %s: pThis=%p pszArgs=%s\n", __PRETTY_FUNCTION__, pThis, pszArgs));4217 LogFlow((IOMMU_LOG_PFX ": iommuAmdR3DbgInfo: pThis=%p pszArgs=%s\n", pThis, pszArgs)); 3734 4218 bool const fVerbose = !strncmp(pszArgs, RT_STR_TUPLE("verbose")) ? true : false; 3735 4219 -
trunk/src/VBox/VMM/include/PDMInternal.h
r83987 r84170 631 631 /** @copydoc PDMIOMMUREGR3::pfnMemRead */ 632 632 DECLR3CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbRead, 633 PRTGCPHYS pGCPhys Out));633 PRTGCPHYS pGCPhysSpa)); 634 634 /** @copydoc PDMIOMMUREGR3::pfnMemWrite */ 635 635 DECLR3CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbWrite, 636 PRTGCPHYS pGCPhys Out));636 PRTGCPHYS pGCPhysSpa)); 637 637 } PDMIOMMU; 638 638 … … 651 651 /** @copydoc PDMIOMMUREGR0::pfnMemRead */ 652 652 DECLR0CALLBACKMEMBER(int, pfnMemRead,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbRead, 653 PRTGCPHYS pGCPhys Out));653 PRTGCPHYS pGCPhysSpa)); 654 654 /** @copydoc PDMIOMMUREGR3::pfnMemWrite */ 655 655 DECLR0CALLBACKMEMBER(int, pfnMemWrite,(PPDMDEVINS pDevIns, uint16_t uDevId, uint64_t uDva, size_t cbWrite, 656 PRTGCPHYS pGCPhys Out));656 PRTGCPHYS pGCPhysSpa)); 657 657 } PDMIOMMUR0; 658 658 /** Pointer to a ring-0 IOMMU data. */
Note:
See TracChangeset
for help on using the changeset viewer.