Changeset 88872 in vbox
- Timestamp:
- May 5, 2021 6:32:22 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuIntel.cpp
r88859 r88872 173 173 kDmarDiag_Ir_Rfi_Irte_Not_Present, 174 174 kDmarDiag_Ir_Rfi_Irte_Rsvd, 175 kDmarDiag_Ir_Rfi_Irte_Svt_Bus, 176 kDmarDiag_Ir_Rfi_Irte_Svt_Masked, 177 kDmarDiag_Ir_Rfi_Irte_Svt_Rsvd, 175 178 kDmarDiag_Ir_Rfi_Rsvd, 176 179 /* Member for determining array index limit. */ … … 208 211 DMARDIAG_DESC(Ir_Rfi_Irte_Not_Present ), 209 212 DMARDIAG_DESC(Ir_Rfi_Irte_Rsvd ), 213 DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Bus ), 214 DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Masked ), 215 DMARDIAG_DESC(Ir_Rfi_Irte_Svt_Rsvd ), 210 216 DMARDIAG_DESC(Ir_Rfi_Rsvd ), 211 217 /* kDmarDiag_End */ … … 1052 1058 static void dmarFaultEventRaiseInterrupt(PPDMDEVINS pDevIns) 1053 1059 { 1054 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1060 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1061 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1062 1063 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1064 1055 1065 #ifdef RT_STRICT 1056 1066 { … … 1071 1081 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEADDR_REG); 1072 1082 Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEUADDR_REG); 1073 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEDATA_REG);1083 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_FEDATA_REG); 1074 1084 1075 1085 /** @todo Assert Msi.Addr is in the MSR_IA32_APICBASE_ADDR range and ensure on 1076 1086 * FEADD_REG write it can't be anything else? */ 1077 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC);1078 1087 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1079 1088 … … 1101 1110 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1102 1111 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1112 1103 1113 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1104 1114 1105 1115 uint32_t const uIcsReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_ICS_REG); 1106 if ( uIcsReg & VTD_BF_ICS_REG_IWC_MASK)1107 return;1108 1109 uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG);1110 if (!(uIectlReg & VTD_BF_IECTL_REG_IM_MASK))1111 {1112 /* Software has unmasked the interrupt, raise it. */1113 MSIMSG Msi;1114 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG);1115 Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG);1116 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG); 1117 1118 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1119 1120 /* Clear interrupt pending bit. */1121 uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK;1122 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);1123 }1124 else1125 {1126 /* Interrupt is masked, set the interrupt pending bit. */1127 uIectlReg |= VTD_BF_IECTL_REG_IP_MASK;1128 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg);1116 if (!(uIcsReg & VTD_BF_ICS_REG_IWC_MASK)) 1117 { 1118 uint32_t uIectlReg = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IECTL_REG); 1119 if (!(uIectlReg & VTD_BF_IECTL_REG_IM_MASK)) 1120 { 1121 /* Software has unmasked the interrupt, raise it. */ 1122 MSIMSG Msi; 1123 Msi.Addr.au32[0] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEADDR_REG); 1124 Msi.Addr.au32[1] = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEUADDR_REG); 1125 Msi.Data.u32 = dmarRegReadRaw32(pThis, VTD_MMIO_OFF_IEDATA_REG); 1126 1127 pThisCC->CTX_SUFF(pIommuHlp)->pfnSendMsi(pDevIns, &Msi, 0 /* uTagSrc */); 1128 1129 /* Clear interrupt pending bit. */ 1130 uIectlReg &= ~VTD_BF_IECTL_REG_IP_MASK; 1131 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1132 } 1133 else 1134 { 1135 /* Interrupt is masked, set the interrupt pending bit. */ 1136 uIectlReg |= VTD_BF_IECTL_REG_IP_MASK; 1137 dmarRegWriteRaw32(pThis, VTD_MMIO_OFF_IECTL_REG, uIectlReg); 1138 } 1129 1139 } 1130 1140 } … … 1185 1195 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1186 1196 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1187 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1197 1198 DMAR_LOCK(pDevIns, pThisCC); 1188 1199 1189 1200 /* Update the diagnostic reason. */ … … 1209 1220 dmarFaultEventRaiseInterrupt(pDevIns); 1210 1221 } 1222 1223 DMAR_UNLOCK(pDevIns, pThisCC); 1211 1224 } 1212 1225 … … 1246 1259 PDMAR pThis = PDMDEVINS_2_DATA(pDevIns, PDMAR); 1247 1260 PCDMARCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PCDMARCC); 1248 DMAR_ASSERT_LOCK_IS_OWNER(pDevIns, pThisCC); 1261 1262 DMAR_LOCK(pDevIns, pThisCC); 1249 1263 1250 1264 /* Update the diagnostic reason. */ … … 1260 1274 1261 1275 dmarFaultEventRaiseInterrupt(pDevIns); 1276 1277 DMAR_UNLOCK(pDevIns, pThisCC); 1262 1278 } 1263 1279 … … 1512 1528 size_t const cbIrte = sizeof(*pIrte); 1513 1529 RTGCPHYS const GCPhysIrte = (uIrtaReg & VTD_BF_IRTA_REG_IRTA_MASK) + (idxIntr * cbIrte); 1514 int rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysIrte, pIrte, cbIrte); 1515 if (RT_SUCCESS(rc)) 1516 return VINF_SUCCESS; 1517 return rc; 1530 return PDMDevHlpPhysReadMeta(pDevIns, GCPhysIrte, pIrte, cbIrte); 1518 1531 } 1519 1532 … … 1536 1549 AssertCompile(VTD_REMAPPABLE_MSI_ADDR_VALID_MASK == UINT32_MAX); 1537 1550 if (!(pMsiIn->Data.u32 & ~VTD_REMAPPABLE_MSI_DATA_VALID_MASK)) 1538 { /* likely */ } 1551 { 1552 /* Compute the index into the interrupt remap table. */ 1553 uint16_t const uHandleHi = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI); 1554 uint16_t const uHandleLo = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO); 1555 uint16_t const uHandle = uHandleLo | (uHandleHi << 15); 1556 bool const fSubHandleValid = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_SHV); 1557 uint32_t const idxIntr = fSubHandleValid 1558 ? uHandle + RT_BF_GET(pMsiIn->Data.u32, VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE) 1559 : uHandle; 1560 1561 /* Validate the index. */ 1562 uint32_t const cEntries = VTD_IRTA_REG_GET_ENTRIES(uIrtaReg); 1563 if (idxIntr < cEntries) 1564 { 1565 /** @todo Implement and read IRTE from interrupt-entry cache here. */ 1566 1567 /* Read the interrupt remap table entry (IRTE) at the index. */ 1568 VTD_IRTE_T Irte; 1569 int rc = dmarIrReadIrte(pDevIns, uIrtaReg, idxIntr, &Irte); 1570 if (RT_SUCCESS(rc)) 1571 { 1572 /* Check if the IRTE is present (this must be done -before- checking reserved bits). */ 1573 uint64_t const uIrteQword0 = Irte.au64[0]; 1574 uint64_t const uIrteQword1 = Irte.au64[1]; 1575 bool const fPresent = RT_BF_GET(uIrteQword0, VTD_BF_0_IRTE_P); 1576 if (fPresent) 1577 { 1578 /* Validate reserved bits in the IRTE. */ 1579 if ( !(uIrteQword0 & ~VTD_IRTE_0_VALID_MASK) 1580 && !(uIrteQword1 & ~VTD_IRTE_1_VALID_MASK)) 1581 { 1582 /* Validate requester id (the device ID) as configured in the IRTE. */ 1583 bool fSrcValid; 1584 DMARDIAG enmIrDiag; 1585 uint8_t const fSvt = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SVT); 1586 switch (fSvt) 1587 { 1588 case VTD_IRTE_SVT_NONE: 1589 { 1590 fSrcValid = true; 1591 enmIrDiag = kDmarDiag_None; 1592 break; 1593 } 1594 1595 case VTD_IRTE_SVT_VALIDATE_MASK: 1596 { 1597 static uint16_t const s_afValidMasks[] = { 0xffff, 0xfffb, 0xfff9, 0xfff8 }; 1598 uint8_t const idxMask = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SQ) & 3; 1599 uint16_t const fValidMask = s_afValidMasks[idxMask]; 1600 fSrcValid = (idDevice & fValidMask) == idDevice; 1601 enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Masked; 1602 break; 1603 } 1604 1605 case VTD_IRTE_SVT_VALIDATE_BUS_RANGE: 1606 { 1607 uint16_t const uSourceId = RT_BF_GET(uIrteQword1, VTD_BF_1_IRTE_SID); 1608 uint8_t const uBusFirst = RT_HI_U8(uSourceId); 1609 uint8_t const uBusLast = RT_LO_U8(uSourceId); 1610 uint8_t const uRequesterIdBus = idDevice >> VBOX_PCI_BUS_SHIFT; 1611 fSrcValid = (uRequesterIdBus >= uBusFirst && uRequesterIdBus <= uBusLast); 1612 enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Bus; 1613 break; 1614 } 1615 1616 default: 1617 { 1618 fSrcValid = false; 1619 enmIrDiag = kDmarDiag_Ir_Rfi_Irte_Svt_Bus; 1620 break; 1621 } 1622 } 1623 1624 if (fSrcValid) 1625 { 1626 /** @todo Get the interrupt mode (must not be posted) and then remap. */ 1627 *pMsiOut = *pMsiIn; // This is just temporary to shut up the compiler! 1628 return VERR_NOT_IMPLEMENTED; 1629 } 1630 else 1631 dmarIrFaultRecordQualified(pDevIns, enmIrDiag, kIrf_Irte_Present_Rsvd, idDevice, idxIntr, &Irte); 1632 } 1633 else 1634 dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, kIrf_Irte_Present_Rsvd, idDevice, 1635 idxIntr, &Irte); 1636 } 1637 else 1638 dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, kIrf_Irte_Not_Present, idDevice, 1639 idxIntr, &Irte); 1640 } 1641 else 1642 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, kIrf_Irte_Read_Failed, idDevice, idxIntr); 1643 } 1644 else 1645 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, kIrf_Intr_Index_Invalid, idDevice, idxIntr); 1646 } 1539 1647 else 1540 {1541 1648 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Rsvd, kIrf_Remappable_Intr_Rsvd, idDevice, 0 /* idxIntr */); 1542 return VERR_IOMMU_INTR_REMAP_DENIED; 1543 } 1544 1545 /* Compute the index into the interrupt remap table. */ 1546 uint16_t const uHandleHi = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI); 1547 uint16_t const uHandleLo = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO); 1548 uint16_t const uHandle = uHandleLo | (uHandleHi << 15); 1549 bool const fSubHandleValid = RT_BF_GET(pMsiIn->Addr.au32[0], VTD_BF_REMAPPABLE_MSI_ADDR_SHV); 1550 uint32_t const idxIntr = fSubHandleValid 1551 ? uHandle + RT_BF_GET(pMsiIn->Data.u32, VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE) 1552 : uHandle; 1553 1554 /* Validate the index. */ 1555 uint32_t const cEntries = VTD_IRTA_REG_GET_ENTRIES(uIrtaReg); 1556 if (idxIntr < cEntries) 1557 { /* likely */ } 1558 else 1559 { 1560 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Intr_Index_Invalid, kIrf_Intr_Index_Invalid, idDevice, idxIntr); 1561 return VERR_IOMMU_INTR_REMAP_DENIED; 1562 } 1563 1564 /** @todo Implement and read IRTE from interrupt-entry cache here. */ 1565 1566 /* Read the interrupt remap table entry (IRTE). */ 1567 VTD_IRTE_T Irte; 1568 int rc = dmarIrReadIrte(pDevIns, uIrtaReg, idxIntr, &Irte); 1569 if (RT_SUCCESS(rc)) 1570 { /* likely */ } 1571 else 1572 { 1573 dmarIrFaultRecord(pDevIns, kDmarDiag_Ir_Rfi_Irte_Read_Failed, kIrf_Irte_Read_Failed, idDevice, idxIntr); 1574 return VERR_IOMMU_INTR_REMAP_DENIED; 1575 } 1576 1577 /* Validate IRTE. */ 1578 uint64_t const uIrteQword0 = Irte.au64[0]; 1579 uint64_t const uIrteQword1 = Irte.au64[1]; 1580 bool const fPresent = RT_BF_GET(uIrteQword0, VTD_BF_0_IRTE_P); 1581 if (fPresent) 1582 { /* likely */ } 1583 else 1584 { 1585 dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Not_Present, kIrf_Irte_Not_Present, idDevice, idxIntr, &Irte); 1586 return VERR_IOMMU_INTR_REMAP_DENIED; 1587 } 1588 if ( !(uIrteQword0 & ~VTD_IRTE_0_VALID_MASK) 1589 && !(uIrteQword1 & ~VTD_IRTE_1_VALID_MASK)) 1590 { /* likely */ } 1591 else 1592 { 1593 dmarIrFaultRecordQualified(pDevIns, kDmarDiag_Ir_Rfi_Irte_Rsvd, kIrf_Irte_Present_Rsvd, idDevice, idxIntr, &Irte); 1594 return VERR_IOMMU_INTR_REMAP_DENIED; 1595 } 1596 1597 /** @todo rest of validation using SVT and SQ. */ 1598 *pMsiOut = *pMsiIn; // This is just temporary to shut up the compiler! 1599 return VERR_NOT_IMPLEMENTED; 1649 return VERR_IOMMU_INTR_REMAP_DENIED; 1600 1650 } 1601 1651 … … 1653 1703 } 1654 1704 1655 /* I f interrupt-remapping isn't enabled, all interrupts are pass-through. */1705 /* Interrupt-remapping isn't enabled, all interrupts are pass-through. */ 1656 1706 *pMsiOut = *pMsiIn; 1657 1707 return VINF_SUCCESS; … … 1773 1823 do \ 1774 1824 { \ 1775 DMAR_LOCK(pDevIns, pThisR3); \1776 1825 dmarIqeFaultRecord(pDevIns, (a_enmDiag), (a_enmIqei)); \ 1777 DMAR_UNLOCK(pDevIns, pThisR3); \1778 1826 return; \ 1779 1827 } while (0) … … 1986 2034 /* The requests have not wrapped around, read them in one go. */ 1987 2035 cbRequests = offQueueTail - offQueueHead; 1988 rc = PDMDevHlpPhysRead (pDevIns, GCPhysRequests, pvRequests, cbRequests);2036 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests, pvRequests, cbRequests); 1989 2037 } 1990 2038 else … … 1992 2040 /* The requests have wrapped around, read forward and wrapped-around. */ 1993 2041 uint32_t const cbForward = cbQueue - offQueueHead; 1994 rc = PDMDevHlpPhysRead (pDevIns, GCPhysRequests, pvRequests, cbForward);2042 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests, pvRequests, cbForward); 1995 2043 1996 2044 uint32_t const cbWrapped = offQueueTail; … … 1998 2046 && cbWrapped > 0) 1999 2047 { 2000 rc = PDMDevHlpPhysRead (pDevIns, GCPhysRequests + cbForward,2001 (void *)((uintptr_t)pvRequests + cbForward), cbWrapped);2048 rc = PDMDevHlpPhysReadMeta(pDevIns, GCPhysRequests + cbForward, 2049 (void *)((uintptr_t)pvRequests + cbForward), cbWrapped); 2002 2050 } 2003 2051 cbRequests = cbForward + cbWrapped;
Note:
See TracChangeset
for help on using the changeset viewer.