Changeset 89312 in vbox for trunk/src/VBox/Devices
- Timestamp:
- May 27, 2021 10:44:15 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r89307 r89312 306 306 /** @} */ 307 307 308 /** Host-address width (HAW) mask. */308 /** Host-address width (HAW) valid mask. */ 309 309 uint64_t fHawMask; 310 /** Maximum guest-address width (MGAW) mask. */310 /** Maximum guest-address width (MGAW) valid mask. */ 311 311 uint64_t fMgawMask; 312 312 … … 432 432 /** The extended attributes of the request (VTD_REQ_ATTR_XXX). */ 433 433 uint8_t fReqAttr; 434 /** Padding. */435 uint8_t bPadding;434 /** The fault processing disabled (FPD) bit. */ 435 uint8_t fFpd; 436 436 /** The PASID if present, can be NIL_PCIPASID. */ 437 437 PCIPASID Pasid; … … 451 451 /** The size of the contiguous translated region (in bytes). */ 452 452 size_t cbContiguous; 453 /** The domain ID. */ 454 uint16_t idDomain; 453 455 } DMARADDRMAP; 454 456 /** Pointer to a DMA address remapping object. */ … … 1406 1408 static void dmarAtFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDATFAULT enmAtFault, PCDMARADDRMAP pAddrRemap) 1407 1409 { 1408 uint8_t const fType1 = pAddrRemap->enmReqType & RT_BIT(1); 1409 uint8_t const fType2 = pAddrRemap->enmReqType & RT_BIT(0); 1410 uint8_t const fExec = pAddrRemap->fReqAttr & VTD_REQ_ATTR_EXE; 1411 uint8_t const fPriv = pAddrRemap->fReqAttr & VTD_REQ_ATTR_PRIV; 1412 uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, pAddrRemap->idDevice) 1413 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2, fType2) 1414 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PP, PCIPASID_IS_VALID(pAddrRemap->Pasid)) 1415 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_EXE, fExec) 1416 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PRIV, fPriv) 1417 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR, enmAtFault) 1418 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PV, PCIPASID_VAL(pAddrRemap->Pasid)) 1419 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_AT, pAddrRemap->enmAddrType) 1420 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T1, fType1) 1421 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F, 1); 1422 uint64_t const uFrcdLo = pAddrRemap->uDmaAddr & X86_PAGE_BASE_MASK; 1423 dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo); 1424 } 1425 1426 1427 /** 1428 * Records a qualified address translation fault. 1429 * 1430 * Qualified faults are those that can be suppressed by software using the FPD bit 1431 * in the contex entry, scalable-mode context entry etc. 1432 * 1433 * This is to be used when Device-TLB, and PASIDs are not supported or for requests 1434 * where the device-TLB and PASID is not relevant/present. 1435 * 1436 * @param pDevIns The IOMMU device instance. 1437 * @param enmDiag The diagnostic reason. 1438 * @param enmAtFault The address translation fault reason. 1439 * @param pAddrRemap The DMA address remap info. 1440 * @param uPagingEntryQw0 The first qword of the paging entry. 1441 */ 1442 static void dmarAtFaultQualifiedRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTDATFAULT enmAtFault, PCDMARADDRMAP pAddrRemap, 1443 uint64_t uPagingEntryQw0) 1444 { 1445 AssertCompile( VTD_BF_0_CONTEXT_ENTRY_FPD_MASK == 0x2 1446 && VTD_BF_0_SM_CONTEXT_ENTRY_FPD_MASK == 0x2 1447 && VTD_BF_0_SM_CONTEXT_ENTRY_FPD_MASK == 0x2 1448 && VTD_BF_SM_PASID_DIR_ENTRY_FPD_MASK == 0x2 1449 && VTD_BF_0_SM_PASID_TBL_ENTRY_FPD_MASK == 0x2); 1450 if (!(uPagingEntryQw0 & VTD_BF_0_CONTEXT_ENTRY_FPD_MASK)) 1451 dmarAtFaultRecord(pDevIns, enmDiag, enmAtFault, pAddrRemap); 1410 /* 1411 * Qualified faults are those that can be suppressed by software using the FPD bit 1412 * in the contex entry, scalable-mode context entry etc. 1413 */ 1414 if (!pAddrRemap->fFpd) 1415 { 1416 uint8_t const fType1 = pAddrRemap->enmReqType & RT_BIT(1); 1417 uint8_t const fType2 = pAddrRemap->enmReqType & RT_BIT(0); 1418 uint8_t const fExec = pAddrRemap->fReqAttr & VTD_REQ_ATTR_EXE; 1419 uint8_t const fPriv = pAddrRemap->fReqAttr & VTD_REQ_ATTR_PRIV; 1420 uint64_t const uFrcdHi = RT_BF_MAKE(VTD_BF_1_FRCD_REG_SID, pAddrRemap->idDevice) 1421 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T2, fType2) 1422 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PP, PCIPASID_IS_VALID(pAddrRemap->Pasid)) 1423 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_EXE, fExec) 1424 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PRIV, fPriv) 1425 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_FR, enmAtFault) 1426 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_PV, PCIPASID_VAL(pAddrRemap->Pasid)) 1427 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_AT, pAddrRemap->enmAddrType) 1428 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_T1, fType1) 1429 | RT_BF_MAKE(VTD_BF_1_FRCD_REG_F, 1); 1430 uint64_t const uFrcdLo = pAddrRemap->uDmaAddr & X86_PAGE_BASE_MASK; 1431 dmarPrimaryFaultRecord(pDevIns, enmDiag, uFrcdHi, uFrcdLo); 1432 } 1452 1433 } 1453 1434 … … 1868 1849 static int dmarDrReadCtxEntry(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCtxTable, uint8_t idxCtxEntry, PVTD_CONTEXT_ENTRY_T pCtxEntry) 1869 1850 { 1851 /* We don't verify bits 63:HAW of GCPhysCtxTable is 0 since reading from such an address should fail anyway. */ 1870 1852 size_t const cbCtxEntry = sizeof(*pCtxEntry); 1871 1853 RTGCPHYS const GCPhysCtxEntry = GCPhysCtxTable + (idxCtxEntry * cbCtxEntry); 1872 1854 return PDMDevHlpPhysReadMeta(pDevIns, GCPhysCtxEntry, pCtxEntry, cbCtxEntry); 1855 } 1856 1857 1858 /** 1859 * Reads a second-level paging entry from guest memory. 1860 * 1861 * @returns VBox status code. 1862 * @param pDevIns The IOMMU device instance. 1863 * @param GCPhysSlptPtr The physical address of the SLPTPTR. 1864 * @param pSlpEntry Where to store the read SLPTPTR. 1865 */ 1866 static int dmarDrReadSlpPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhysSlptPtr, PVTD_SLP_ENTRY_T pSlpEntry) 1867 { 1868 /* We don't verify bits 63:HAW of GCPhysSlptPtr is 0 since reading from such an address should fail anyway. */ 1869 return PDMDevHlpPhysReadMeta(pDevIns, GCPhysSlptPtr, pSlpEntry, sizeof(*pSlpEntry)); 1870 } 1871 1872 1873 /** 1874 * Performs second level translation. 1875 * 1876 * @returns VBox status code. 1877 * @param pDevIns The IOMMU device instance. 1878 * @param SlpEntry The second-level paging entry. 1879 * @param pAddrRemap The DMA address remap info. 1880 */ 1881 static int dmarDrSecondLevelTranslate(PPDMDEVINS pDevIns, VTD_SLP_ENTRY_T SlpEntry, PDMARADDRMAP pAddrRemap) 1882 { 1883 RT_NOREF3(pDevIns, SlpEntry, pAddrRemap); 1884 /** @todo Implement me */ 1885 return VERR_NOT_IMPLEMENTED; 1873 1886 } 1874 1887 … … 1884 1897 static int dmarDrLegacyModeRemapAddr(PPDMDEVINS pDevIns, uint64_t uRtaddrReg, PDMARADDRMAP pAddrRemap) 1885 1898 { 1899 /* Read the root-entry from guest memory. */ 1886 1900 uint8_t const idxRootEntry = RT_HI_U8(pAddrRemap->idDevice); 1887 1901 VTD_ROOT_ENTRY_T RootEntry; … … 1889 1903 if (RT_SUCCESS(rc)) 1890 1904 { 1905 /* Check if the root entry is present (must be done before validating reserved bits). */ 1891 1906 uint64_t const uRootEntryQword0 = RootEntry.au64[0]; 1892 1907 uint64_t const uRootEntryQword1 = RootEntry.au64[1]; … … 1894 1909 if (fRootEntryPresent) 1895 1910 { 1911 /* Validate reserved bits in the root entry. */ 1896 1912 if ( !(uRootEntryQword0 & ~VTD_ROOT_ENTRY_0_VALID_MASK) 1897 1913 && !(uRootEntryQword1 & ~VTD_ROOT_ENTRY_1_VALID_MASK)) 1898 1914 { 1915 /* Read the context-entry from guest memory. */ 1899 1916 RTGCPHYS const GCPhysCtxTable = RT_BF_GET(uRootEntryQword0, VTD_BF_0_ROOT_ENTRY_CTP); 1900 1917 uint8_t const idxCtxEntry = RT_LO_U8(pAddrRemap->idDevice); 1901 1918 VTD_CONTEXT_ENTRY_T CtxEntry; 1902 /* We don't verify bits 63:HAW of GCPhysCtxTable is 0 since reading from such an address should fail anyway. */1903 1919 rc = dmarDrReadCtxEntry(pDevIns, GCPhysCtxTable, idxCtxEntry, &CtxEntry); 1904 1920 if (RT_SUCCESS(rc)) … … 1906 1922 uint64_t const uCtxEntryQword0 = CtxEntry.au64[0]; 1907 1923 uint64_t const uCtxEntryQword1 = CtxEntry.au64[1]; 1924 1925 /* Note the FPD bit which software can use to supress translation faults from here on in. */ 1926 pAddrRemap->fFpd = RT_BF_GET(uCtxEntryQword0, VTD_BF_0_CONTEXT_ENTRY_FPD); 1927 1928 /* Check if the context-entry is present (must be done before validating reserved bits). */ 1908 1929 bool const fCtxEntryPresent = RT_BF_GET(uCtxEntryQword0, VTD_BF_0_CONTEXT_ENTRY_P); 1909 1930 if (fCtxEntryPresent) 1910 1931 { 1932 /* Validate reserved bits in the context-entry. */ 1911 1933 if ( !(uCtxEntryQword0 & ~VTD_CONTEXT_ENTRY_0_VALID_MASK) 1912 1934 && !(uCtxEntryQword1 & ~VTD_CONTEXT_ENTRY_1_VALID_MASK)) 1913 1935 { 1936 /* Validate the translation type (TT). */ 1914 1937 PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PCDMAR); 1915 1938 uint8_t const fTt = RT_BF_GET(uCtxEntryQword0, VTD_BF_0_CONTEXT_ENTRY_TT); … … 1918 1941 case 0: 1919 1942 { 1943 /* 1944 * Untranslated requests are translated using second-level paging structures referenced 1945 * through SLPTPTR. Translated requests and Translation Requests are blocked. 1946 */ 1920 1947 if (pAddrRemap->enmAddrType == PCIADDRTYPE_UNTRANSLATED) 1921 1948 { 1949 /* Validate the address width. */ 1922 1950 if (dmarDrLegacyModeIsAwValid(pThis, &CtxEntry)) 1923 1951 { 1924 1925 return VERR_NOT_IMPLEMENTED; 1952 /* Read the SLPTPTR from guest memory. */ 1953 RTGCPHYS const GCPhysSlptPtr = uCtxEntryQword0 & VTD_BF_0_CONTEXT_ENTRY_SLPTPTR_MASK; 1954 VTD_SLP_ENTRY_T SlpEntry; 1955 rc = dmarDrReadSlpPtr(pDevIns, GCPhysSlptPtr, &SlpEntry); 1956 if (RT_SUCCESS(rc)) 1957 { 1958 /* Note the domain ID this context-entry maps to. */ 1959 pAddrRemap->idDomain = RT_BF_GET(uCtxEntryQword1, VTD_BF_1_CONTEXT_ENTRY_DID); 1960 1961 /* Finally... perform second-level translation. */ 1962 return dmarDrSecondLevelTranslate(pDevIns, SlpEntry, pAddrRemap); 1963 } 1964 dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lct_4_3, VTDATFAULT_LCT_4_3, pAddrRemap); 1926 1965 } 1927 1966 else 1928 dmarAtFaultQualifiedRecord(pDevIns, kDmarDiag_Atf_Lct_4_1, VTDATFAULT_LCT_4_1, 1929 pAddrRemap, uCtxEntryQword0); 1967 dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lct_4_1, VTDATFAULT_LCT_4_1, pAddrRemap); 1930 1968 } 1969 1931 1970 Log4Func(("Translation type blocks translated and translation requests\n")); 1932 1971 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; … … 1935 1974 case 2: 1936 1975 { 1937 if (pThis->fExtCapReg & VTD_BF_ECAP_REG_PT_MASK) 1976 /* 1977 * Untranslated requests are processed as pass-through (PT) if pass-through is supported. 1978 * Translated and translation requests are blocked. If PT isn't supported this TT value 1979 * is reserved which I assume raises a fault (hence fallthru below). 1980 */ 1981 if ( (pThis->fExtCapReg & VTD_BF_ECAP_REG_PT_MASK) 1982 && (pAddrRemap->enmAddrType == PCIADDRTYPE_UNTRANSLATED)) 1938 1983 { 1939 1984 pAddrRemap->GCPhysSpa = pAddrRemap->uDmaAddr; … … 1946 1991 case 1: 1947 1992 { 1993 /* We don't support device-TLBs, so this TT value is treated as reserved. */ 1948 1994 Assert(!(pThis->fExtCapReg & VTD_BF_ECAP_REG_DT_MASK)); 1949 1995 RT_FALL_THRU(); … … 1952 1998 default: 1953 1999 { 1954 dmarAtFaultQualifiedRecord(pDevIns, kDmarDiag_Atf_Lct_4_2, VTDATFAULT_LCT_4_2, pAddrRemap,1955 uCtxEntryQword0);2000 /* Any other TT value is reserved. */ 2001 dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lct_4_2, VTDATFAULT_LCT_4_2, pAddrRemap); 1956 2002 break; 1957 2003 } … … 1959 2005 } 1960 2006 else 1961 dmarAtFaultQualifiedRecord(pDevIns, kDmarDiag_Atf_Lct_3, VTDATFAULT_LCT_3, pAddrRemap, 1962 uCtxEntryQword0); 2007 dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lct_3, VTDATFAULT_LCT_3, pAddrRemap); 1963 2008 } 1964 2009 else 1965 dmarAtFaultQualifiedRecord(pDevIns, kDmarDiag_Atf_Lct_2, VTDATFAULT_LCT_2, pAddrRemap, 1966 uCtxEntryQword0); 2010 dmarAtFaultRecord(pDevIns, kDmarDiag_Atf_Lct_2, VTDATFAULT_LCT_2, pAddrRemap); 1967 2011 } 1968 2012 else … … 3130 3174 } 3131 3175 3132 uint8_t const fFlts = 1; /* First- Level translation support. */3133 uint8_t const fSlts = 1; /* Second- Level translation support. */3176 uint8_t const fFlts = 1; /* First-level translation support. */ 3177 uint8_t const fSlts = 1; /* Second-level translation support. */ 3134 3178 uint8_t const fPt = 1; /* Pass-Through support. */ 3135 3179 uint8_t const fSmts = fFlts & fSlts & fPt; /* Scalable mode translation support.*/ … … 3142 3186 PDMDevHlpCpuGetGuestAddrWidths(pDevIns, &cGstPhysAddrBits, &cGstLinearAddrBits); 3143 3187 3144 uint8_t const fFl1gp = 1; /* First- Level 1GB pages support. */3188 uint8_t const fFl1gp = 1; /* First-level 1GB pages support. */ 3145 3189 uint8_t const fFl5lp = 1; /* First-level 5-level paging support (PML5E). */ 3146 uint8_t const fSl2mp = 1; /* Second- Level 2MB pages support. */3147 uint8_t const fSl2gp = fSl2mp & 1; /* Second- Level 1GB pages support. */3148 uint8_t const fSllps = fSl2mp | (fSl2gp << 1); /* Second- Level large page Support. */3190 uint8_t const fSl2mp = 1; /* Second-level 2MB pages support. */ 3191 uint8_t const fSl2gp = fSl2mp & 1; /* Second-level 1GB pages support. */ 3192 uint8_t const fSllps = fSl2mp | (fSl2gp << 1); /* Second-level large page support. */ 3149 3193 uint8_t const fMamv = (fSl2gp ? X86_PAGE_1G_SHIFT /* Maximum address mask value (for 2nd-level invalidations). */ 3150 3194 : X86_PAGE_2M_SHIFT)
Note:
See TracChangeset
for help on using the changeset viewer.