VirtualBox

Changeset 101190 in vbox for trunk/src


Ignore:
Timestamp:
Sep 20, 2023 11:51:34 AM (15 months ago)
Author:
vboxsync
Message:

VMM/CPUM-armv8: Include the guest ID registers in the saved state and compare that the host can provide exposed features to the guest when the state is being loaded, bugref:10525

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp

    r101121 r101190  
    499499{
    500500    AssertReturn(uPass == 0, VERR_SSM_UNEXPECTED_PASS);
    501     /** @todo */ RT_NOREF(pVM, pSSM);
     501    cpumR3SaveCpuId(pVM, pSSM);
    502502    return VINF_SSM_DONT_CALL_AGAIN;
    503503}
     
    526526        SSMR3PutU32(pSSM, pVCpu->cpum.s.fChanged);
    527527    }
     528
     529    cpumR3SaveCpuId(pVM, pSSM);
    528530    return VINF_SUCCESS;
    529531}
     
    584586
    585587    pVM->cpum.s.fPendingRestore = false;
    586     return VINF_SUCCESS;
     588
     589    /* Load CPUID and explode guest features. */
     590    return cpumR3LoadCpuId(pVM, pSSM, uVersion);
    587591}
    588592
  • trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId-armv8.cpp

    r101186 r101190  
    654654    *ppIdRegs = &pVM->cpum.s.GuestIdRegs;
    655655    return VINF_SUCCESS;
     656}
     657
     658
     659/*
     660 *
     661 *
     662 * Saved state related code.
     663 * Saved state related code.
     664 * Saved state related code.
     665 *
     666 *
     667 */
     668/** Saved state field descriptors for CPUMIDREGS. */
     669static const SSMFIELD g_aCpumIdRegsFields[] =
     670{
     671    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Pfr0El1),
     672    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Pfr1El1),
     673    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Dfr0El1),
     674    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Dfr1El1),
     675    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Afr0El1),
     676    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Afr1El1),
     677    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Isar0El1),
     678    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Isar1El1),
     679    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Isar2El1),
     680    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Mmfr0El1),
     681    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Mmfr1El1),
     682    SSMFIELD_ENTRY(CPUMIDREGS, u64RegIdAa64Mmfr2El1),
     683    SSMFIELD_ENTRY(CPUMIDREGS, u64RegClidrEl1),
     684    SSMFIELD_ENTRY(CPUMIDREGS, u64RegCtrEl0),
     685    SSMFIELD_ENTRY(CPUMIDREGS, u64RegDczidEl0),
     686    SSMFIELD_ENTRY_TERM()
     687};
     688
     689
     690/**
     691 * Called both in pass 0 and the final pass.
     692 *
     693 * @param   pVM                 The cross context VM structure.
     694 * @param   pSSM                The saved state handle.
     695 */
     696void cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM)
     697{
     698    /*
     699     * Save all the CPU ID leaves.
     700     */
     701    SSMR3PutStructEx(pSSM, &pVM->cpum.s.GuestIdRegs, sizeof(pVM->cpum.s.GuestIdRegs), 0, g_aCpumIdRegsFields, NULL);
     702}
     703
     704
     705/**
     706 * Loads the CPU ID leaves saved by pass 0, inner worker.
     707 *
     708 * @returns VBox status code.
     709 * @param   pVM                 The cross context VM structure.
     710 * @param   pSSM                The saved state handle.
     711 * @param   uVersion            The format version.
     712 * @param   pGuestIdRegs        The guest ID register as loaded from the saved state.
     713 */
     714static int cpumR3LoadCpuIdInner(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, PCCPUMIDREGS pGuestIdRegs)
     715{
     716    /*
     717     * This can be skipped.
     718     */
     719    bool fStrictCpuIdChecks;
     720    CFGMR3QueryBoolDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"), "StrictCpuIdChecks", &fStrictCpuIdChecks, true);
     721
     722    /*
     723     * Define a bunch of macros for simplifying the santizing/checking code below.
     724     */
     725    /* For checking guest features. */
     726#define CPUID_GST_FEATURE_RET(a_IdReg, a_Field) \
     727    do { \
     728        if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
     729        { \
     730            if (fStrictCpuIdChecks) \
     731                return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS, \
     732                                         N_(#a_Field " is not supported by the host but has already exposed to the guest")); \
     733            LogRel(("CPUM: " #a_Field " is not supported by the host but has already been exposed to the guest\n")); \
     734        } \
     735    } while (0)
     736#define CPUID_GST_FEATURE_WRN(a_IdReg, a_Field) \
     737    do { \
     738        if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
     739            LogRel(("CPUM: " #a_Field " is not supported by the host but has already been exposed to the guest\n")); \
     740    } while (0)
     741#define CPUID_GST_FEATURE_EMU(a_IdReg, a_Field) \
     742    do { \
     743        if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
     744            LogRel(("CPUM: Warning - " #a_Field " is not supported by the host but has already been exposed to the guest. This may impact performance.\n")); \
     745    } while (0)
     746#define CPUID_GST_FEATURE_IGN(a_IdReg, a_Field) do { } while (0)
     747
     748    RT_NOREF(uVersion);
     749    /*
     750     * Verify that we can support the features already exposed to the guest on
     751     * this host.
     752     *
     753     * Most of the features we're emulating requires intercepting instruction
     754     * and doing it the slow way, so there is no need to warn when they aren't
     755     * present in the host CPU.  Thus we use IGN instead of EMU on these.
     756     *
     757     * Trailing comments:
     758     *      "EMU"  - Possible to emulate, could be lots of work and very slow.
     759     *      "EMU?" - Can this be emulated?
     760     */
     761    /* ID_AA64ISAR0_EL1 */
     762    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_AES);
     763    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA1);
     764    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA2);
     765    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_CRC32);
     766    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_ATOMIC);
     767    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TME);
     768    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_RDM);
     769    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA3);
     770    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SM3);
     771    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SM4);
     772    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_DP);
     773    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_FHM);
     774    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TS);
     775    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TLB);
     776    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_RNDR);
     777
     778    /* ID_AA64ISAR1_EL1 */
     779    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_DPB);
     780    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_APA);
     781    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_API);
     782    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_FJCVTZS);
     783    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_LRCPC);
     784    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_GPA);
     785    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_GPI);
     786    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_FRINTTS);
     787    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_SB);
     788    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_SPECRES);
     789    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_BF16);
     790    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_DGH);
     791    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_I8MM);
     792    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_XS);
     793    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_LS64);
     794
     795    /* ID_AA64ISAR2_EL1 */
     796    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_WFXT);
     797    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_RPRES);
     798    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_GPA3);
     799    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_APA3);
     800    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_MOPS);
     801    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_BC);
     802    CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_PACFRAC);
     803
     804#undef CPUID_GST_FEATURE_RET
     805#undef CPUID_GST_FEATURE_WRN
     806#undef CPUID_GST_FEATURE_EMU
     807#undef CPUID_GST_FEATURE_IGN
     808
     809    /*
     810     * We're good, commit the CPU ID registers.
     811     */
     812    pVM->cpum.s.GuestIdRegs = *pGuestIdRegs;
     813    return VINF_SUCCESS;
     814}
     815
     816
     817/**
     818 * Loads the CPU ID leaves saved by pass 0.
     819 *
     820 * @returns VBox status code.
     821 * @param   pVM                 The cross context VM structure.
     822 * @param   pSSM                The saved state handle.
     823 * @param   uVersion            The format version.
     824 */
     825int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
     826{
     827    CPUMIDREGS GuestIdRegs;
     828    int rc = SSMR3GetStructEx(pSSM, &GuestIdRegs, sizeof(GuestIdRegs), 0, g_aCpumIdRegsFields, NULL);
     829    AssertRCReturn(rc, rc);
     830
     831    return cpumR3LoadCpuIdInner(pVM, pSSM, uVersion, &GuestIdRegs);
    656832}
    657833
  • trunk/src/VBox/VMM/include/CPUMInternal-armv8.h

    r101121 r101190  
    175175DECLHIDDEN(int)       cpumR3SysRegStrictInitChecks(void);
    176176
     177void                  cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM);
     178int                   cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion);
     179
    177180DECLCALLBACK(void)    cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    178181DECLCALLBACK(void)    cpumR3CpuFeatInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
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