VirtualBox

Ignore:
Timestamp:
Apr 4, 2025 5:36:38 PM (5 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168306
Message:

VMM/PGM: Move some code for the ARMv8 page table walking around in order to be able to create standalone testcase, bugref:10388

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PGMAll.cpp

    r108843 r108856  
    966966
    967967#elif defined(VBOX_VMM_TARGET_ARMV8)
    968 
    969 /*
    970  *
    971  * Mode criteria:
    972  *      - MMU enabled/disabled.
    973  *      - TCR_EL1.TG0 (granule size for TTBR0_EL1).
    974  *      - TCR_EL1.TG1 (granule size for TTBR1_EL1).
    975  *      - TCR_EL1.T0SZ (address space size for TTBR0_EL1).
    976  *      - TCR_EL1.T1SZ (address space size for TTBR1_EL1).
    977  *      - TCR_EL1.IPS (intermediate physical address size).
    978  *      - TCR_EL1.TBI0 (ignore top address byte for TTBR0_EL1).
    979  *      - TCR_EL1.TBI1 (ignore top address byte for TTBR1_EL1).
    980  *      - TCR_EL1.HPD0 (hierarchical permisson disables for TTBR0_EL1).
    981  *      - TCR_EL1.HPD1 (hierarchical permisson disables for TTBR1_EL1).
    982  *      - More ?
    983  *
    984  * Other relevant modifiers:
    985  *      - TCR_EL1.HA - hardware access bit.
    986  *      - TCR_EL1.HD - hardware dirty bit.
    987  *      - ++
    988  *
    989  * Each privilege EL (1,2,3) has their own TCR_ELx and TTBR[01]_ELx registers,
    990  * so they should all have their own separate modes.  To make it simpler,
    991  * why not do a separate mode for TTBR0_ELx and one for TTBR1_ELx.  Top-level
    992  * functions determins which of the roots to use and call template (C++)
    993  * functions that takes it from there.  Using the preprocessor function template
    994  * approach is _not_ desirable here.
    995  *
    996  */
    997 
    998 /** @todo  Proper ARMv8 guest support for PGM;  The idea is to cache the
    999  *         configuration register values and lazily reconfigure when they
    1000  *         change. */
    1001968# include "PGMAllGst-armv8.cpp.h"
    1002 
    1003 /**
    1004  * Guest mode data array.
    1005  */
    1006 PGMMODEDATAGST const g_aPgmGuestModeData[PGM_GUEST_MODE_DATA_ARRAY_SIZE] =
    1007 {
    1008     { UINT32_MAX, NULL, NULL, NULL, NULL, NULL }, /* 0 */
    1009     {
    1010         PGM_TYPE_NONE,
    1011         PGM_CTX(pgm,GstNoneGetPage),
    1012         PGM_CTX(pgm,GstNoneQueryPageFast),
    1013         PGM_CTX(pgm,GstNoneModifyPage),
    1014         PGM_CTX(pgm,GstNoneWalk),
    1015         PGM_CTX(pgm,GstNoneEnter),
    1016         PGM_CTX(pgm,GstNoneExit),
    1017     },
    1018 
    1019 #define PGM_MODE_TYPE_CREATE(a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd) \
    1020         (2 + (  (a_fEpd ? RT_BIT_32(6) : 0)     \
    1021               | (a_fTbi ? RT_BIT_32(5) : 0)     \
    1022               | (a_GranuleSz << 3)              \
    1023               | (a_InitialLookupLvl << 1)       \
    1024               | (a_fTtbr0 ? RT_BIT_32(0) : 0) ))
    1025 
    1026 #define PGM_MODE_CREATE_EX(a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd) \
    1027     { \
    1028         PGM_MODE_TYPE_CREATE(a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd), \
    1029         PGM_CTX(pgm,GstGetPage)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd>, \
    1030         PGM_CTX(pgm,GstQueryPageFast)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd>, \
    1031         PGM_CTX(pgm,GstModifyPage)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd>, \
    1032         PGM_CTX(pgm,GstWalk)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd>, \
    1033         PGM_CTX(pgm,GstEnter)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd>, \
    1034         PGM_CTX(pgm,GstExit)<a_fTtbr0, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd> \
    1035     }
    1036 
    1037 #define PGM_MODE_CREATE_TTBR(a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd) \
    1038     PGM_MODE_CREATE_EX(false, a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd), \
    1039     PGM_MODE_CREATE_EX(true,  a_InitialLookupLvl, a_GranuleSz, a_fTbi, a_fEpd)
    1040 
    1041 #define PGM_MODE_CREATE_LOOKUP_LVL(a_GranuleSz, a_fTbi, a_fEpd) \
    1042     PGM_MODE_CREATE_TTBR(0,  a_GranuleSz, a_fTbi, a_fEpd ), \
    1043     PGM_MODE_CREATE_TTBR(1,  a_GranuleSz, a_fTbi, a_fEpd ), \
    1044     PGM_MODE_CREATE_TTBR(2,  a_GranuleSz, a_fTbi, a_fEpd ), \
    1045     PGM_MODE_CREATE_TTBR(3,  a_GranuleSz, a_fTbi, a_fEpd ) /* Invalid */
    1046 
    1047 #define PGM_MODE_CREATE_GRANULE_SZ(a_fTbi, a_fEpd) \
    1048     PGM_MODE_CREATE_LOOKUP_LVL(ARMV8_TCR_EL1_AARCH64_TG1_INVALID, a_fTbi, a_fEpd), \
    1049     PGM_MODE_CREATE_LOOKUP_LVL(ARMV8_TCR_EL1_AARCH64_TG1_16KB,    a_fTbi, a_fEpd), \
    1050     PGM_MODE_CREATE_LOOKUP_LVL(ARMV8_TCR_EL1_AARCH64_TG1_4KB,     a_fTbi, a_fEpd), \
    1051     PGM_MODE_CREATE_LOOKUP_LVL(ARMV8_TCR_EL1_AARCH64_TG1_64KB,    a_fTbi, a_fEpd)
    1052 
    1053 #define PGM_MODE_CREATE_TBI(a_fEpd) \
    1054     PGM_MODE_CREATE_GRANULE_SZ(false, a_fEpd), \
    1055     PGM_MODE_CREATE_GRANULE_SZ(true,  a_fEpd)
    1056 
    1057     /* Recursive expansion for the win, this will blow up to 128 entries covering all possible modes. */
    1058     PGM_MODE_CREATE_TBI(false),
    1059     PGM_MODE_CREATE_TBI(true)
    1060 
    1061 #undef PGM_MODE_CREATE_TBI
    1062 #undef PGM_MODE_CREATE_GRANULE_SZ
    1063 #undef PGM_MODE_CREATE_LOOKUP_LVL
    1064 #undef PGM_MODE_CREATE_TTBR
    1065 #undef PGM_MODE_CREATE_EX
    1066 };
    1067 
    1068969#else
    1069970# error "port me"
     
    36563557#elif defined(VBOX_VMM_TARGET_ARMV8)
    36573558
    3658 template<uint8_t a_offTsz, uint8_t a_offTg, uint8_t a_offTbi, uint8_t a_offEpd, bool a_fTtbr0>
    3659 DECLINLINE(uintptr_t) pgmR3DeduceTypeFromTcr(uint64_t u64RegSctlr, uint64_t u64RegTcr, uint64_t *pfInitialLookupMask)
    3660 {
    3661     uintptr_t idxNewGst = 0;
    3662 
    3663     /*
    3664      * MMU enabled at all?
    3665      * Technically this is incorrect as we use ARMV8_SCTLR_EL1_M regardless of the EL but the bit is the same
    3666      * for all exception levels.
    3667      */
    3668     if (u64RegSctlr & ARMV8_SCTLR_EL1_M)
    3669     {
    3670         uint64_t const u64Tsz = (u64RegTcr >> a_offTsz) & 0x1f;
    3671         uint64_t const u64Tg  = (u64RegTcr >> a_offTg)  & 0x3;
    3672         bool     const fTbi   = RT_BOOL(u64RegTcr & RT_BIT_64(a_offTbi));
    3673         bool     const fEpd   = RT_BOOL(u64RegTcr & RT_BIT_64(a_offEpd));
    3674 
    3675         /*
    3676          * From: https://github.com/codingbelief/arm-architecture-reference-manual-for-armv8-a/blob/master/en/chapter_d4/d42_2_controlling_address_translation_stages.md
    3677          * For all translation stages
    3678          * The maximum TxSZ value is 39. If TxSZ is programmed to a value larger than 39 then it is IMPLEMENTATION DEFINED whether:
    3679          *     - The implementation behaves as if the field is programmed to 39 for all purposes other than reading back the value of the field.
    3680          *     - Any use of the TxSZ value generates a Level 0 Translation fault for the stage of translation at which TxSZ is used.
    3681          *
    3682          * For a stage 1 translation
    3683          * The minimum TxSZ value is 16. If TxSZ is programmed to a value smaller than 16 then it is IMPLEMENTATION DEFINED whether:
    3684          *     - The implementation behaves as if the field were programmed to 16 for all purposes other than reading back the value of the field.
    3685          *     - Any use of the TxSZ value generates a stage 1 Level 0 Translation fault.
    3686          *
    3687          * We currently choose the former for both.
    3688          */
    3689         uint64_t uLookupLvl;
    3690         if (/*u64Tsz >= 16 &&*/ u64Tsz <= 24)
    3691         {
    3692             uLookupLvl = 0;
    3693             if (u64Tsz >= 16)
    3694                 *pfInitialLookupMask = RT_BIT_64(24 - u64Tsz + 1) - 1;
    3695             else
    3696                 *pfInitialLookupMask = RT_BIT_64(24 - 16 + 1) - 1;
    3697         }
    3698         else if (u64Tsz >= 25 && u64Tsz <= 33)
    3699         {
    3700             uLookupLvl = 1;
    3701             *pfInitialLookupMask = RT_BIT_64(33 - u64Tsz + 1) - 1;
    3702         }
    3703         else /*if (u64Tsz >= 34 && u64Tsz <= 39)*/
    3704         {
    3705             uLookupLvl = 2;
    3706             if (u64Tsz <= 39)
    3707                 *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1;
    3708             else
    3709                 *pfInitialLookupMask = RT_BIT_64(39 - 39 + 1) - 1;
    3710         }
    3711 
    3712         /* Build the index into the PGM mode callback table for the given config. */
    3713         idxNewGst = PGM_MODE_TYPE_CREATE(a_fTtbr0, uLookupLvl, u64Tg, fTbi, fEpd);
    3714     }
    3715     else
    3716         idxNewGst = PGM_TYPE_NONE;
    3717 
    3718     return idxNewGst;
    3719 }
    3720 
    3721 
    37223559VMM_INT_DECL(int) PGMChangeMode(PVMCPUCC pVCpu, uint8_t bEl, uint64_t u64RegSctlr, uint64_t u64RegTcr)
    37233560{
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