VirtualBox

Changeset 97231 in vbox for trunk


Ignore:
Timestamp:
Oct 19, 2022 9:12:57 AM (2 years ago)
Author:
vboxsync
Message:

VMM/CPUM: Define our own X86EFLAGS/X86RFLAGS structures so we can use reserved bits for internal state.

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpum.h

    r97213 r97231  
    15171517
    15181518#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
    1519 VMMDECL(int)                CPUMCpuIdCollectLeavesX86(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves);
    1520 VMMDECL(CPUMCPUVENDOR)      CPUMCpuIdDetectX86VendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX);
     1519VMMDECL(int)            CPUMCpuIdCollectLeavesX86(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves);
     1520VMMDECL(CPUMCPUVENDOR)  CPUMCpuIdDetectX86VendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX);
    15211521#endif
     1522
     1523VMM_INT_DECL(bool)      CPUMAssertGuestRFlagsCookie(PVM pVM, PVMCPU pVCpu);
     1524
    15221525
    15231526/** @name Guest Register Getters.
     
    27532756DECLINLINE(void) CPUMSetGuestVmxVmSucceed(PCPUMCTX pCtx)
    27542757{
    2755     pCtx->eflags.u32 &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
     2758    pCtx->eflags.uBoth &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
    27562759}
    27572760
     
    27632766DECLINLINE(void) CPUMSetGuestVmxVmFailInvalid(PCPUMCTX pCtx)
    27642767{
    2765     pCtx->eflags.u32 &= ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
    2766     pCtx->eflags.u32 |= X86_EFL_CF;
     2768    pCtx->eflags.uBoth &= ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
     2769    pCtx->eflags.uBoth |= X86_EFL_CF;
    27672770}
    27682771
     
    27752778DECLINLINE(void) CPUMSetGuestVmxVmFailValid(PCPUMCTX pCtx, VMXINSTRERR enmInsErr)
    27762779{
    2777     pCtx->eflags.u32 &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
    2778     pCtx->eflags.u32 |= X86_EFL_ZF;
     2780    pCtx->eflags.uBoth &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
     2781    pCtx->eflags.uBoth |= X86_EFL_ZF;
    27792782    pCtx->hwvirt.vmx.Vmcs.u32RoVmInstrError = enmInsErr;
    27802783}
  • trunk/include/VBox/vmm/cpumctx.h

    r97213 r97231  
    227227AssertCompileSize(CPUMHWVIRT, 4);
    228228#endif
     229
     230/** Number of EFLAGS bits we put aside for the hardware EFLAGS, with the bits
     231 * above this we use for storing internal state not visible to the guest.
     232 *
     233 * The initial plan was to use 24 or 22 here and keep bits that needs clearing
     234 * on instruction boundrary in the top of the first 32 bits, allowing us to use
     235 * a AND with a 32-bit immediate for clearing both RF and the interrupt shadow
     236 * bits.  However, when using anything less than 32, there is a significant code
     237 * size increase: VMMR0.ro is 2475709 bytes with 32 bits, 2482069 bytes with 24
     238 * bits, and 2482261 bytes with 22 bits.
     239 *
     240 * So, for now we're best off setting this to 32.
     241 */
     242#define CPUMX86EFLAGS_HW_BITS       32
     243/** Mask for the hardware EFLAGS bits, 64-bit version. */
     244#define CPUMX86EFLAGS_HW_MASK_64    (RT_BIT_64(CPUMX86EFLAGS_HW_BITS) - UINT64_C(1))
     245/** Mask for the hardware EFLAGS bits, 32-bit version. */
     246#if CPUMX86EFLAGS_HW_BITS == 32
     247# define CPUMX86EFLAGS_HW_MASK_32   UINT32_MAX
     248#elif CPUMX86EFLAGS_HW_BITS < 32 && CPUMX86EFLAGS_HW_BITS >= 22
     249# define CPUMX86EFLAGS_HW_MASK_32   (RT_BIT_32(CPUMX86EFLAGS_HW_BITS) - UINT32_C(1))
     250#else
     251# error "Misconfigured CPUMX86EFLAGS_HW_BITS value!"
     252#endif
     253
     254/** Mask of internal flags kept with EFLAGS, 64-bit version.   */
     255#define CPUMX86EFLAGS_INT_MASK_64   UINT64_C(0x0000000000000000)
     256/** Mask of internal flags kept with EFLAGS, 32-bit version.   */
     257#define CPUMX86EFLAGS_INT_MASK_32   UINT64_C(0x0000000000000000)
     258
     259
     260/**
     261 * CPUM EFLAGS.
     262 *
     263 * This differs from X86EFLAGS in that we could use bits 31:22 for internal
     264 * purposes, see CPUMX86EFLAGS_HW_BITS.
     265 */
     266typedef union CPUMX86EFLAGS
     267{
     268    /** The full unsigned view, both hardware and VBox bits. */
     269    uint32_t        uBoth;
     270    /** The plain unsigned view of the hardware bits. */
     271#if CPUMX86EFLAGS_HW_BITS == 32
     272    uint32_t        u;
     273#else
     274    uint32_t        u : CPUMX86EFLAGS_HW_BITS;
     275#endif
     276#ifndef VBOX_FOR_DTRACE_LIB
     277    /** The bitfield view. */
     278    X86EFLAGSBITS   Bits;
     279#endif
     280} CPUMX86EFLAGS;
     281/** Pointer to CPUM EFLAGS. */
     282typedef CPUMX86EFLAGS *PCPUMX86EFLAGS;
     283/** Pointer to const CPUM EFLAGS. */
     284typedef const CPUMX86EFLAGS *PCCPUMX86EFLAGS;
     285
     286/**
     287 * CPUM RFLAGS.
     288 *
     289 * This differs from X86EFLAGS in that we use could be using bits 63:22 for
     290 * internal purposes, see CPUMX86EFLAGS_HW_BITS.
     291 */
     292typedef union CPUMX86RFLAGS
     293{
     294    /** The full unsigned view, both hardware and VBox bits. */
     295    uint64_t        uBoth;
     296    /** The plain unsigned view of the hardware bits. */
     297#if CPUMX86EFLAGS_HW_BITS == 32
     298    uint32_t        u;
     299#else
     300    uint32_t        u : CPUMX86EFLAGS_HW_BITS;
     301#endif
     302#ifndef VBOX_FOR_DTRACE_LIB
     303    /** The bitfield view. */
     304    X86EFLAGSBITS   Bits;
     305#endif
     306} CPUMX86RFLAGS;
     307/** Pointer to CPUM RFLAGS. */
     308typedef CPUMX86RFLAGS *PCPUMX86RFLAGS;
     309/** Pointer to const CPUM RFLAGS. */
     310typedef const CPUMX86RFLAGS *PCCPUMX86RFLAGS;
    229311
    230312
     
    306388    union
    307389    {
    308         X86EFLAGS       eflags;
    309         X86RFLAGS       rflags;
     390        CPUMX86EFLAGS   eflags;
     391        CPUMX86RFLAGS   rflags;
    310392    } CPUM_UNION_NM(rflags);
    311393
     
    322404    uint64_t            cr3;
    323405    uint64_t            cr4;
    324     /** @todo Add the 4 PAE PDPE registers. See PGMCPU::aGstPaePdpeRegs. */
    325406    /** @} */
    326407
     
    351432    /** @name System MSRs.
    352433     * @{ */
    353     uint64_t            msrEFER;
     434    uint64_t            msrEFER; /**< @todo move EFER up to the crX registers for better cacheline mojo */
    354435    uint64_t            msrSTAR;            /**< Legacy syscall eip, cs & ss. */
    355436    uint64_t            msrPAT;             /**< Page attribute table. */
     
    570651AssertCompileMemberOffset(CPUMCTX,                                        tr, 0x0128);
    571652AssertCompileMemberOffset(CPUMCTX,                                       rip, 0x0140);
     653AssertCompileMemberOffset(CPUMCTX,                                    eflags, 0x0148);
    572654AssertCompileMemberOffset(CPUMCTX,                                    rflags, 0x0148);
    573655AssertCompileMemberOffset(CPUMCTX,                                  fInhibit, 0x0150);
  • trunk/include/iprt/x86.h

    r96977 r97231  
    231231/** Read as 1 bits. */
    232232#define X86_EFL_RA1_MASK    RT_BIT_32(1)
     233/** Read as 0 bits, excluding bits 31:22.
     234 * Bits 3, 5, 15, and 22 thru 31. */
     235#define X86_EFL_RAZ_MASK    UINT32_C(0xffc08028)
     236/** Read as 0 bits, excluding bits 31:22.
     237 * Bits 3, 5 and 15. */
     238#define X86_EFL_RAZ_LO_MASK UINT32_C(0x00008028)
    233239/** IOPL shift. */
    234240#define X86_EFL_IOPL_SHIFT  12
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r97220 r97231  
    184184{
    185185    return pVCpu->cpum.s.Hyper.dr[7];
     186}
     187
     188
     189/**
     190 * Checks that the special cookie stored in unused reserved RFLAGS bits
     191 *
     192 * @retval  true if cookie is ok.
     193 * @retval  false if cookie is not ok.
     194 * @param   pVM         The cross context VM structure.
     195 * @param   pVCpu       The cross context virtual CPU structure.
     196 */
     197VMM_INT_DECL(bool) CPUMAssertGuestRFlagsCookie(PVM pVM, PVMCPU pVCpu)
     198{
     199    AssertLogRelMsgReturn(      (pVCpu->cpum.s.Guest.rflags.uBoth & ~(uint64_t)(X86_EFL_LIVE_MASK | X86_EFL_RA1_MASK))
     200                             == pVM->cpum.s.fReservedRFlagsCookie
     201                          && (pVCpu->cpum.s.Guest.rflags.uBoth & X86_EFL_RA1_MASK) == X86_EFL_RA1_MASK,
     202                          ("rflags=%#RX64 vs fReservedRFlagsCookie=%#RX64\n",
     203                           pVCpu->cpum.s.Guest.rflags.uBoth, pVM->cpum.s.fReservedRFlagsCookie),
     204                          false);
     205    return true;
    186206}
    187207
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp

    r97208 r97231  
    80248024            || (pVCpu->cpum.GstCtx.ax & 0xf) >= 10)
    80258025        {
    8026             iemAImpl_add_u16(&pVCpu->cpum.GstCtx.ax, 0x106, &pVCpu->cpum.GstCtx.eflags.u32);
     8026            iemAImpl_add_u16(&pVCpu->cpum.GstCtx.ax, 0x106, &pVCpu->cpum.GstCtx.eflags.uBoth);
    80278027            pVCpu->cpum.GstCtx.eflags.Bits.u1AF = 1;
    80288028            pVCpu->cpum.GstCtx.eflags.Bits.u1CF = 1;
     
    80698069            || (pVCpu->cpum.GstCtx.ax & 0xf) >= 10)
    80708070        {
    8071             iemAImpl_sub_u16(&pVCpu->cpum.GstCtx.ax, 0x106, &pVCpu->cpum.GstCtx.eflags.u32);
     8071            iemAImpl_sub_u16(&pVCpu->cpum.GstCtx.ax, 0x106, &pVCpu->cpum.GstCtx.eflags.uBoth);
    80728072            pVCpu->cpum.GstCtx.eflags.Bits.u1AF = 1;
    80738073            pVCpu->cpum.GstCtx.eflags.Bits.u1CF = 1;
  • trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h

    r97223 r97231  
    18051805           Use 32-bit VMWRITE. */
    18061806        uint32_t fEFlags = pVCpu->cpum.GstCtx.eflags.u;
    1807         Assert(fEFlags & X86_EFL_RA1_MASK);
    1808         Assert(!(fEFlags & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
     1807        Assert((fEFlags & X86_EFL_RA1_MASK) == X86_EFL_RA1_MASK);
     1808        AssertMsg(!(fEFlags & ~(X86_EFL_LIVE_MASK | X86_EFL_RA1_MASK)), ("%#x\n", fEFlags));
    18091809
    18101810#ifndef IN_NEM_DARWIN
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r97219 r97231  
    145145#include <iprt/mem.h>
    146146#include <iprt/mp.h>
     147#include <iprt/rand.h>
    147148#include <iprt/string.h>
    148149
     
    22052206
    22062207    /*
     2208     * Generate the RFLAGS cookie.
     2209     */
     2210    pVM->cpum.s.fReservedRFlagsCookie = RTRandU64() & ~(CPUMX86EFLAGS_HW_MASK_64 | CPUMX86EFLAGS_INT_MASK_64);
     2211
     2212    /*
    22072213     * Init the VMX/SVM state.
    22082214     *
     
    22202226        Assert(pVM->apCpusR3[0]->cpum.s.Guest.hwvirt.enmHwvirt == CPUMHWVIRT_NONE);
    22212227
     2228    /*
     2229     * Initialize the general guest CPU state.
     2230     */
    22222231    CPUMR3Reset(pVM);
     2232
    22232233    return VINF_SUCCESS;
    22242234}
     
    23032313    pCtx->eip                       = 0x0000fff0;
    23042314    pCtx->edx                       = 0x00000600;   /* P6 processor */
    2305     pCtx->eflags.Bits.u1Reserved0   = 1;
     2315
     2316    Assert((pVM->cpum.s.fReservedRFlagsCookie & (X86_EFL_LIVE_MASK | X86_EFL_RAZ_LO_MASK | X86_EFL_RA1_MASK)) == 0);
     2317    pCtx->rflags.uBoth              = pVM->cpum.s.fReservedRFlagsCookie | X86_EFL_RA1_MASK;
    23062318
    23072319    pCtx->cs.Sel                    = 0xf000;
     
    24952507    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
    24962508    {
    2497         PVMCPU pVCpu = pVM->apCpusR3[idCpu];
    2498 
     2509        PVMCPU const   pVCpu   = pVM->apCpusR3[idCpu];
     2510        PCPUMCTX const pGstCtx = &pVCpu->cpum.s.Guest;
     2511
     2512        /** @todo ditch this the next time we change the saved state. */
    24992513        SSMR3PutStructEx(pSSM, &DummyHyperCtx,           sizeof(DummyHyperCtx),           0, g_aCpumCtxFields, NULL);
    25002514
    2501         PCPUMCTX pGstCtx = &pVCpu->cpum.s.Guest;
     2515        uint64_t const fSavedRFlags = pGstCtx->rflags.uBoth;
     2516        pGstCtx->rflags.uBoth &= CPUMX86EFLAGS_HW_MASK_64; /* Temporarily clear the non-hardware bits in RFLAGS while saving. */
    25022517        SSMR3PutStructEx(pSSM, pGstCtx,                  sizeof(*pGstCtx),                0, g_aCpumCtxFields, NULL);
     2518        pGstCtx->rflags.uBoth  = fSavedRFlags;
     2519
    25032520        SSMR3PutStructEx(pSSM, &pGstCtx->XState.x87,     sizeof(pGstCtx->XState.x87),     0, g_aCpumX87Fields, NULL);
    25042521        if (pGstCtx->fXStateMask != 0)
     
    29222939            AssertRCReturn(rc, rc);
    29232940
     2941            /* Deal with the reusing of reserved RFLAGS bits. */
     2942            pGstCtx->rflags.uBoth |= pVM->cpum.s.fReservedRFlagsCookie;
     2943
    29242944            /* REM and other may have cleared must-be-one fields in DR6 and
    29252945               DR7, fix these. */
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r97178 r97231  
    22102210                fFFDone = false;
    22112211
     2212#ifdef VBOX_STRICT
     2213            CPUMAssertGuestRFlagsCookie(pVM, pVCpu);
     2214#endif
     2215
    22122216            /*
    22132217             * Now what to do?
  • trunk/src/VBox/VMM/include/CPUMInternal.h

    r97213 r97231  
    382382    uint8_t                 abPadding1[1];
    383383
     384    /** Random value we store in the reserved RFLAGS bits we don't use ourselves so
     385     *  we can detect corruption. */
     386    uint64_t                fReservedRFlagsCookie;
     387
    384388    /** Align to 64-byte boundary. */
    385     uint8_t                 abPadding2[20+4];
     389    uint8_t                 abPadding2[16];
    386390
    387391    /** Host CPU feature information.
  • trunk/src/VBox/VMM/include/IEMMc.h

    r97153 r97231  
    334334#define IEM_MC_REF_GREG_I64(a_pi64Dst, a_iGReg)         (a_pi64Dst) = (int64_t *)iemGRegRefU64(pVCpu, (a_iGReg))
    335335#define IEM_MC_REF_GREG_I64_CONST(a_pi64Dst, a_iGReg)   (a_pi64Dst) = (int64_t const *)iemGRegRefU64(pVCpu, (a_iGReg))
    336 /** @note Not for IOPL or IF testing or modification. */
    337 #define IEM_MC_REF_EFLAGS(a_pEFlags)                    (a_pEFlags) = &pVCpu->cpum.GstCtx.eflags.u
     336/** @note Not for IOPL or IF testing or modification.
     337 * @note Must preserve any undefined bits, see CPUMX86EFLAGS! */
     338#define IEM_MC_REF_EFLAGS(a_pEFlags)                    (a_pEFlags) = &pVCpu->cpum.GstCtx.eflags.uBoth
    338339#define IEM_MC_REF_MXCSR(a_pfMxcsr)                     (a_pfMxcsr) = &pVCpu->cpum.GstCtx.XState.x87.MXCSR
    339340
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