Changeset 88625 in vbox for trunk/src/VBox
- Timestamp:
- Apr 21, 2021 8:09:20 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88623 r88625 171 171 /** The MMIO handle. */ 172 172 IOMMMIOHANDLE hMmio; 173 /** The event semaphore the queued-invalidation thread waits on. */ 174 SUPSEMEVENT hEvtQueuedInvThread; 175 /** Whether the queued-invalidation thread has been signaled. */ 176 bool volatile fQueuedInvThreadSignaled; 177 /** Padding. */ 178 bool afPadding0[3]; 179 /** Error diagnostic. */ 180 DMARDIAG enmDiag; 173 181 174 182 /** Registers (group 0). */ … … 182 190 uint8_t uVerReg; 183 191 /** Alignment. */ 184 uint8_t abPadding[3]; 185 /** Error diagnostic. */ 186 DMARDIAG enmDiag; 192 uint8_t abPadding[7]; 187 193 /** Copy of CAP_REG. */ 188 194 uint64_t fCap; … … 215 221 /** Pointer to the const DMAR device state. */ 216 222 typedef DMAR const *PCDMAR; 223 AssertCompileMemberAlignment(DMAR, abRegs0, 8); 224 AssertCompileMemberAlignment(DMAR, abRegs1, 8); 217 225 218 226 /** … … 225 233 /** The IOMMU helper. */ 226 234 R3PTRTYPE(PCPDMIOMMUHLPR3) pIommuHlpR3; 235 /** The queued-invalidation thread. */ 236 R3PTRTYPE(PPDMTHREAD) pQueuedInvThread; 227 237 } DMARR3; 228 238 /** Pointer to the ring-3 DMAR device state. */ … … 514 524 515 525 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 526 /** @todo Add IOMMU struct size/alignment verification, see 527 * Devices/testcase/Makefile.kmk and 528 * Devices/testcase/tstDeviceStructSize[RC].cpp */ 529 516 530 /** 517 531 * Gets the number of supported adjusted guest-address width (SAGAW) in bits given a … … 1001 1015 if (off == VTD_MMIO_OFF_IQT_REG) 1002 1016 { 1003 /* Verify if the queue tail offset is aligned according to the descriptor width in IQA_REG. */1004 1017 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1005 uint16_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg); 1018 1019 /* Verify if the queue tail offset is aligned according to the descriptor width. */ 1020 uint32_t const offQueueTail = VTD_IQT_REG_GET_QT(uIqtReg); 1006 1021 uint64_t const uIqaReg = dmarRegRead64(pThis, VTD_MMIO_OFF_IQA_REG); 1007 1022 uint8_t const fDw = RT_BF_GET(uIqaReg, VTD_BF_IQA_REG_DW); … … 1009 1024 || !(offQueueTail & 0x1f)) 1010 1025 { 1011 /** @todo Figure out what to do here, like waking up worker thread or 1012 * something. */ 1026 /* Don't bother waking the thread if an invalidation-queue error is pending. */ 1027 uint32_t const uFstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_FSTS_REG); 1028 if (!(uFstsReg & VTD_BF_FSTS_REG_IQE_MASK)) 1029 { 1030 /** @todo Figure out what to do here, like waking up worker thread or 1031 * something. */ 1032 } 1013 1033 } 1014 1034 else … … 1038 1058 if (fDw == VTD_IQA_REG_DW_256_BIT) 1039 1059 { 1040 uint64_t const fDwMask = VTD_BF_ECAP_REG_SMTS_MASK | VTD_BF_ECAP_REG_ADMS_MASK; 1041 bool const fSupports256BitDw = RT_BOOL(pThis->fExtCap & fDwMask); 1060 bool const fSupports256BitDw = RT_BOOL(pThis->fExtCap & (VTD_BF_ECAP_REG_SMTS_MASK | VTD_BF_ECAP_REG_ADMS_MASK)); 1042 1061 if (fSupports256BitDw) 1043 1062 { /* likely */ } … … 1133 1152 switch (off) 1134 1153 { 1154 case VTD_MMIO_OFF_CCMD_REG: 1155 case VTD_MMIO_OFF_CCMD_REG + 4: 1156 { 1157 rcStrict = dmarCcmdRegWrite(pDevIns, offReg, cb, uRegWritten); 1158 break; 1159 } 1160 1135 1161 case VTD_MMIO_OFF_IQT_REG: 1136 1162 case VTD_MMIO_OFF_IQT_REG + 4: 1137 1163 { 1138 1164 rcStrict = dmarIqtRegWrite(pDevIns, offReg, uRegWritten); 1139 break;1140 }1141 1142 case VTD_MMIO_OFF_CCMD_REG:1143 case VTD_MMIO_OFF_CCMD_REG + 4:1144 {1145 rcStrict = dmarCcmdRegWrite(pDevIns, offReg, cb, uRegWritten);1146 1165 break; 1147 1166 } … … 1197 1216 1198 1217 #ifdef IN_RING3 1218 /** 1219 * The queued-invalidation thread function. 1220 * 1221 * @returns VBox status code. 1222 * @param pDevIns The IOMMU device instance. 1223 * @param pThread The command thread. 1224 */ 1225 static DECLCALLBACK(int) dmarR3QueuedInvThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1226 { 1227 NOREF(pThread); 1228 LogFlowFunc(("\n")); 1229 1230 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 1231 return VINF_SUCCESS; 1232 1233 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1234 PCDMARR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARR3); 1235 1236 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 1237 { 1238 /* 1239 * Sleep until we are woken up. 1240 */ 1241 bool const fSignaled = ASMAtomicXchgBool(&pThis->fQueuedInvThreadSignaled, false); 1242 if (!fSignaled) 1243 { 1244 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtQueuedInvThread, RT_INDEFINITE_WAIT); 1245 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 1246 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) 1247 break; 1248 ASMAtomicWriteBool(&pThis->fQueuedInvThreadSignaled, false); 1249 } 1250 1251 /* 1252 * Fetch and process queued-invalidation requests. 1253 */ 1254 DMAR_LOCK_RET(pDevIns, pThisR3, VERR_IGNORED); 1255 uint32_t const uGstsReg = dmarRegRead32(pThis, VTD_MMIO_OFF_GSTS_REG); 1256 DMAR_UNLOCK(pDevIns, pThisR3); 1257 1258 if (uGstsReg & VTD_BF_GSTS_REG_QIES_MASK) 1259 { 1260 /** @todo Read invalidation descriptors and perform invalidation. */ 1261 } 1262 } 1263 1264 LogFlowFunc(("Queued-invalidation thread terminating\n")); 1265 return VINF_SUCCESS; 1266 } 1267 1268 1269 /** 1270 * Wakes up the queued-invalidation thread so it can respond to a state change. 1271 * 1272 * @returns VBox status code. 1273 * @param pDevIns The IOMMU device instance. 1274 * @param pThread The queued-invalidation thread. 1275 * 1276 * @thread EMT. 1277 */ 1278 static DECLCALLBACK(int) dmarR3QueuedInvThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread) 1279 { 1280 RT_NOREF(pThread); 1281 LogFlowFunc(("\n")); 1282 PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1283 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtQueuedInvThread); 1284 } 1285 1286 1199 1287 /** 1200 1288 * @callback_method_impl{FNDBGFHANDLERDEV} … … 1370 1458 static DECLCALLBACK(int) iommuIntelR3Destruct(PPDMDEVINS pDevIns) 1371 1459 { 1372 RT_NOREF(pDevIns);1460 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1373 1461 LogFlowFunc(("\n")); 1462 1463 if (pThis->hEvtQueuedInvThread != NIL_SUPSEMEVENT) 1464 { 1465 PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtQueuedInvThread); 1466 pThis->hEvtQueuedInvThread = NIL_SUPSEMEVENT; 1467 } 1468 1374 1469 return VINF_SUCCESS; 1375 1470 } … … 1458 1553 AssertCompile(!(DMAR_MMIO_BASE_PHYSADDR & X86_PAGE_4K_OFFSET_MASK)); 1459 1554 rc = PDMDevHlpMmioCreateAndMap(pDevIns, DMAR_MMIO_BASE_PHYSADDR, DMAR_MMIO_SIZE, dmarMmioWrite, dmarMmioRead, 1460 IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED, 1461 "Intel-IOMMU",&pThis->hMmio);1462 Assert RCReturn(rc, rc);1555 IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED, "Intel-IOMMU", 1556 &pThis->hMmio); 1557 AssertLogRelRCReturn(rc, rc); 1463 1558 1464 1559 /* 1465 1560 * Register debugger info items. 1466 1561 */ 1467 PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", dmarR3DbgInfo); 1562 rc = PDMDevHlpDBGFInfoRegister(pDevIns, "iommu", "Display IOMMU state.", dmarR3DbgInfo); 1563 AssertLogRelRCReturn(rc, rc); 1468 1564 1469 1565 #ifdef VBOX_WITH_STATISTICS … … 1497 1593 */ 1498 1594 dmarR3RegsInit(pDevIns); 1595 1596 /* 1597 * Create queued-invalidation thread and semaphore. 1598 */ 1599 char szQueuedInvThread[32]; 1600 RT_ZERO(szQueuedInvThread); 1601 RTStrPrintf(szQueuedInvThread, sizeof(szQueuedInvThread), "IOMMU-QI-%u", iInstance); 1602 rc = PDMDevHlpThreadCreate(pDevIns, &pThisR3->pQueuedInvThread, pThis, dmarR3QueuedInvThread, dmarR3QueuedInvThreadWakeUp, 1603 0 /* cbStack */, RTTHREADTYPE_IO, szQueuedInvThread); 1604 AssertLogRelRCReturn(rc, rc); 1605 1606 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtQueuedInvThread); 1607 AssertLogRelRCReturn(rc, rc); 1499 1608 1500 1609 /* … … 1506 1615 uint16_t const offFrcd = RT_BF_GET(pThis->fCap, VTD_BF_CAP_REG_FRO); 1507 1616 uint16_t const offIva = RT_BF_GET(pThis->fExtCap, VTD_BF_ECAP_REG_IRO); 1508 LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits, FRO=%#x, IRO=%#x) mapped at %#RGp\n", DMAR_LOG_PFX,1509 RT_BF_GET(uVerReg, VTD_BF_VER_REG_MAX), RT_BF_GET(uVerReg, VTD_BF_VER_REG_MIN),1617 LogRel(("%s: VER=%u.%u CAP=%#RX64 ECAP=%#RX64 (MGAW=%u bits, SAGAW=%u bits, FRO=%#x, IRO=%#x) mapped at %#RGp\n", 1618 DMAR_LOG_PFX, RT_BF_GET(uVerReg, VTD_BF_VER_REG_MAX), RT_BF_GET(uVerReg, VTD_BF_VER_REG_MIN), 1510 1619 pThis->fCap, pThis->fExtCap, cMaxGstAddrBits, cSupGstAddrBits, offFrcd, offIva, DMAR_MMIO_BASE_PHYSADDR)); 1620 1511 1621 return VINF_SUCCESS; 1512 1622 }
Note:
See TracChangeset
for help on using the changeset viewer.