Changeset 88704 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Apr 26, 2021 3:26:56 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88697 r88704 24 24 #include "DevIommuIntel.h" 25 25 26 #include <iprt/mem.h> 26 27 #include <iprt/string.h> 27 28 … … 143 144 kDmarDiag_None = 0, 144 145 kDmarDiag_IqtReg_Qt_NotAligned, 146 kDmarDiag_IqtReg_Qt_Invalid, 145 147 kDmarDiag_IqaReg_Dw_Invalid, 148 kDmarDiag_IqaReg_Dsc_Fetch_Failed, 146 149 kDmarDiag_CcmdReg_Ttm_Invalid, 147 150 kDmarDiag_CcmdReg_Qi_Enabled, … … 158 161 static const char *const g_apszDmarDiagDesc[] = 159 162 { 160 DMARDIAG_DESC(kNone , "None" ), 161 DMARDIAG_DESC(kDmarDiag_IqtReg_Qt_NotAligned, "IqtReg_Qt_NotAligned"), 162 DMARDIAG_DESC(kDmarDiag_IqaReg_Dw_Invalid , "IqaReg_Dw_Invalid" ), 163 DMARDIAG_DESC(kDmarDiag_CcmdReg_Ttm_Invalid , "CcmdReg_Ttm_Invalid" ), 164 DMARDIAG_DESC(kDmarDiag_CcmdReg_Qi_Enabled , "CcmdReg_Qi_Enabled" ), 165 DMARDIAG_DESC(kDmarDiag_CcmdReg_NotSupported, "CcmdReg_NotSupported") 163 DMARDIAG_DESC(kNone , "None" ), 164 DMARDIAG_DESC(kDmarDiag_IqtReg_Qt_NotAligned , "IqtReg_Qt_NotAligned" ), 165 DMARDIAG_DESC(kDmarDiag_IqtReg_Qt_Invalid , "IqtReg_Qt_Invalid" ), 166 DMARDIAG_DESC(kDmarDiag_IqaReg_Dw_Invalid , "IqaReg_Dw_Invalid" ), 167 DMARDIAG_DESC(kDmarDiag_IqaReg_Dsc_Fetch_Failed, "IqaReg_Dsc_Fetch_Failed"), 168 DMARDIAG_DESC(kDmarDiag_CcmdReg_Ttm_Invalid , "CcmdReg_Ttm_Invalid" ), 169 DMARDIAG_DESC(kDmarDiag_CcmdReg_Qi_Enabled , "CcmdReg_Qi_Enabled" ), 170 DMARDIAG_DESC(kDmarDiag_CcmdReg_NotSupported , "CcmdReg_NotSupported" ) 166 171 /* kDmarDiag_End */ 167 172 }; … … 863 868 * Checks if the invalidation-queue is empty. 864 869 * 870 * Extended version which optionally returns the current queue head and tail 871 * offsets. 872 * 865 873 * @returns @c true if empty, @c false otherwise. 866 874 * @param pThis The shared DMAR device state. 867 */ 868 static bool dmarInvQueueIsEmpty(PCDMAR pThis) 869 { 870 uint64_t const uIqtReg = dmarRegReadRaw64(pThis, VTD_MMIO_OFF_IQT_REG); 871 uint64_t const uIqhReg = dmarRegReadRaw64(pThis, VTD_MMIO_OFF_IQH_REG); 872 /* Don't bother masking out QT, QH out of IQT_REG, IQH_REG since all other bits are RsvdZ. */ 875 * @param poffQh Where to store the queue head offset. Optional, can be NULL. 876 * @param poffQt Where to store the queue tail offset. Optional, can be NULL. 877 */ 878 static bool dmarInvQueueIsEmptyEx(PCDMAR pThis, uint32_t *poffQh, uint32_t *poffQt) 879 { 880 /* Read only the low-32 bits of the queue head and queue tail registers as high bits are all reserved.*/ 881 uint32_t const uIqtReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IQT_REG); 882 uint32_t const uIqhReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IQH_REG); 883 884 /* Don't bother masking QT, QH out of IQT_REG, IQH_REG since all other bits are RsvdZ. */ 873 885 Assert(!(uIqtReg & ~VTD_BF_IQT_REG_QT_MASK)); 874 886 Assert(!(uIqhReg & ~VTD_BF_IQH_REG_QH_MASK)); 887 if (poffQh) 888 *poffQh = uIqhReg; 889 if (poffQt) 890 *poffQt = uIqtReg; 875 891 return uIqtReg == uIqhReg; 892 } 893 894 895 /** 896 * Checks if the invalidation-queue is empty. 897 * 898 * @returns @c true if empty, @c false otherwise. 899 * @param pThis The shared DMAR device state. 900 */ 901 static bool dmarInvQueueIsEmpty(PCDMAR pThis) 902 { 903 return dmarInvQueueIsEmptyEx(pThis, NULL /* poffQh */, NULL /* poffQt */); 876 904 } 877 905 … … 1016 1044 * @param enmDiag The diagnostic reason. 1017 1045 */ 1018 static void dmarIqeFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTD_IQE RCD_IQEI_T enmIqei)1046 static void dmarIqeFaultRecord(PPDMDEVINS pDevIns, DMARDIAG enmDiag, VTD_IQEI_T enmIqei) 1019 1047 { 1020 1048 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); … … 1149 1177 /* Hardware treats bit 4 as RsvdZ in this situation, so clear it. */ 1150 1178 dmarRegChangeRaw32(pThis, offReg, ~RT_BIT(4) /* fAndMask*/ , 0 /* fOrMask */); 1151 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_NotAligned, k QueueTailNotAligned);1179 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_NotAligned, kIqei_QueueTailNotAligned); 1152 1180 } 1153 1181 return VINF_SUCCESS; … … 1180 1208 { /* likely */ } 1181 1209 else 1182 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqaReg_Dw_Invalid, kI nvalidDescriptorWidth);1210 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqaReg_Dw_Invalid, kIqei_InvalidDescriptorWidth); 1183 1211 } 1184 1212 return VINF_SUCCESS; … … 1361 1389 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 1362 1390 return VINF_SUCCESS; 1391 1392 uint8_t const cMaxPages = 1 << VTD_BF_IQA_REG_QS_MASK; 1393 size_t const cbMaxQs = cMaxPages << X86_PAGE_SHIFT; 1394 void *pvQueue = RTMemAllocZ(cbMaxQs); 1395 AssertPtrReturn(pvQueue, VERR_NO_MEMORY); 1363 1396 1364 1397 while (pThread->enmState == PDMTHREADSTATE_RUNNING) … … 1383 1416 if (dmarInvQueueCanProcessRequests(pThis)) 1384 1417 { 1385 /** @todo Read IQH and IQT, descriptors from memory and perform invalidation. */ 1418 uint32_t offQueueHead; 1419 uint32_t offQueueTail; 1420 bool const fIsEmpty = dmarInvQueueIsEmptyEx(pThis, &offQueueHead, &offQueueTail); 1421 if (!fIsEmpty) 1422 { 1423 uint64_t const uIqaReg = dmarRegRead64(pThis, VTD_MMIO_OFF_IQA_REG); 1424 uint8_t const cQueuePages = 1 << (uIqaReg & VTD_BF_IQA_REG_QS_MASK); 1425 uint32_t const cbQueue = cQueuePages << X86_PAGE_SHIFT; 1426 if (offQueueTail <= cbQueue) 1427 { 1428 uint32_t const cbDescriptors = offQueueTail - offQueueHead; 1429 RTGCPHYS const GCPhysQueueBase = uIqaReg & VTD_BF_IQA_REG_IQA_MASK; 1430 1431 DMAR_UNLOCK(pDevIns, pThisR3); 1432 int rc = PDMDevHlpPhysRead(pDevIns, GCPhysQueueBase, pvQueue, cbDescriptors); 1433 DMAR_LOCK(pDevIns, pThisR3); 1434 1435 if (RT_SUCCESS(rc)) 1436 { 1437 /** @todo Handle RTADDR_REG MMIO write first, for handling kIqei_InvalidTtm. I 1438 * don't think it needs to be checked/handled here? */ 1439 /** @todo Process invalidation descriptors. */ 1440 } 1441 else 1442 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqaReg_Dsc_Fetch_Failed, kIqei_FetchDescriptorFailed); 1443 } 1444 else 1445 dmarIqeFaultRecord(pDevIns, kDmarDiag_IqtReg_Qt_Invalid, kIqei_InvalidTailPointer); 1446 } 1386 1447 } 1387 1448 DMAR_UNLOCK(pDevIns, pThisR3); 1388 1449 } 1450 1451 RTMemFree(pvQueue); 1452 pvQueue = NULL; 1389 1453 1390 1454 LogFlowFunc(("Invalidation-queue thread terminating\n"));
Note:
See TracChangeset
for help on using the changeset viewer.