Changeset 84223 in vbox
- Timestamp:
- May 9, 2020 5:34:23 AM (4 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp
r84222 r84223 479 479 /** Number of device table segments supported (power of 2). */ 480 480 #define IOMMU_MAX_DEV_TAB_SEGMENTS 3 481 /** Maximum number of host address translation levels supported. */481 /** Maximum host address translation level supported (inclusive). */ 482 482 #define IOMMU_MAX_HOST_PT_LEVEL 6 483 483 /** The IOTLB entry magic. */ … … 2103 2103 kIoPageFaultType_PteInvalidPageSize, 2104 2104 kIoPageFaultType_PteInvalidLvlEncoding, 2105 kIoPageFaultType_ InvalidSkippedPageLvl,2105 kIoPageFaultType_SkippedLevelIovaNotZero, 2106 2106 kIoPageFaultType_PteRsvdNotZero, 2107 2107 kIoPageFaultType_PteValidNotSet, … … 3783 3783 case kIoPageFaultType_PteInvalidPageSize: 3784 3784 case kIoPageFaultType_PteInvalidLvlEncoding: 3785 case kIoPageFaultType_ InvalidSkippedPageLvl:3785 case kIoPageFaultType_SkippedLevelIovaNotZero: 3786 3786 case kIoPageFaultType_PteRsvdNotZero: 3787 3787 case kIoPageFaultType_PteValidNotSet: … … 4039 4039 } 4040 4040 4041 /* The virtual address bits indexing table. */ 4042 static uint8_t const s_acIovaLevelShifts[] = { 0, 12, 21, 30, 39, 48, 57, 0 }; 4043 static uint64_t const s_auIovaLevelMasks[] = { UINT64_C(0x0000000000000000), 4044 UINT64_C(0x00000000001ff000), 4045 UINT64_C(0x000000003fe00000), 4046 UINT64_C(0x0000007fc0000000), 4047 UINT64_C(0x0000ff8000000000), 4048 UINT64_C(0x01ff000000000000), 4049 UINT64_C(0xfe00000000000000), 4050 UINT64_C(0x0000000000000000) }; 4051 AssertCompile(RT_ELEMENTS(s_acIovaLevelShifts) == RT_ELEMENTS(s_auIovaLevelMasks)); 4052 AssertCompile(RT_ELEMENTS(s_acIovaLevelShifts) > IOMMU_MAX_HOST_PT_LEVEL); 4053 4041 4054 /* Traverse the I/O page table starting with the page directory in the DTE. */ 4042 4055 IOPTENTITY_T PtEntity; 4043 PtEntity.u64 = pDte->au64[0];4056 PtEntity.u64 = pDte->au64[0]; 4044 4057 for (;;) 4045 4058 { 4046 /* The virtual address bits indexing table. */ 4047 static uint8_t const s_acIovaLvlShifts[] = { 0, 12, 21, 30, 39, 48, 57, 0 }; 4048 4049 /* Figure out the system physical address of the page table at the next level. */ 4059 /* Figure out the system physical address of the page table at the current level. */ 4050 4060 uint8_t const uLevel = PtEntity.n.u3NextLevel; 4051 Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaL vlShifts));4061 Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaLevelShifts)); 4052 4062 Assert(uLevel <= IOMMU_MAX_HOST_PT_LEVEL); 4053 uint16_t const idxPte = (uIova >> s_acIovaL vlShifts[uLevel]) & UINT64_C(0x1ff);4063 uint16_t const idxPte = (uIova >> s_acIovaLevelShifts[uLevel]) & UINT64_C(0x1ff); 4054 4064 uint64_t const offPte = idxPte << 3; 4055 4065 RTGCPHYS const GCPhysPtEntity = (PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK) + offPte; 4056 4066 4057 /* Read the page table entity at the next level. */4067 /* Read the page table entity at the current level. */ 4058 4068 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysPtEntity, &PtEntity.u64, sizeof(PtEntity)); 4059 4069 if (RT_FAILURE(rc)) … … 4067 4077 4068 4078 /* Check present bit. */ 4069 if (!PtEntity.n.u1Present) 4079 if (PtEntity.n.u1Present) 4080 { /* likely */ } 4081 else 4070 4082 { 4071 4083 EVT_IO_PAGE_FAULT_T EvtIoPageFault; … … 4078 4090 /* Check permission bits. */ 4079 4091 uint8_t const fPtePerm = (PtEntity.u64 >> IOMMU_IO_PERM_SHIFT) & IOMMU_IO_PERM_MASK; 4080 if ((fAccess & fPtePerm) != fAccess) 4092 if ((fAccess & fPtePerm) == fAccess) 4093 { /* likely */ } 4094 else 4081 4095 { 4082 4096 EVT_IO_PAGE_FAULT_T EvtIoPageFault; … … 4087 4101 } 4088 4102 4103 /* If this is a PTE, we're at the final level and we're done. */ 4089 4104 uint8_t const uNextLevel = PtEntity.n.u3NextLevel; 4090 bool const fIsPte = RT_BOOL(uNextLevel == 0 || uNextLevel == 7);4091 if (fIsPte)4105 if ( uNextLevel == 0 4106 || uNextLevel == 7) 4092 4107 { 4093 4108 /** @todo IOMMU: Compute final SPA and return. */ … … 4095 4110 } 4096 4111 4097 /* Checklevel encoding of the PDE. */4112 /* Validate the next level encoding of the PDE. */ 4098 4113 #if IOMMU_MAX_HOST_PT_LEVEL < 6 4099 if (uNextLevel > IOMMU_MAX_HOST_PT_LEVEL) 4114 if (uNextLevel <= IOMMU_MAX_HOST_PT_LEVEL) 4115 { /* likely */ } 4116 else 4100 4117 { 4101 4118 EVT_IO_PAGE_FAULT_T EvtIoPageFault; 4102 4119 iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */, 4103 enmOp, &EvtIoPageFault);4120 false /* fPermDenied */, enmOp, &EvtIoPageFault); 4104 4121 iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault, 4105 4122 kIoPageFaultType_PteInvalidLvlEncoding); … … 4110 4127 #endif 4111 4128 4112 /** @todo IOMMU: rest of page walk. */ 4129 /* Validate level transition. */ 4130 if (uNextLevel < uLevel) 4131 { /* likely */ } 4132 else 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_PteInvalidLvlEncoding); 4139 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 4140 } 4141 4142 /* Ensure IOVA bits of skipped levels are zero. */ 4143 Assert(uLevel > 0); 4144 uint64_t uIovaSkipMask = 0; 4145 for (unsigned idxLevel = uLevel - 1; idxLevel > uNextLevel; idxLevel--) 4146 uIovaSkipMask |= s_auIovaLevelMasks[idxLevel]; 4147 if (!(uIova & uIovaSkipMask)) 4148 { /* likely */ } 4149 else 4150 { 4151 EVT_IO_PAGE_FAULT_T EvtIoPageFault; 4152 iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */, 4153 false /* fPermDenied */, enmOp, &EvtIoPageFault); 4154 iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault, 4155 kIoPageFaultType_SkippedLevelIovaNotZero); 4156 return VERR_IOMMU_ADDR_TRANSLATION_FAILED; 4157 } 4158 4159 /* Continue with traversing the page directory at this level. */ 4113 4160 } 4114 4161
Note:
See TracChangeset
for help on using the changeset viewer.

