Changeset 89001 in vbox for trunk/src/VBox/Devices/Bus
- Timestamp:
- May 12, 2021 8:43:29 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88894 r89001 363 363 /** Pointer to the const DMAR device state for the current context. */ 364 364 typedef CTX_SUFF(PDMAR) const PCDMARCC; 365 366 /** 367 * Type of DMAR originated events that generate interrupts. 368 */ 369 typedef enum DMAREVENTTYPE 370 { 371 /** Invalidation completion event. */ 372 DMAREVENTTYPE_INV_COMPLETE = 0, 373 /** Fault event. */ 374 DMAREVENTTYPE_FAULT 375 } DMAREVENTTYPE; 365 376 366 377 … … 1053 1064 1054 1065 /** 1066 * Raises an event on behalf of the DMAR. 1067 * 1068 * These are events that are generated by the DMAR itself (like faults and 1069 * invalidation completion notifications). 1070 * 1071 * @param pDevIns The IOMMU device instance. 1072 * @param enmEventType The DMAR event type. 1073 * 1074 * @remarks The DMAR lock must be held while calling this function. 1075 */ 1076 static void dmarEventRaiseInterrupt(PPDMDEVINS pDevIns, DMAREVENTTYPE enmEventType) 1077 { 1078 uint16_t offCtlReg; 1079 uint32_t fIntrMaskedMask; 1080 uint32_t fIntrPendingMask; 1081 uint16_t offMsiAddrLoReg; 1082 uint16_t offMsiAddrHiReg; 1083 uint16_t offMsiDataReg; 1084 switch (enmEventType) 1085 { 1086 case DMAREVENTTYPE_INV_COMPLETE: 1087 { 1088 offCtlReg = VTD_MMIO_OFF_IECTL_REG; 1089 fIntrMaskedMask = VTD_BF_IECTL_REG_IM_MASK; 1090 fIntrPendingMask = VTD_BF_IECTL_REG_IP_MASK; 1091 offMsiAddrLoReg = VTD_MMIO_OFF_IEADDR_REG; 1092 offMsiAddrHiReg = VTD_MMIO_OFF_IEUADDR_REG; 1093 offMsiDataReg = VTD_MMIO_OFF_IEDATA_REG; 1094 break; 1095 } 1096 1097 case DMAREVENTTYPE_FAULT: 1098 { 1099 offCtlReg = VTD_MMIO_OFF_FECTL_REG; 1100 fIntrMaskedMask = VTD_BF_FECTL_REG_IM_MASK; 1101 fIntrPendingMask = VTD_BF_FECTL_REG_IP_MASK; 1102 offMsiAddrLoReg = VTD_MMIO_OFF_FEADDR_REG; 1103 offMsiAddrHiReg = VTD_MMIO_OFF_FEUADDR_REG; 1104 offMsiDataReg = VTD_MMIO_OFF_FEDATA_REG; 1105 break; 1106 } 1107 1108 default: 1109 { 1110 /* Shouldn't ever happen. */ 1111 AssertMsgFailedReturnVoid(("DMAR event type %#x unknown!\n", enmEventType)); 1112 } 1113 } 1114 1115 /* Check if software has masked the interrupt. */ 1116 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1117 uint32_t uCtlReg = dmarRegReadRaw32(pThis, offCtlReg); 1118 if (!(uCtlReg & fIntrMaskedMask)) 1119 { 1120 /* 1121 * Interrupt is unmasked, raise it. 1122 * 1123 * Interrupts generated by the DMAR have trigger mode and level as 0. 1124 * See Intel spec. 5.1.6 "Remapping Hardware Event Interrupt Programming". 1125 */ 1126 MSIMSG Msi; 1127 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, offMsiAddrLoReg); 1128 Msi.Addr.au32[1] = (pThis->fExtCapReg & VTD_BF_ECAP_REG_EIM_MASK) ? dmarRegReadRaw32(pThis, offMsiAddrHiReg) : 0; 1129 Msi.Data.u32 = dmarRegReadRaw32(pThis, offMsiDataReg); 1130 Msi.Data.n.u1Level = 0; 1131 Msi.Data.n.u1TriggerMode = 0; 1132 1133 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1134 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1135 1136 /* Clear interrupt pending bit. */ 1137 uCtlReg &= ~fIntrPendingMask; 1138 dmarRegWriteRaw32(pThis, offCtlReg, uCtlReg); 1139 } 1140 else 1141 { 1142 /* Interrupt is masked, set the interrupt pending bit. */ 1143 uCtlReg |= fIntrPendingMask; 1144 dmarRegWriteRaw32(pThis, offCtlReg, uCtlReg); 1145 } 1146 } 1147 1148 1149 /** 1055 1150 * Raises an interrupt in response to a fault event. 1056 1151 * … … 1064 1159 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1065 1160 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1066 1067 1161 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1068 1162 … … 1077 1171 } 1078 1172 #endif 1079 1080 uint32_t uFectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FECTL_REG); 1081 if (!(uFectlReg & VTD_BF_FECTL_REG_IM_MASK)) 1082 { 1083 /* Software has unmasked the interrupt, raise it. */ 1084 MSIMSG Msi; 1085 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEADDR_REG); 1086 Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEUADDR_REG); 1087 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEDATA_REG); 1088 1089 /** @todo Assert Msi.Addr is in the MSR_IA32_APICBASE_ADDR range and ensure on 1090 * FEADD_REG write it can't be anything else? */ 1091 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1092 1093 /* Clear interrupt pending bit. */ 1094 uFectlReg &= ~VTD_BF_FECTL_REG_IP_MASK; 1095 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_FECTL_REG, uFectlReg); 1096 } 1097 else 1098 { 1099 /* Interrupt is masked, set the interrupt pending bit. */ 1100 uFectlReg |= VTD_BF_FECTL_REG_IP_MASK; 1101 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_FECTL_REG, uFectlReg); 1102 } 1173 dmarEventRaiseInterrupt(pDevIns, DMAREVENTTYPE_FAULT); 1103 1174 } 1104 1175 … … 1114 1185 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1115 1186 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1116 1117 1187 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1118 1188 1119 1189 uint32_t const uIcsReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_ICS_REG); 1120 1190 if (!(uIcsReg & VTD_BF_ICS_REG_IWC_MASK)) 1121 { 1122 uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG); 1123 if (!(uIectlReg & VTD_BF_IECTL_REG_IM_MASK)) 1124 { 1125 /* Software has unmasked the interrupt, raise it. */ 1126 MSIMSG Msi; 1127 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG); 1128 Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG); 1129 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG); 1130 1131 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1132 1133 /* Clear interrupt pending bit. */ 1134 uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK; 1135 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1136 } 1137 else 1138 { 1139 /* Interrupt is masked, set the interrupt pending bit. */ 1140 uIectlReg |= VTD_BF_IECTL_REG_IP_MASK; 1141 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1142 } 1143 } 1191 dmarEventRaiseInterrupt(pDevIns, DMAREVENTTYPE_INV_COMPLETE); 1144 1192 } 1145 1193 #endif /* IN_RING3 */ … … 1511 1559 uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous) 1512 1560 { 1513 RT_NOREF7(pDevIns, idDevice, uIova, cbIova, fFlags, pGCPhysSpa, pcbContiguous); 1561 RT_NOREF6(idDevice, uIova, cbIova, fFlags, pGCPhysSpa, pcbContiguous); 1562 1563 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1564 if (fFlags & PDMIOMMU_MEM_F_READ) 1565 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemRead)); 1566 else 1567 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMemWrite)); 1568 1514 1569 return VERR_NOT_IMPLEMENTED; 1515 1570 } … … 1591 1646 static int dmarIrRemapIntr(PPDMDEVINS pDevIns, uint64_t uIrtaReg, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut) 1592 1647 { 1593 Assert( VTD_MSI_ADDR_GET_INTR_FORMAT(pMsiIn->Addr.u64)== VTD_INTR_FORMAT_REMAPPABLE);1648 Assert(pMsiIn->Addr.dmar_remap.fIntrFormat == VTD_INTR_FORMAT_REMAPPABLE); 1594 1649 1595 1650 /* Validate reserved bits in the interrupt request. */ … … 1735 1790 { 1736 1791 /* Handle compatibility format interrupts. */ 1737 bool const fIsRemap Format= RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_INTR_FMT);1738 if (!fIsRemap Format)1792 bool const fIsRemappable = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_INTR_FMT); 1793 if (!fIsRemappable) 1739 1794 { 1740 1795 STAM_COUNTER_INC(&pThis->CTX_SUFF_Z(StatMsiRemapCfi));
Note:
See TracChangeset
for help on using the changeset viewer.