VirtualBox

Ignore:
Timestamp:
May 9, 2020 11:27:30 AM (5 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Page walk bits.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r84223 r84225  
    40594059        /* Figure out the system physical address of the page table at the current level. */
    40604060        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;
    40664061
    40674062        /* 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            }
    40764078        }
    40774079
     
    41034105        /* If this is a PTE, we're at the final level and we're done. */
    41044106        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;
    41104140        }
    41114141
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette