Changeset 84225 in vbox for trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
- Timestamp:
- May 9, 2020 11:27:30 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r84223 r84225 4059 4059 /* Figure out the system physical address of the page table at the current level. */ 4060 4060 uint8_t const uLevel = PtEntity.n.u3NextLevel; 4061 Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaLevelShifts));4062 Assert(uLevel <= IOMMU_MAX_HOST_PT_LEVEL);4063 uint16_t const idxPte = (uIova >> s_acIovaLevelShifts[uLevel]) & UINT64_C(0x1ff);4064 uint64_t const offPte = idxPte << 3;4065 RTGCPHYS const GCPhysPtEntity = (PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK) + offPte;4066 4061 4067 4062 /* Read the page table entity at the current level. */ 4068 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysPtEntity, &PtEntity.u64, sizeof(PtEntity)); 4069 if (RT_FAILURE(rc)) 4070 { 4071 Log((IOMMU_LOG_PFX ": Failed to read page table entry at %#RGp. rc=%Rrc -> PageTabHwError\n", GCPhysPtEntity, rc)); 4072 EVT_PAGE_TAB_HW_ERR_T EvtPageTabHwErr; 4073 iommuAmdInitPageTabHwErrorEvent(uDevId, pDte->n.u16DomainId, GCPhysPtEntity, enmOp, &EvtPageTabHwErr); 4074 iommuAmdRaisePageTabHwErrorEvent(pDevIns, enmOp, &EvtPageTabHwErr, kHwErrType_TargetAbort); 4075 return VERR_IOMMU_IPE_2; 4063 { 4064 Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaLevelShifts)); 4065 Assert(uLevel <= IOMMU_MAX_HOST_PT_LEVEL); 4066 uint16_t const idxPte = (uIova >> s_acIovaLevelShifts[uLevel]) & UINT64_C(0x1ff); 4067 uint64_t const offPte = idxPte << 3; 4068 RTGCPHYS const GCPhysPtEntity = (PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK) + offPte; 4069 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysPtEntity, &PtEntity.u64, sizeof(PtEntity)); 4070 if (RT_FAILURE(rc)) 4071 { 4072 Log((IOMMU_LOG_PFX ": Failed to read page table entry at %#RGp. rc=%Rrc -> PageTabHwError\n", GCPhysPtEntity, rc)); 4073 EVT_PAGE_TAB_HW_ERR_T EvtPageTabHwErr; 4074 iommuAmdInitPageTabHwErrorEvent(uDevId, pDte->n.u16DomainId, GCPhysPtEntity, enmOp, &EvtPageTabHwErr); 4075 iommuAmdRaisePageTabHwErrorEvent(pDevIns, enmOp, &EvtPageTabHwErr, kHwErrType_TargetAbort); 4076 return VERR_IOMMU_IPE_2; 4077 } 4076 4078 } 4077 4079 … … 4103 4105 /* If this is a PTE, we're at the final level and we're done. */ 4104 4106 uint8_t const uNextLevel = PtEntity.n.u3NextLevel; 4105 if ( uNextLevel == 0 4106 || uNextLevel == 7) 4107 { 4108 /** @todo IOMMU: Compute final SPA and return. */ 4109 return VERR_NOT_IMPLEMENTED; 4107 if (uNextLevel == 0) 4108 { 4109 /* The page size of the translation is the default (4K). */ 4110 pIotlbe->GCPhysSpa = PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK; 4111 pIotlbe->cShift = X86_PAGE_4K_SHIFT; 4112 pIotlbe->fIoPerm = fPtePerm; 4113 return VINF_SUCCESS; 4114 } 4115 if (uNextLevel == 7) 4116 { 4117 /* The default page size of the translation is overriden. */ 4118 RTGCPHYS const GCPhysPte = PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK; 4119 uint8_t cShift = X86_PAGE_4K_SHIFT; 4120 while (GCPhysPte & RT_BIT_64(cShift++)) 4121 ; 4122 4123 /* The page size must be larger than the default size and lower than the default size of the higher level. */ 4124 Assert(uLevel < IOMMU_MAX_HOST_PT_LEVEL); /* PTE at level 6 handled outside the loop, uLevel should be <= 5. */ 4125 if ( cShift > s_acIovaLevelShifts[uLevel] 4126 && cShift < s_acIovaLevelShifts[uLevel + 1]) 4127 { 4128 pIotlbe->GCPhysSpa = GCPhysPte; 4129 pIotlbe->cShift = cShift; 4130 pIotlbe->fIoPerm = fPtePerm; 4131 return VINF_SUCCESS; 4132 } 4133 4134 EVT_IO_PAGE_FAULT_T EvtIoPageFault; 4135 iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */, 4136 false /* fPermDenied */, enmOp, &EvtIoPageFault); 4137 iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault, 4138 kIoPageFaultType_PteInvalidPageSize); 4139 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 4110 4140 } 4111 4141
Note:
See TracChangeset
for help on using the changeset viewer.