Changeset 89235 in vbox
- Timestamp:
- May 24, 2021 7:31:02 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144578
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/iommu-intel.h
r89223 r89235 1341 1341 1342 1342 /** 1343 * VT-d FRCD type requests (FRCD_REG::T2).1343 * VT-d faulted request types (FRCD_REG::T2). 1344 1344 * In accordance with the Intel spec. 1345 1345 */ 1346 1346 typedef enum VTDREQTYPE 1347 1347 { 1348 VTDREQTYPE_WRITE = 0, 1349 VTDREQTYPE_PAGE, 1350 VTDREQTYPE_READ, 1351 VTDREQTYPE_ATOMIC_OP 1348 VTDREQTYPE_WRITE = 0, /**< Memory access write request. */ 1349 VTDREQTYPE_PAGE, /**< Page translation request. */ 1350 VTDREQTYPE_READ, /**< Memory access read request. */ 1351 VTDREQTYPE_ATOMIC_OP /**< Memory access atomic operation. */ 1352 1352 } VTDREQTYPE; 1353 1354 1355 /** @name VT-d faulted request attributes (FRCD_REG::EXE, FRCD_REG::PRIV). 1356 * In accordance with the Intel spec. 1357 * @{ 1358 */ 1359 /** Supervisory privilege was requested. */ 1360 #define VTD_REQ_ATTR_PRIV RT_BIT(0) 1361 /** Execute permission was requested. */ 1362 #define VTD_REQ_ATTR_EXE RT_BIT(1) 1363 /** @} */ 1353 1364 1354 1365 -
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r89216 r89235 154 154 typedef enum 155 155 { 156 /* No error, this must be zero! */ 156 157 kDmarDiag_None = 0, 158 159 /* Address Translation Faults. */ 160 kDmarDiag_Atf_Rta_1_1, 161 kDmarDiag_Atf_Rta_1_2, 162 kDmarDiag_Atf_Rta_1_3, 163 164 /* CCMD_REG faults. */ 157 165 kDmarDiag_CcmdReg_NotSupported, 158 166 kDmarDiag_CcmdReg_Qi_Enabled, 159 167 kDmarDiag_CcmdReg_Ttm_Invalid, 168 169 /* IQA_REG faults. */ 160 170 kDmarDiag_IqaReg_Dsc_Fetch_Error, 161 171 kDmarDiag_IqaReg_Dw_128_Invalid, 162 172 kDmarDiag_IqaReg_Dw_256_Invalid, 173 174 /* Invalidation Queue Error Info. */ 163 175 kDmarDiag_Iqei_Dsc_Type_Invalid, 164 176 kDmarDiag_Iqei_Inv_Wait_Dsc_0_1_Rsvd, … … 166 178 kDmarDiag_Iqei_Inv_Wait_Dsc_Invalid, 167 179 kDmarDiag_Iqei_Ttm_Rsvd, 180 181 /* IQT_REG faults. */ 168 182 kDmarDiag_IqtReg_Qt_Invalid, 169 183 kDmarDiag_IqtReg_Qt_NotAligned, 184 185 /* Compatibility Format Interrupt Faults. */ 170 186 kDmarDiag_Ir_Cfi_Blocked, 187 188 /* Remappable Format Interrupt Faults. */ 171 189 kDmarDiag_Ir_Rfi_Intr_Index_Invalid, 172 190 kDmarDiag_Ir_Rfi_Irte_Mode_Invalid, … … 178 196 kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd, 179 197 kDmarDiag_Ir_Rfi_Rsvd, 198 180 199 /* Member for determining array index limit. */ 181 200 kDmarDiag_End, 182 /* Type size hack. */ 201 202 /* Usual 32-bit type size hack. */ 183 203 kDmarDiag_32Bit_Hack = 0x7fffffff 184 204 } DMARDIAG; … … 194 214 { 195 215 DMARDIAG_DESC(None ), 216 DMARDIAG_DESC(Atf_Rta_1_1 ), 217 DMARDIAG_DESC(Atf_Rta_1_2 ), 218 DMARDIAG_DESC(Atf_Rta_1_3 ), 196 219 DMARDIAG_DESC(CcmdReg_NotSupported ), 197 220 DMARDIAG_DESC(CcmdReg_Qi_Enabled ), … … 1318 1341 1319 1342 /** 1320 * Records an address translation fault .1343 * Records an address translation fault (extensive version). 1321 1344 * 1322 1345 * @param pDevIns The IOMMU device instance. … … 1330 1353 * @param fHasPasid Whether the faulted request has a PASID TLP prefix. 1331 1354 * @param uPasid The PASID value when a PASID TLP prefix is present. 1332 * @param fExec Execute permission was requested by the faulted request. 1333 * @param fPriv Supervisor privilege permission was requested by the 1334 * faulted request. 1335 */ 1336 static void dmarAddrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice, 1337 uint64_t uFaultAddr, VTDREQTYPE enmReqType, uint8_t uAddrType, bool fHasPasid, uint32_t uPasid, 1338 bool fExec, bool fPriv) 1355 * @param fReqAttr The attributes of the faulted requested 1356 * (VTD_REQ_ATTR_XXX). 1357 */ 1358 static void dmarAddrFaultRecordEx(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice, 1359 uint64_t uFaultAddr, VTDREQTYPE enmReqType, uint8_t uAddrType, bool fHasPasid, uint32_t uPasid, 1360 uint8_t fReqAttr) 1339 1361 { 1340 1362 uint8_t const fType1 = enmReqType & RT_BIT(1); 1341 1363 uint8_t const fType2 = enmReqType & RT_BIT(0); 1364 uint8_t const fExec = fReqAttr & VTD_REQ_ATTR_EXE; 1365 uint8_t const fPriv = fReqAttr & VTD_REQ_ATTR_PRIV; 1342 1366 uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, idDevice) 1343 1367 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2, fType2) … … 1352 1376 uint64_t const uFrcdLo = uFaultAddr & X86_PAGE_BASE_MASK; 1353 1377 dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo); 1378 } 1379 1380 1381 /** 1382 * Records an address translation fault. 1383 * 1384 * This is to be used when Device-TLB, and PASIDs are not supported or for requests 1385 * where the device-TLB and PASID is not relevant/present. 1386 * 1387 * @param pDevIns The IOMMU device instance. 1388 * @param enmDiag The diagnostic reason. 1389 * @param enmAddrFault The address translation fault reason. 1390 * @param idDevice The device ID (bus, device, function). 1391 * @param uFaultAddr The page address of the faulted request. 1392 * @param enmReqType The type of the faulted request. 1393 */ 1394 static void dmarAddrFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDADDRFAULT enmAddrFault, uint16_t idDevice, 1395 uint64_t uFaultAddr, VTDREQTYPE enmReqType) 1396 { 1397 dmarAddrFaultRecordEx(pDevIns, enmDiag, enmAddrFault, idDevice, uFaultAddr, enmReqType, 0 /* uAddrType */, 1398 false /* fHasPasid */, 0 /* uPasid */, 0 /* fReqAttr */); 1354 1399 } 1355 1400 … … 1709 1754 1710 1755 /** 1756 * Performs a PCI target abort for a DMA operation. 1757 * 1758 * @param pDevIns The IOMMU device instance. 1759 */ 1760 static void dmarDmaTargetAbort(PPDMDEVINS pDevIns) 1761 { 1762 /** @todo r=ramshankar: I don't know for sure if a PCI target abort is caused or not 1763 * as the Intel VT-d spec. is vague. Wording seems to suggest it does, but 1764 * who knows. */ 1765 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 1766 uint16_t const u16Status = PDMPciDevGetStatus(pPciDev) | VBOX_PCI_STATUS_SIG_TARGET_ABORT; 1767 PDMPciDevSetStatus(pPciDev, u16Status); 1768 } 1769 1770 1771 /** 1772 * Validates the table translation mode for a DMA request. 1773 * 1774 * @returns @c true if the TTM is valid, @c false otherwise. 1775 * @param pDevIns The IOMMU device instance. 1776 * @param uRtaddrReg The current RTADDR_REG value. 1777 * @param idDevice The device ID (bus, device, function). 1778 * @param uIova The I/O virtual address being accessed. 1779 * @param enmReqType The type of the request (for fault recording). 1780 */ 1781 static bool dmarDmaIsTtmValid(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, uint16_t idDevice, uint64_t uIova, VTDREQTYPE enmReqType) 1782 { 1783 bool fValid = true; 1784 PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR); 1785 uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM); 1786 switch (fTtm) 1787 { 1788 case VTD_TTM_LEGACY_MODE: 1789 break; 1790 1791 case VTD_TTM_SCALABLE_MODE: 1792 { 1793 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_SMTS_MASK) 1794 break; 1795 dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_3, VTDADDRFAULT_RTA_1_3, idDevice, uIova, enmReqType); 1796 fValid = false; 1797 break; 1798 } 1799 1800 case VTD_TTM_ABORT_DMA_MODE: 1801 { 1802 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK) 1803 dmarDmaTargetAbort(pDevIns); 1804 else 1805 dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_1, VTDADDRFAULT_RTA_1_1, idDevice, uIova, enmReqType); 1806 fValid = false; 1807 break; 1808 } 1809 1810 default: 1811 { 1812 dmarAddrFaultRecord(pDevIns, kDmarDiag_Atf_Rta_1_2, VTDADDRFAULT_RTA_1_2, idDevice, uIova, enmReqType); 1813 fValid = false; 1814 break; 1815 } 1816 } 1817 return fValid; 1818 } 1819 1820 1821 /** 1711 1822 * Memory access bulk (one or more 4K pages) request from a device. 1712 1823 * … … 1747 1858 uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous) 1748 1859 { 1749 RT_NOREF6(idDevice, uIova, cbIova, fFlags, pGCPhysSpa, pcbContiguous); 1860 /* Validate. */ 1861 AssertPtr(pDevIns); 1862 AssertPtr(pGCPhysSpa); 1863 AssertPtr(pcbContiguous); 1864 Assert(cbIova > 0); /** @todo Are we going to support ZLR (zero-length reads to write-only pages)? */ 1865 Assert(!(fFlags & ~PDMIOMMU_MEM_F_VALID_MASK)); 1750 1866 1751 1867 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); … … 1762 1878 if (fFlags & PDMIOMMU_MEM_F_READ) 1763 1879 { 1880 enmReqType = VTDREQTYPE_READ; 1764 1881 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead)); 1765 enmReqType = VTDREQTYPE_READ;1766 1882 } 1767 1883 else 1768 1884 { 1885 enmReqType = VTDREQTYPE_WRITE; 1769 1886 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite)); 1770 enmReqType = VTDREQTYPE_WRITE;1771 1887 } 1772 1888 1773 uint8_t const fTtm = RT_BF_GET(uRtaddrReg, VTD_BF_RTADDR_REG_TTM); 1774 switch (fTtm) 1775 { 1776 case VTD_TTM_LEGACY_MODE: 1777 case VTD_TTM_ABORT_DMA_MODE: 1778 { 1779 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_ADMS_MASK) 1780 { 1781 } 1782 } 1783 } 1889 bool fTtmValid = dmarDmaIsTtmValid(pDevIns, uRtaddrReg, idDevice, uIova, enmReqType); 1890 if (!fTtmValid) 1891 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 1784 1892 1785 1893 return VERR_NOT_IMPLEMENTED;
Note:
See TracChangeset
for help on using the changeset viewer.