VirtualBox

Changeset 84223 in vbox


Ignore:
Timestamp:
May 9, 2020 5:34:23 AM (4 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

    r84222 r84223  
    479479/** Number of device table segments supported (power of 2). */
    480480#define IOMMU_MAX_DEV_TAB_SEGMENTS                  3
    481 /** Maximum number of host address translation levels supported. */
     481/** Maximum host address translation level supported (inclusive). */
    482482#define IOMMU_MAX_HOST_PT_LEVEL                     6
    483483/** The IOTLB entry magic. */
     
    21032103    kIoPageFaultType_PteInvalidPageSize,
    21042104    kIoPageFaultType_PteInvalidLvlEncoding,
    2105     kIoPageFaultType_InvalidSkippedPageLvl,
     2105    kIoPageFaultType_SkippedLevelIovaNotZero,
    21062106    kIoPageFaultType_PteRsvdNotZero,
    21072107    kIoPageFaultType_PteValidNotSet,
     
    37833783        case kIoPageFaultType_PteInvalidPageSize:
    37843784        case kIoPageFaultType_PteInvalidLvlEncoding:
    3785         case kIoPageFaultType_InvalidSkippedPageLvl:
     3785        case kIoPageFaultType_SkippedLevelIovaNotZero:
    37863786        case kIoPageFaultType_PteRsvdNotZero:
    37873787        case kIoPageFaultType_PteValidNotSet:
     
    40394039    }
    40404040
     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
    40414054    /* Traverse the I/O page table starting with the page directory in the DTE. */
    40424055    IOPTENTITY_T PtEntity;
    4043     PtEntity.u64   = pDte->au64[0];
     4056    PtEntity.u64 = pDte->au64[0];
    40444057    for (;;)
    40454058    {
    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. */
    40504060        uint8_t const uLevel = PtEntity.n.u3NextLevel;
    4051         Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaLvlShifts));
     4061        Assert(uLevel > 0 && uLevel < RT_ELEMENTS(s_acIovaLevelShifts));
    40524062        Assert(uLevel <= IOMMU_MAX_HOST_PT_LEVEL);
    4053         uint16_t const idxPte         = (uIova >> s_acIovaLvlShifts[uLevel]) & UINT64_C(0x1ff);
     4063        uint16_t const idxPte         = (uIova >> s_acIovaLevelShifts[uLevel]) & UINT64_C(0x1ff);
    40544064        uint64_t const offPte         = idxPte << 3;
    40554065        RTGCPHYS const GCPhysPtEntity = (PtEntity.u64 & IOMMU_PTENTITY_ADDR_MASK) + offPte;
    40564066
    4057         /* Read the page table entity at the next level. */
     4067        /* Read the page table entity at the current level. */
    40584068        int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysPtEntity, &PtEntity.u64, sizeof(PtEntity));
    40594069        if (RT_FAILURE(rc))
     
    40674077
    40684078        /* Check present bit. */
    4069         if (!PtEntity.n.u1Present)
     4079        if (PtEntity.n.u1Present)
     4080        { /* likely */ }
     4081        else
    40704082        {
    40714083            EVT_IO_PAGE_FAULT_T EvtIoPageFault;
     
    40784090        /* Check permission bits. */
    40794091        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
    40814095        {
    40824096            EVT_IO_PAGE_FAULT_T EvtIoPageFault;
     
    40874101        }
    40884102
     4103        /* If this is a PTE, we're at the final level and we're done. */
    40894104        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)
    40924107        {
    40934108            /** @todo IOMMU: Compute final SPA and return. */
     
    40954110        }
    40964111
    4097         /* Check level encoding of the PDE. */
     4112        /* Validate the next level encoding of the PDE. */
    40984113#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
    41004117        {
    41014118            EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    41024119            iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, uIova, true /* fPresent */, false /* fRsvdNotZero */,
    4103                                          enmOp, &EvtIoPageFault);
     4120                                         false /* fPermDenied */, enmOp, &EvtIoPageFault);
    41044121            iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, NULL /* pIrte */, enmOp, &EvtIoPageFault,
    41054122                                          kIoPageFaultType_PteInvalidLvlEncoding);
     
    41104127#endif
    41114128
    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. */
    41134160    }
    41144161
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