Changeset 88781 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Apr 29, 2021 1:27:08 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88765 r88781 135 135 /** 136 136 * DMAR error diagnostics. 137 * Sorted alphabetically so it's easier to add and locate items, no other reason. 137 138 * 138 139 * @note Members of this enum are used as array indices, so no gaps in enum … … 143 144 { 144 145 kDmarDiag_None = 0, 146 kDmarDiag_CcmdReg_NotSupported, 147 kDmarDiag_CcmdReg_Qi_Enabled, 148 kDmarDiag_CcmdReg_Ttm_Invalid, 149 kDmarDiag_IqaReg_Dsc_Fetch_Error, 150 kDmarDiag_IqaReg_Dw_Invalid, 151 kDmarDiag_Iqei_Dsc_Type_Invalid, 152 kDmarDiag_Iqei_Inv_Wait_Dsc_0_1_Rsvd, 153 kDmarDiag_Iqei_Inv_Wait_Dsc_2_3_Rsvd, 154 kDmarDiag_Iqei_Inv_Wait_Dsc_Ttm, 155 kDmarDiag_IqtReg_Qt_Invalid, 145 156 kDmarDiag_IqtReg_Qt_NotAligned, 146 kDmarDiag_IqtReg_Qt_Invalid,147 kDmarDiag_IqaReg_Dw_Invalid,148 kDmarDiag_IqaReg_Dsc_Fetch_Error,149 kDmarDiag_Iqei_Dsc_Type_Invalid,150 kDmarDiag_CcmdReg_Ttm_Invalid,151 kDmarDiag_CcmdReg_Qi_Enabled,152 kDmarDiag_CcmdReg_NotSupported,153 157 /* Member for determining array index limit. */ 154 158 kDmarDiag_End, … … 163 167 #define DMARDIAG_DESC(a_Name) RT_CONCAT(kDmarDiag_, a_Name) < kDmarDiag_End ? RT_STR(a_Name) : "Ignored" 164 168 165 /** DMAR diagnostics description . */169 /** DMAR diagnostics description for members in DMARDIAG. */ 166 170 static const char *const g_apszDmarDiagDesc[] = 167 171 { 168 DMARDIAG_DESC(None ), 169 DMARDIAG_DESC(IqtReg_Qt_NotAligned ), 170 DMARDIAG_DESC(IqtReg_Qt_Invalid ), 171 DMARDIAG_DESC(IqaReg_Dw_Invalid ), 172 DMARDIAG_DESC(IqaReg_Dsc_Fetch_Error), 173 DMARDIAG_DESC(Iqei_Dsc_Type_Invalid ), 174 DMARDIAG_DESC(CcmdReg_Ttm_Invalid ), 175 DMARDIAG_DESC(CcmdReg_Qi_Enabled ), 176 DMARDIAG_DESC(CcmdReg_NotSupported ) 172 DMARDIAG_DESC(None ), 173 DMARDIAG_DESC(CcmdReg_NotSupported ), 174 DMARDIAG_DESC(CcmdReg_Qi_Enabled ), 175 DMARDIAG_DESC(CcmdReg_Ttm_Invalid ), 176 DMARDIAG_DESC(IqaReg_Dsc_Fetch_Error ), 177 DMARDIAG_DESC(IqaReg_Dw_Invalid ), 178 DMARDIAG_DESC(Iqei_Dsc_Type_Invalid ), 179 DMARDIAG_DESC(Iqei_Inv_Wait_Dsc_0_1_Rsvd), 180 DMARDIAG_DESC(Iqei_Inv_Wait_Dsc_2_3_Rsvd), 181 DMARDIAG_DESC(Iqei_Inv_Wait_Dsc_Ttm ), 182 DMARDIAG_DESC(IqtReg_Qt_Invalid ), 183 DMARDIAG_DESC(IqtReg_Qt_NotAligned ) 177 184 /* kDmarDiag_End */ 178 185 }; … … 991 998 992 999 /** 993 * Raises an interrupt in response to a nevent.1000 * Raises an interrupt in response to a fault event. 994 1001 * 995 1002 * @param pDevIns The IOMMU device instance. 996 1003 */ 997 static void dmarFault RaiseInterrupt(PPDMDEVINS pDevIns)1004 static void dmarFaultEventRaiseInterrupt(PPDMDEVINS pDevIns) 998 1005 { 999 1006 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); … … 1035 1042 } 1036 1043 } 1044 1045 1046 #ifdef IN_RING3 1047 /** 1048 * Raises an interrupt in response to an invalidation (complete) event. 1049 * 1050 * @param pDevIns The IOMMU device instance. 1051 */ 1052 static void dmarR3InvEventRaiseInterrupt(PPDMDEVINS pDevIns) 1053 { 1054 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1055 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1056 1057 uint32_t const uIcsReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_ICS_REG); 1058 if (uIcsReg & VTD_BF_ICS_REG_IWC_MASK) 1059 return; 1060 1061 uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG); 1062 if (!(uIectlReg & VTD_BF_FECTL_REG_IM_MASK)) 1063 { 1064 /* Software has unmasked the interrupt, raise it. */ 1065 MSIMSG Msi; 1066 Msi.Addr.u64 = RT_MAKE_U64(dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG), 1067 dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG)); 1068 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG); 1069 1070 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1071 1072 /* Clear interrupt pending bit. */ 1073 uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK; 1074 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1075 } 1076 else 1077 { 1078 /* Interrupt is masked, set the interrupt pending bit. */ 1079 uIectlReg |= VTD_BF_IECTL_REG_IP_MASK; 1080 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1081 } 1082 } 1083 #endif /* IN_RING3 */ 1037 1084 1038 1085 … … 1101 1148 dmarRegChangeRaw64(pThis, VTD_MMIO_OFF_IQERCD_REG, UINT64_MAX, fIqei); 1102 1149 1103 dmarFault RaiseInterrupt(pDevIns);1150 dmarFaultEventRaiseInterrupt(pDevIns); 1104 1151 } 1105 1152 … … 1440 1487 static void dmarR3InvQueueProcessRequests(PPDMDEVINS pDevIns, void const *pvRequests, uint32_t cbRequests, uint8_t fDw) 1441 1488 { 1489 PCDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1490 PCDMARR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARR3); 1491 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisR3); 1492 1442 1493 uint8_t const cbDsc = fDw == VTD_IQA_REG_DW_256_BIT ? 32 : 16; 1443 1494 for (uint32_t offDsc = 0; offDsc < cbRequests; offDsc += cbDsc) 1444 1495 { 1445 1496 uint64_t const *puDscQwords = (uint64_t const *)((uintptr_t)pvRequests + offDsc); 1446 uint8_t const fDscType = VTD_GENERIC_INV_DSC_GET_TYPE(puDscQwords[0]); 1497 uint64_t const uQword0 = puDscQwords[0]; 1498 uint64_t const uQword1 = puDscQwords[1]; 1499 uint8_t const fDscType = VTD_GENERIC_INV_DSC_GET_TYPE(uQword0); 1500 uint8_t const fTtm = dmarRtAddrRegGetTtm(pThis); 1501 Assert(fTtm != VTD_TTM_RSVD); /* Should be guaranteed when software updates GCMD_REG.SRTP. */ 1502 1447 1503 switch (fDscType) 1448 1504 { … … 1451 1507 case VTD_DEV_TLB_INV_DSC_TYPE: LogRelMax(32, ("%s: DEV_TLB\n", DMAR_LOG_PFX)); break; 1452 1508 case VTD_IEC_INV_DSC_TYPE: LogRelMax(32, ("%s: IEC_INV\n", DMAR_LOG_PFX)); break; 1453 case VTD_INV_WAIT_DSC_TYPE: LogRelMax(32, ("%s: INV_WAIT\n", DMAR_LOG_PFX)); break; 1509 1510 case VTD_INV_WAIT_DSC_TYPE: 1511 { 1512 /* Validate translation modes valid for this descriptor. */ 1513 if ( fTtm == VTD_TTM_LEGACY_MODE 1514 || fDw == VTD_IQA_REG_DW_256_BIT) 1515 { /* likely */ } 1516 else 1517 { 1518 dmarIqeFaultRecord(pDevIns, kDmarDiag_Iqei_Inv_Wait_Dsc_Ttm, kIqei_InvalidDescriptorType); 1519 return; 1520 } 1521 1522 /* Validate reserved bits. */ 1523 uint64_t const fValidMask0 = !(pThis->fExtCap & VTD_BF_ECAP_REG_PDS_MASK) 1524 ? VTD_INV_WAIT_DSC_0_VALID_MASK & ~VTD_BF_0_INV_WAIT_DSC_PD_MASK 1525 : VTD_INV_WAIT_DSC_0_VALID_MASK; 1526 if ( !(uQword0 & ~fValidMask0) 1527 && !(uQword1 & ~VTD_INV_WAIT_DSC_1_VALID_MASK)) 1528 { /* likely */ } 1529 else 1530 { 1531 dmarIqeFaultRecord(pDevIns, kDmarDiag_Iqei_Inv_Wait_Dsc_0_1_Rsvd, kIqei_RsvdFieldViolation); 1532 return; 1533 } 1534 if (fDw == VTD_IQA_REG_DW_256_BIT) 1535 { 1536 uint64_t const uQword2 = puDscQwords[2]; 1537 uint64_t const uQword3 = puDscQwords[3]; 1538 if ( !uQword2 1539 && !uQword3) 1540 { /* likely */ } 1541 else 1542 { 1543 dmarIqeFaultRecord(pDevIns, kDmarDiag_Iqei_Inv_Wait_Dsc_2_3_Rsvd, kIqei_RsvdFieldViolation); 1544 return; 1545 } 1546 } 1547 1548 /* Perform status write (this must be done prior to generating the completion interrupt). */ 1549 bool const fSw = RT_BF_GET(uQword0, VTD_BF_0_INV_WAIT_DSC_SW); 1550 if (fSw) 1551 { 1552 uint32_t const uStatus = RT_BF_GET(uQword0, VTD_BF_0_INV_WAIT_DSC_STDATA); 1553 RTGCPHYS const GCPhysStatus = uQword1 & VTD_BF_1_INV_WAIT_DSC_STADDR_MASK; 1554 DMAR_UNLOCK(pDevIns, pThisR3); 1555 int const rc = PDMDevHlpPhysWrite(pDevIns, GCPhysStatus, (void const*)&uStatus, sizeof(uStatus)); 1556 DMAR_LOCK(pDevIns, pThisR3); 1557 AssertRC(rc); 1558 } 1559 1560 /* Generate invalidation event interrupt. */ 1561 bool const fIf = RT_BF_GET(uQword0, VTD_BF_0_INV_WAIT_DSC_IF); 1562 if (fIf) 1563 dmarR3InvEventRaiseInterrupt(pDevIns); 1564 break; 1565 } 1566 1454 1567 case VTD_P_IOTLB_INV_DSC_TYPE: LogRelMax(32, ("%s: P_IOTLB\n", DMAR_LOG_PFX)); break; 1455 1568 case VTD_PC_INV_DSC_TYPE: LogRelMax(32, ("%s: PC_INV\n", DMAR_LOG_PFX)); break; … … 1461 1574 default: 1462 1575 { 1576 /* Stop processing further requests. */ 1463 1577 LogFunc(("Invalid descriptor type: %#x\n", fDscType)); 1464 1578 dmarIqeFaultRecord(pDevIns, kDmarDiag_Iqei_Dsc_Type_Invalid, kIqei_InvalidDescriptorType); … … 1510 1624 if (!fSignaled) 1511 1625 { 1512 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtInvQueue, RT_INDEFINITE_WAIT);1626 int const rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtInvQueue, RT_INDEFINITE_WAIT); 1513 1627 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); 1514 1628 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
Note:
See TracChangeset
for help on using the changeset viewer.