VirtualBox

Changeset 108923 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Apr 9, 2025 6:55:17 PM (4 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168427
Message:

VMM/PGMAllGst-armv8.cpp.h: More work on supporting different granule sizes, and support checking permissions and getting at the effective attributes for the GstQueryPageFast() callback, bugref:10388

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PGMAllGst-armv8.cpp.h

    r108920 r108923  
    318318
    319319
     320static const PGMWALKFAIL g_aPermPrivRead[] =
     321{
     322    /* UXN PXN AP[2] AP[1] */
     323    /*   0   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     324    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     325    /*   0   0    1     0  */ PGM_WALKFAIL_SUCCESS,
     326    /*   0   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     327    /*   0   1    0     0  */ PGM_WALKFAIL_SUCCESS,
     328    /*   0   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     329    /*   0   1    1     0  */ PGM_WALKFAIL_SUCCESS,
     330    /*   0   1    1     1  */ PGM_WALKFAIL_SUCCESS,
     331    /*   1   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     332    /*   1   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     333    /*   1   0    1     0  */ PGM_WALKFAIL_SUCCESS,
     334    /*   1   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     335    /*   1   1    0     0  */ PGM_WALKFAIL_SUCCESS,
     336    /*   1   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     337    /*   1   1    1     0  */ PGM_WALKFAIL_SUCCESS,
     338    /*   1   1    1     1  */ PGM_WALKFAIL_SUCCESS
     339};
     340
     341
     342static const PGMWALKFAIL g_aPermPrivWrite[] =
     343{
     344    /* UXN PXN AP[2] AP[1] */
     345    /*   0   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     346    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     347    /*   0   0    1     0  */ PGM_WALKFAIL_NOT_WRITABLE,
     348    /*   0   0    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     349    /*   0   1    0     0  */ PGM_WALKFAIL_SUCCESS,
     350    /*   0   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     351    /*   0   1    1     0  */ PGM_WALKFAIL_NOT_WRITABLE,
     352    /*   0   1    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     353    /*   1   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     354    /*   1   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     355    /*   1   0    1     0  */ PGM_WALKFAIL_NOT_WRITABLE,
     356    /*   1   0    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     357    /*   1   1    0     0  */ PGM_WALKFAIL_SUCCESS,
     358    /*   1   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     359    /*   1   1    1     0  */ PGM_WALKFAIL_NOT_WRITABLE,
     360    /*   1   1    1     1  */ PGM_WALKFAIL_NOT_WRITABLE
     361};
     362
     363
     364static const PGMWALKFAIL g_aPermPrivExec[] =
     365{
     366    /* UXN PXN AP[2] AP[1] */
     367    /*   0   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     368    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     369    /*   0   0    1     0  */ PGM_WALKFAIL_SUCCESS,
     370    /*   0   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     371    /*   0   1    0     0  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     372    /*   0   1    0     1  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     373    /*   0   1    1     0  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     374    /*   0   1    1     1  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     375    /*   1   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     376    /*   1   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     377    /*   1   0    1     0  */ PGM_WALKFAIL_SUCCESS,
     378    /*   1   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     379    /*   1   1    0     0  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     380    /*   1   1    0     1  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     381    /*   1   1    1     0  */ PGM_WALKFAIL_NOT_EXECUTABLE,
     382    /*   1   1    1     1  */ PGM_WALKFAIL_NOT_EXECUTABLE
     383};
     384
     385
     386static const PGMWALKFAIL g_aPermUnprivRead[] =
     387{
     388    /* UXN PXN AP[2] AP[1] */
     389    /*   0   0    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     390    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     391    /*   0   0    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     392    /*   0   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     393    /*   0   1    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     394    /*   0   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     395    /*   0   1    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     396    /*   0   1    1     1  */ PGM_WALKFAIL_SUCCESS,
     397    /*   1   0    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     398    /*   1   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     399    /*   1   0    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     400    /*   1   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     401    /*   1   1    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     402    /*   1   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     403    /*   1   1    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     404    /*   1   1    1     1  */ PGM_WALKFAIL_SUCCESS
     405};
     406
     407
     408static const PGMWALKFAIL g_aPermUnprivWrite[] =
     409{
     410    /* UXN PXN AP[2] AP[1] */
     411    /*   0   0    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     412    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     413    /*   0   0    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE,
     414    /*   0   0    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     415    /*   0   1    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     416    /*   0   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     417    /*   0   1    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE,
     418    /*   0   1    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     419    /*   1   0    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     420    /*   1   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     421    /*   1   0    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE,
     422    /*   1   0    1     1  */ PGM_WALKFAIL_NOT_WRITABLE,
     423    /*   1   1    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE,
     424    /*   1   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     425    /*   1   1    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE,
     426    /*   1   1    1     1  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE
     427};
     428
     429
     430static const PGMWALKFAIL g_aPermUnprivExec[] =
     431{
     432    /* UXN PXN AP[2] AP[1] */
     433    /*   0   0    0     0  */ PGM_WALKFAIL_SUCCESS,
     434    /*   0   0    0     1  */ PGM_WALKFAIL_SUCCESS,
     435    /*   0   0    1     0  */ PGM_WALKFAIL_SUCCESS,
     436    /*   0   0    1     1  */ PGM_WALKFAIL_SUCCESS,
     437    /*   0   1    0     0  */ PGM_WALKFAIL_SUCCESS,
     438    /*   0   1    0     1  */ PGM_WALKFAIL_SUCCESS,
     439    /*   0   1    1     0  */ PGM_WALKFAIL_SUCCESS,
     440    /*   0   1    1     1  */ PGM_WALKFAIL_SUCCESS,
     441    /*   1   0    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     442    /*   1   0    0     1  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     443    /*   1   0    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     444    /*   1   0    1     1  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     445    /*   1   1    0     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     446    /*   1   1    0     1  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     447    /*   1   1    1     0  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE,
     448    /*   1   1    1     1  */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE
     449};
     450
     451
     452DECL_FORCE_INLINE(uint32_t) pgmGstQueryPageCheckPermissions(PPGMPTWALKFAST pWalk, ARMV8VMSA64DESC Desc, uint32_t fFlags, uint8_t uLvl)
     453{
     454    Assert(!(fFlags & ~PGMQPAGE_F_VALID_MASK));
     455
     456    /* Descriptor flags to page table attribute flags mapping. */
     457    static const PGMPTATTRS s_aEffective[] =
     458    {
     459        /* UXN PXN AP[2] AP[1] */
     460        /*   0   0    0     0  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK |                                             PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK,
     461        /*   0   0    0     1  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK | PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK,
     462        /*   0   0    1     0  */ PGM_PTATTRS_PR_MASK |                                                                   PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK,
     463        /*   0   0    1     1  */ PGM_PTATTRS_PR_MASK |                       PGM_PTATTRS_UR_MASK |                       PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK,
     464
     465        /*   0   1    0     0  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK |                                                                   PGM_PTATTRS_UX_MASK,
     466        /*   0   1    0     1  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK |                       PGM_PTATTRS_UX_MASK,
     467        /*   0   1    1     0  */ PGM_PTATTRS_PR_MASK |                                                                                         PGM_PTATTRS_UX_MASK,
     468        /*   0   1    1     1  */ PGM_PTATTRS_PR_MASK |                       PGM_PTATTRS_UR_MASK |                                             PGM_PTATTRS_UX_MASK,
     469
     470        /*   1   0    0     0  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK |                                             PGM_PTATTRS_PX_MASK,
     471        /*   1   0    0     1  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK | PGM_PTATTRS_PX_MASK,
     472        /*   1   0    1     0  */ PGM_PTATTRS_PR_MASK |                                                                   PGM_PTATTRS_PX_MASK,
     473        /*   1   0    1     1  */ PGM_PTATTRS_PR_MASK |                       PGM_PTATTRS_UR_MASK |                       PGM_PTATTRS_PX_MASK,
     474
     475        /*   1   1    0     0  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK,
     476        /*   1   1    0     1  */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK ,
     477        /*   1   1    1     0  */ PGM_PTATTRS_PR_MASK,
     478        /*   1   1    1     1  */ PGM_PTATTRS_PR_MASK |                       PGM_PTATTRS_UR_MASK,
     479    };
     480
     481    static const uint32_t *s_apaPerm[] =
     482    {
     483        /* U X W R */
     484        /* 0 0 0 0 */ NULL,                   /* Invalid                      */
     485        /* 0 0 0 1 */ &g_aPermPrivRead[0],    /* Privileged read access       */
     486        /* 0 0 1 0 */ &g_aPermPrivWrite[0],   /* Privileged write access      */
     487        /* 0 0 1 1 */ NULL,                   /* Invalid access flags         */
     488        /* 0 1 0 0 */ &g_aPermPrivExec[0],    /* Privileged execute access    */
     489        /* 0 1 0 1 */ NULL,                   /* Invalid access flags         */
     490        /* 0 1 1 0 */ NULL,                   /* Invalid access flags         */
     491        /* 0 1 1 1 */ NULL,                   /* Invalid access flags         */
     492
     493        /* 1 0 0 0 */ NULL,                   /* Invalid access flags         */
     494        /* 1 0 0 1 */ &g_aPermUnprivRead[0],  /* Unprivileged read access     */
     495        /* 1 0 1 0 */ &g_aPermUnprivWrite[0], /* Unprivileged read access     */
     496        /* 1 0 1 1 */ NULL,                   /* Invalid access flags         */
     497        /* 1 1 0 0 */ &g_aPermUnprivExec[0],  /* Unprivileged execute access  */
     498        /* 1 1 0 1 */ NULL,                   /* Invalid access flags         */
     499        /* 1 1 1 0 */ NULL,                   /* Invalid access flags         */
     500        /* 1 1 1 1 */ NULL,                   /* Invalid access flags         */
     501    };
     502    Assert(fFlags < RT_ELEMENTS(s_apaPerm));
     503
     504    const uint32_t *paPerm = s_apaPerm[fFlags];
     505    AssertReturn(paPerm, VERR_PGM_MODE_IPE);
     506
     507    uint32_t const idxPerm =   RT_BF_GET(Desc, ARMV8_VMSA64_DESC_PG_OR_BLOCK_LATTR_AP)
     508                             | ((Desc & ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_PXN) >> ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_PXN_BIT) << 2
     509                             | ((Desc & ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_UXN) >> ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_UXN_BIT) << 3;
     510
     511    pWalk->fEffective = s_aEffective[idxPerm];
     512
     513    PGMWALKFAIL const fFailed = paPerm[idxPerm];
     514    if (fFailed == PGM_WALKFAIL_SUCCESS)
     515    {
     516        pWalk->fInfo |= PGM_WALKINFO_SUCCEEDED;
     517        return VINF_SUCCESS;
     518    }
     519
     520    pWalk->fFailed = fFailed | (uLvl << PGM_WALKFAIL_LEVEL_SHIFT);
     521    return VERR_ACCESS_DENIED;
     522}
     523
     524
    320525template<bool a_fTtbr0, uint8_t a_InitialLookupLvl, uint8_t a_GranuleSz, bool a_fTbi, bool a_fEpd>
    321526static PGM_CTX_DECL(int) PGM_CTX(pgm,GstQueryPageFast)(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fFlags, PPGMPTWALKFAST pWalk)
    322527{
    323     RT_NOREF(fFlags); /** @todo */
    324 
    325     /*
    326      * Initial lookup level 3 is not valid and only instantiated because we need two
    327      * bits for the lookup level when creating the index and have to fill the slots.
    328      */
    329     if RT_CONSTEXPR_IF(a_InitialLookupLvl == 3)
    330     {
    331         AssertReleaseFailed();
    332         return VERR_PGM_MODE_IPE;
     528    /* This also applies to TG1 granule sizes, as both share the same encoding in TCR. */
     529    AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_INVALID == ARMV8_TCR_EL1_AARCH64_TG1_INVALID);
     530    AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_16KB    == ARMV8_TCR_EL1_AARCH64_TG1_16KB);
     531    AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_4KB     == ARMV8_TCR_EL1_AARCH64_TG1_4KB);
     532    AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_64KB    == ARMV8_TCR_EL1_AARCH64_TG1_64KB);
     533
     534    uint64_t fLookupMaskFull;
     535    RTGCPTR  offPageMask;
     536
     537    RTGCPTR offLvl1BlockMask;
     538    RTGCPTR offLvl2BlockMask;
     539
     540    uint64_t fNextTableOrPageMask;
     541    uint8_t  cLvl0Shift;
     542    uint8_t  cLvl1Shift;
     543    uint8_t  cLvl2Shift;
     544    uint8_t  cLvl3Shift;
     545
     546    RTGCPHYS fGCPhysLvl1BlockBase;
     547    RTGCPHYS fGCPhysLvl2BlockBase;
     548
     549    /** @todo This needs to go into defines in armv8.h if final. */
     550    if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_4KB)
     551    {
     552        fLookupMaskFull      = RT_BIT_64(9) - 1;
     553        offLvl1BlockMask     = (RTGCPTR)(_1G - 1);
     554        offLvl2BlockMask     = (RTGCPTR)(_2M - 1);
     555        offPageMask          = (RTGCPTR)(_4K - 1);
     556        fNextTableOrPageMask = UINT64_C(0xfffffffff000);
     557        cLvl0Shift           = 39;
     558        cLvl1Shift           = 30;
     559        cLvl2Shift           = 21;
     560        cLvl3Shift           = 12;
     561        fGCPhysLvl1BlockBase = UINT64_C(0xffffc0000000);
     562        fGCPhysLvl2BlockBase = UINT64_C(0xffffffe00000);
     563    }
     564    else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_16KB)
     565    {
     566        fLookupMaskFull      = RT_BIT_64(11) - 1;
     567        offLvl1BlockMask     = 0; /** @todo TCR_EL1.DS support. */
     568        offLvl2BlockMask     = (RTGCPTR)(_32M - 1);
     569        offPageMask          = (RTGCPTR)(_16K - 1);
     570        fNextTableOrPageMask = UINT64_C(0xffffffffc000);
     571        cLvl0Shift           = 47;
     572        cLvl1Shift           = 36;
     573        cLvl2Shift           = 25;
     574        cLvl3Shift           = 14;
     575        fGCPhysLvl1BlockBase = 0; /* Not supported. */
     576        fGCPhysLvl2BlockBase = UINT64_C(0xfffffe000000);
     577    }
     578    else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_64KB)
     579    {
     580        Assert(a_InitialLookupLvl > 0);
     581
     582        fLookupMaskFull      = RT_BIT_64(13)   - 1;
     583        offLvl1BlockMask     = 0; /** @todo FEAT_LPA (RTGCPTR)(4*_1T - 1) */
     584        offLvl2BlockMask     = (RTGCPTR)(_512M - 1);
     585        offPageMask          = (RTGCPTR)(_64K  - 1);
     586        fNextTableOrPageMask = UINT64_C(0xffffffff0000);
     587        cLvl0Shift           = 0; /* No Level 0 with 64KiB granules. */
     588        cLvl1Shift           = 42;
     589        cLvl2Shift           = 29;
     590        cLvl3Shift           = 16;
     591        fGCPhysLvl1BlockBase = 0; /* Not supported. */
     592        fGCPhysLvl2BlockBase = UINT64_C(0xffffe0000000);
    333593    }
    334594    else
    335     {
    336         /* This also applies to TG1 granule sizes, as both share the same encoding in TCR. */
    337         AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_INVALID == ARMV8_TCR_EL1_AARCH64_TG1_INVALID);
    338         AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_16KB    == ARMV8_TCR_EL1_AARCH64_TG1_16KB);
    339         AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_4KB     == ARMV8_TCR_EL1_AARCH64_TG1_4KB);
    340         AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_64KB    == ARMV8_TCR_EL1_AARCH64_TG1_64KB);
    341 
    342         uint64_t fLookupMaskFull;
    343         RTGCPTR  offPageMask;
    344 
    345         RTGCPTR offLvl1BlockMask;
    346         RTGCPTR offLvl2BlockMask;
    347 
    348         uint64_t fNextTableOrPageMask;
    349         uint8_t  cLvl0Shift;
    350         uint8_t  cLvl1Shift;
    351         uint8_t  cLvl2Shift;
    352         uint8_t  cLvl3Shift;
    353 
    354         RTGCPHYS fGCPhysLvl1BlockBase;
    355         RTGCPHYS fGCPhysLvl2BlockBase;
    356 
    357         /** @todo This needs to go into defines in armv8.h if final. */
    358         if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_4KB)
    359         {
    360             fLookupMaskFull      = RT_BIT_64(9) - 1;
    361             offLvl1BlockMask     = (RTGCPTR)(_1G - 1);
    362             offLvl2BlockMask     = (RTGCPTR)(_2M - 1);
    363             offPageMask          = (RTGCPTR)(_4K - 1);
    364             fNextTableOrPageMask = UINT64_C(0xfffffffff000);
    365             cLvl0Shift           = 39;
    366             cLvl1Shift           = 30;
    367             cLvl2Shift           = 21;
    368             cLvl3Shift           = 12;
    369             fGCPhysLvl1BlockBase = UINT64_C(0xffffc0000000);
    370             fGCPhysLvl2BlockBase = UINT64_C(0xffffffe00000);
    371         }
    372         else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_16KB)
    373         {
    374             fLookupMaskFull      = RT_BIT_64(11) - 1;
    375             offLvl1BlockMask     = 0; /** @todo TCR_EL1.DS support. */
    376             offLvl2BlockMask     = (RTGCPTR)(_32M - 1);
    377             offPageMask          = (RTGCPTR)(_16K - 1);
    378             fNextTableOrPageMask = UINT64_C(0xffffffffc000);
    379             cLvl0Shift           = 47;
    380             cLvl1Shift           = 36;
    381             cLvl2Shift           = 25;
    382             cLvl3Shift           = 14;
    383             fGCPhysLvl1BlockBase = 0; /* Not supported. */
    384             fGCPhysLvl2BlockBase = UINT64_C(0xfffffe000000);
    385         }
    386         else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_64KB)
    387         {
    388             Assert(a_InitialLookupLvl > 0);
    389 
    390             fLookupMaskFull      = RT_BIT_64(13)   - 1;
    391             offLvl1BlockMask     = 0; /** @todo FEAT_LPA (RTGCPTR)(4*_1T - 1) */
    392             offLvl2BlockMask     = (RTGCPTR)(_512M - 1);
    393             offPageMask          = (RTGCPTR)(_64K  - 1);
    394             fNextTableOrPageMask = UINT64_C(0xffffffff0000);
    395             cLvl0Shift           = 0; /* No Level 0 with 64KiB granules. */
    396             cLvl1Shift           = 42;
    397             cLvl2Shift           = 29;
    398             cLvl3Shift           = 16;
    399             fGCPhysLvl1BlockBase = 0; /* Not supported. */
    400             fGCPhysLvl2BlockBase = UINT64_C(0xffffe0000000);
    401         }
    402         else
    403             AssertReleaseFailedReturn(VERR_PGM_MODE_IPE);
    404 
    405         /* Get the initial lookup mask. */
    406         uint8_t const bEl = CPUMGetGuestEL(pVCpu);
    407         uint64_t fLookupMask;
    408         if RT_CONSTEXPR_IF(a_fTtbr0 == true)
    409             fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr0[bEl];
    410         else
    411             fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr1[bEl];
    412 
    413         RTGCPHYS         GCPhysPt = CPUMGetEffectiveTtbr(pVCpu, GCPtr);
    414         PARMV8VMSA64DESC paDesc   = NULL;
    415         ARMV8VMSA64DESC  Desc;
    416         int rc;
    417         if RT_CONSTEXPR_IF(a_InitialLookupLvl == 0)
    418         {
    419             Assert(cLvl0Shift != 0);
    420             uint8_t const uLvl = 0;
    421 
    422             rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
    423             if (RT_SUCCESS(rc)) { /* probable */ }
    424             else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
    425 
    426             Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl0Shift) & fLookupMask]);
    427             if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
    428             else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
    429 
    430             if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
    431             else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /** @todo Only supported if TCR_EL1.DS is set. */
    432 
    433             /* Full lookup mask from now on. */
    434             fLookupMask = fLookupMaskFull;
    435             GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
    436         }
    437 
    438         if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 1)
    439         {
    440             uint8_t const uLvl = 1;
    441 
    442             rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
    443             if (RT_SUCCESS(rc)) { /* probable */ }
    444             else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
    445 
    446             Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl1Shift) & fLookupMask]);
    447             if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
    448             else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
    449 
    450             if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
    451             else
    452             {
    453                 if (offLvl1BlockMask != 0)
    454                 {
    455                     /* Block descriptor. */
    456                     pWalk->GCPtr       = GCPtr;
    457                     pWalk->fInfo       = PGM_WALKINFO_SUCCEEDED | PGM_WALKINFO_GIGANTIC_PAGE;
    458                     pWalk->GCPhys      = (RTGCPHYS)(Desc & fGCPhysLvl1BlockBase) | (GCPtr & offLvl1BlockMask);
    459                     return VINF_SUCCESS;
    460                 }
    461                 else
    462                     return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl);
    463             }
    464 
    465             /* Full lookup mask from now on. */
    466             fLookupMask = fLookupMaskFull;
    467             GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
    468         }
    469 
    470         if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 2)
    471         {
    472             uint8_t const uLvl = 2;
    473 
    474             rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
    475             if (RT_SUCCESS(rc)) { /* probable */ }
    476             else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
    477 
    478             Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl2Shift) & fLookupMask]);
    479             if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
    480             else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
    481 
    482             if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
    483             else
    484             {
    485                 /* Block descriptor. */
    486                 pWalk->GCPtr      = GCPtr;
    487                 pWalk->fInfo      = PGM_WALKINFO_SUCCEEDED | PGM_WALKINFO_BIG_PAGE;
    488                 pWalk->GCPhys     = (RTGCPHYS)(Desc & fGCPhysLvl2BlockBase) | (GCPtr & offLvl2BlockMask);
    489                 return VINF_SUCCESS;
    490             }
    491 
    492             /* Full lookup mask from now on. */
    493             fLookupMask = fLookupMaskFull;
    494             GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
    495         }
    496 
    497         AssertCompile(a_InitialLookupLvl <= 3);
    498         uint8_t const uLvl = 3;
    499 
    500         /* Next level. */
     595        AssertReleaseFailedReturn(VERR_PGM_MODE_IPE);
     596
     597    /* Get the initial lookup mask. */
     598    uint8_t const bEl = (fFlags & PGMQPAGE_F_USER_MODE) ? 0 : 1; /** @todo EL2 support */
     599    uint64_t fLookupMask;
     600    if RT_CONSTEXPR_IF(a_fTtbr0 == true)
     601        fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr0[bEl];
     602    else
     603        fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr1[bEl];
     604
     605    RTGCPHYS         GCPhysPt = CPUMGetEffectiveTtbr(pVCpu, GCPtr);
     606    PARMV8VMSA64DESC paDesc   = NULL;
     607    ARMV8VMSA64DESC  Desc;
     608    int rc;
     609    if RT_CONSTEXPR_IF(a_InitialLookupLvl == 0)
     610    {
     611        Assert(cLvl0Shift != 0);
     612        uint8_t const uLvl = 0;
     613
    501614        rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
    502615        if (RT_SUCCESS(rc)) { /* probable */ }
    503616        else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
    504617
    505         Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl3Shift) & fLookupMask]);
     618        Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl0Shift) & fLookupMask]);
    506619        if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
    507620        else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
    508621
    509622        if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
    510         else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /* No block descriptors. */
    511 
    512         pWalk->GCPtr  = GCPtr;
    513         pWalk->fInfo  = PGM_WALKINFO_SUCCEEDED;
    514         pWalk->GCPhys = (RTGCPHYS)(Desc & fNextTableOrPageMask) | (GCPtr & offPageMask);
    515         return VINF_SUCCESS;
    516     }
     623        else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /** @todo Only supported if TCR_EL1.DS is set. */
     624
     625        /* Full lookup mask from now on. */
     626        fLookupMask = fLookupMaskFull;
     627        GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
     628    }
     629
     630    if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 1)
     631    {
     632        uint8_t const uLvl = 1;
     633
     634        rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
     635        if (RT_SUCCESS(rc)) { /* probable */ }
     636        else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
     637
     638        Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl1Shift) & fLookupMask]);
     639        if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
     640        else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
     641
     642        if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
     643        else
     644        {
     645            if (offLvl1BlockMask != 0)
     646            {
     647                /* Block descriptor. */
     648                pWalk->GCPtr      = GCPtr;
     649                pWalk->fInfo      = PGM_WALKINFO_GIGANTIC_PAGE;
     650                pWalk->GCPhys     = (RTGCPHYS)(Desc & fGCPhysLvl1BlockBase) | (GCPtr & offLvl1BlockMask);
     651                return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl);
     652            }
     653            else
     654                return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl);
     655        }
     656
     657        /* Full lookup mask from now on. */
     658        fLookupMask = fLookupMaskFull;
     659        GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
     660    }
     661
     662    if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 2)
     663    {
     664        uint8_t const uLvl = 2;
     665
     666        rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
     667        if (RT_SUCCESS(rc)) { /* probable */ }
     668        else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
     669
     670        Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl2Shift) & fLookupMask]);
     671        if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
     672        else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
     673
     674        if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
     675        else
     676        {
     677            /* Block descriptor. */
     678            pWalk->GCPtr      = GCPtr;
     679            pWalk->fInfo      = PGM_WALKINFO_BIG_PAGE;
     680            pWalk->GCPhys     = (RTGCPHYS)(Desc & fGCPhysLvl2BlockBase) | (GCPtr & offLvl2BlockMask);
     681            return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl);
     682        }
     683
     684        /* Full lookup mask from now on. */
     685        fLookupMask = fLookupMaskFull;
     686        GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask);
     687    }
     688
     689    AssertCompile(a_InitialLookupLvl <= 3);
     690    uint8_t const uLvl = 3;
     691
     692    /* Next level. */
     693    rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc);
     694    if (RT_SUCCESS(rc)) { /* probable */ }
     695    else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc);
     696
     697    Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl3Shift) & fLookupMask]);
     698    if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ }
     699    else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl);
     700
     701    if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ }
     702    else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /* No block descriptors. */
     703
     704    pWalk->GCPtr  = GCPtr;
     705    pWalk->GCPhys = (RTGCPHYS)(Desc & fNextTableOrPageMask) | (GCPtr & offPageMask);
     706    return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl);
    517707}
    518708
     
    632822    {
    633823        uint64_t const u64Tsz = (u64RegTcr >> a_offTsz) & 0x1f;
    634         uint64_t const u64Tg  = (u64RegTcr >> a_offTg)  & 0x3;
     824        uint64_t       u64Tg  = (u64RegTcr >> a_offTg)  & 0x3;
    635825        bool     const fTbi   = RT_BOOL(u64RegTcr & RT_BIT_64(a_offTbi));
    636826        bool     const fEpd   = RT_BOOL(u64RegTcr & RT_BIT_64(a_offEpd));
    637827
    638828        /*
    639          * From: https://github.com/codingbelief/arm-architecture-reference-manual-for-armv8-a/blob/master/en/chapter_d4/d42_2_controlling_address_translation_stages.md
    640          * For all translation stages
    641          * The maximum TxSZ value is 39. If TxSZ is programmed to a value larger than 39 then it is IMPLEMENTATION DEFINED whether:
    642          *     - The implementation behaves as if the field is programmed to 39 for all purposes other than reading back the value of the field.
    643          *     - Any use of the TxSZ value generates a Level 0 Translation fault for the stage of translation at which TxSZ is used.
     829         * From the ARM reference manual regarding granule size choices:
    644830         *
    645          * For a stage 1 translation
    646          * The minimum TxSZ value is 16. If TxSZ is programmed to a value smaller than 16 then it is IMPLEMENTATION DEFINED whether:
    647          *     - The implementation behaves as if the field were programmed to 16 for all purposes other than reading back the value of the field.
    648          *     - Any use of the TxSZ value generates a stage 1 Level 0 Translation fault.
     831         * If the value is programmed to either a reserved value or a size that has not been implemented, then
     832         * the hardware will treat the field as if it has been programmed to an IMPLEMENTATION DEFINED
     833         * choice of the sizes that has been implemented for all purposes other than the value read back from
     834         * this register.
    649835         *
    650          * We currently choose the former for both.
     836         * We always fall back on the 4KiB granule size in that case.
    651837         */
     838        /** @todo Can this be made table driven? */
    652839        uint64_t uLookupLvl;
    653         if (/*u64Tsz >= 16 &&*/ u64Tsz <= 24)
     840        if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_16KB)
    654841        {
    655             uLookupLvl = 0;
    656             if (u64Tsz >= 16)
    657                 *pfInitialLookupMask = RT_BIT_64(24 - u64Tsz + 1) - 1;
    658             else
    659                 *pfInitialLookupMask = RT_BIT_64(24 - 16 + 1) - 1;
     842            if (u64Tsz <= 16)
     843            {
     844                uLookupLvl = 0;
     845                *pfInitialLookupMask = 0x1;
     846            }
     847            else if (u64Tsz >= 17 && u64Tsz <= 27)
     848            {
     849                uLookupLvl = 1;
     850                *pfInitialLookupMask = RT_BIT_64(28 - u64Tsz + 1) - 1;
     851            }
     852            else if (u64Tsz >= 28 && u64Tsz <= 38)
     853            {
     854                uLookupLvl = 2;
     855                *pfInitialLookupMask = RT_BIT_64(38 - u64Tsz + 1) - 1;
     856            }
     857            else /* if (u64Tsz == 39) */
     858            {
     859                uLookupLvl = 3;
     860                *pfInitialLookupMask = 0x1;
     861            }
    660862        }
    661         else if (u64Tsz >= 25 && u64Tsz <= 33)
     863        else if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_64KB)
    662864        {
    663             uLookupLvl = 1;
    664             *pfInitialLookupMask = RT_BIT_64(33 - u64Tsz + 1) - 1;
     865            if (/*u64Tsz >= 16 &&*/ u64Tsz <= 21)
     866            {
     867                uLookupLvl = 1;
     868                *pfInitialLookupMask = RT_BIT_64(21 - u64Tsz + 1) - 1;
     869            }
     870            else if (u64Tsz >= 22 && u64Tsz <= 34)
     871            {
     872                uLookupLvl = 2;
     873                *pfInitialLookupMask = RT_BIT_64(34 - u64Tsz + 1) - 1;
     874            }
     875            else /*if (u64Tsz >= 35 && u64Tsz <= 39)*/
     876            {
     877                uLookupLvl = 3;
     878                if (u64Tsz <= 39)
     879                    *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1;
     880                else
     881                    *pfInitialLookupMask = 0x1;
     882            }
    665883        }
    666         else /*if (u64Tsz >= 34 && u64Tsz <= 39)*/
     884        else /* if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_4KB) */
    667885        {
    668             uLookupLvl = 2;
    669             if (u64Tsz <= 39)
    670                 *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1;
    671             else
    672                 *pfInitialLookupMask = RT_BIT_64(39 - 39 + 1) - 1;
     886            /*
     887             * From: https://github.com/codingbelief/arm-architecture-reference-manual-for-armv8-a/blob/master/en/chapter_d4/d42_2_controlling_address_translation_stages.md
     888             * For all translation stages
     889             * The maximum TxSZ value is 39. If TxSZ is programmed to a value larger than 39 then it is IMPLEMENTATION DEFINED whether:
     890             *     - The implementation behaves as if the field is programmed to 39 for all purposes other than reading back the value of the field.
     891             *     - Any use of the TxSZ value generates a Level 0 Translation fault for the stage of translation at which TxSZ is used.
     892             *
     893             * For a stage 1 translation
     894             * The minimum TxSZ value is 16. If TxSZ is programmed to a value smaller than 16 then it is IMPLEMENTATION DEFINED whether:
     895             *     - The implementation behaves as if the field were programmed to 16 for all purposes other than reading back the value of the field.
     896             *     - Any use of the TxSZ value generates a stage 1 Level 0 Translation fault.
     897             *
     898             * We currently choose the former for both.
     899             */
     900            if (/*u64Tsz >= 16 &&*/ u64Tsz <= 24)
     901            {
     902                uLookupLvl = 0;
     903                if (u64Tsz >= 16)
     904                    *pfInitialLookupMask = RT_BIT_64(24 - u64Tsz + 1) - 1;
     905                else
     906                    *pfInitialLookupMask = RT_BIT_64(9) - 1;
     907            }
     908            else if (u64Tsz >= 25 && u64Tsz <= 33)
     909            {
     910                uLookupLvl = 1;
     911                *pfInitialLookupMask = RT_BIT_64(33 - u64Tsz + 1) - 1;
     912            }
     913            else /*if (u64Tsz >= 34 && u64Tsz <= 39)*/
     914            {
     915                uLookupLvl = 2;
     916                if (u64Tsz <= 39)
     917                    *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1;
     918                else
     919                    *pfInitialLookupMask = 0x1;
     920            }
     921
     922            u64Tg = ARMV8_TCR_EL1_AARCH64_TG0_4KB;
    673923        }
    674924
Note: See TracChangeset for help on using the changeset viewer.

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