VirtualBox

Changeset 92554 in vbox


Ignore:
Timestamp:
Nov 22, 2021 6:36:16 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
148435
Message:

ValKit/bs3-fpustate-1: More NEM/linux tweaks. bugref:9044

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-fpustate-1-template.c

    r92530 r92554  
    110110
    111111/**
     112 * Checks if we're seeing a problem with fnstenv saving zero selectors when
     113 * running on the compare area.
     114 *
     115 * This triggers in NEM mode if the native hypervisor doesn't do a good enough
     116 * job at save the FPU state for 16-bit and 32-bit guests.  We have heuristics
     117 * in CPUMInternal.mac (SAVE_32_OR_64_FPU) for this.
     118 *
     119 * @returns true if this the zero selector issue.
     120 * @param   pabReadback The MMIO read buffer containing the fnstenv result
     121 *                      typically produced by IEM.
     122 * @param   pabCompare  The buffer containing the fnstenv result typcially
     123 *                      produced by the CPU itself.
     124 */
     125static bool TMPL_NM(bs3FpuState1_IsZeroFnStEnvSelectorsProblem)(const uint8_t BS3_FAR *pabReadback,
     126                                                                const uint8_t BS3_FAR *pabCompare)
     127{
     128    unsigned const offCs = ARCH_BITS == 16 ?  8 : 16;
     129    unsigned const offDs = ARCH_BITS == 16 ? 12 : 24;
     130    if (   *(const uint16_t BS3_FAR *)&pabCompare[offCs] == 0
     131        && *(const uint16_t BS3_FAR *)&pabCompare[offDs] == 0)
     132    {
     133        /* Check the stuff before the CS register: */
     134        if (Bs3MemCmp(pabReadback, pabCompare, offCs) == 0)
     135        {
     136            /* Check the stuff between the DS and CS registers:*/
     137            if (Bs3MemCmp(&pabReadback[offCs + 2], &pabCompare[offCs + 2], offDs - offCs - 2) == 0)
     138            {
     139#if ARCH_BITS != 16
     140                /* Check the stuff after the DS register if 32-bit mode: */
     141                if (   *(const uint16_t BS3_FAR *)&pabReadback[offDs + 2]
     142                    == *(const uint16_t BS3_FAR *)&pabCompare[offDs + 2])
     143#endif
     144                    return true;
     145            }
     146        }
     147    }
     148    return false;
     149}
     150
     151
     152/**
    112153 * Tests for FPU state corruption.
    113154 *
     
    124165
    125166    uint8_t             abBuf[sizeof(X86FXSTATE)*2 + 32];
    126     uint8_t BS3_FAR    *pbTmp = &abBuf[0x10 - (((uintptr_t)abBuf) & 0x0f)];
    127     X86FXSTATE BS3_FAR *pExpected = (X86FXSTATE BS3_FAR *)pbTmp;
    128     X86FXSTATE BS3_FAR *pChecking = pExpected + 1;
     167    uint8_t BS3_FAR    *pbTmp                   = &abBuf[0x10 - (((uintptr_t)abBuf) & 0x0f)];
     168    X86FXSTATE BS3_FAR *pExpected               = (X86FXSTATE BS3_FAR *)pbTmp;
     169    X86FXSTATE BS3_FAR *pChecking               = pExpected + 1;
    129170    uint32_t            iLoop;
    130171    uint32_t            uStartTick;
    131172    bool                fMmioReadback;
    132     bool                fReadBackError = false;
    133     bool                fReadError = false;
     173    bool                fReadBackError          = false;
     174    bool                fReadError              = false;
     175    uint32_t            cFnStEnvSelectorsZero   = 0;
    134176    BS3PTRUNION         MmioReg;
    135     BS3CPUVENDOR const  enmCpuVendor = Bs3GetCpuVendor();
    136     bool const          fSkipStorIdt = Bs3TestQueryCfgBool(VMMDEV_TESTING_CFG_IS_NEM_LINUX);
    137     bool const          fFastFxSaveRestore = RT_BOOL(ASMCpuId_EDX(0x80000001) & X86_CPUID_AMD_FEATURE_EDX_FFXSR);
    138     //bool const          fFdpXcptOnly = (ASMCpuIdEx_EBX(7, 0) & X86_CPUID_STEXT_FEATURE_EBX_FDP_EXCPTN_ONLY)
    139     //                                && ASMCpuId_EAX(0) >= 7;
     177    BS3CPUVENDOR const  enmCpuVendor            = Bs3GetCpuVendor();
     178    bool const          fSkipStorIdt            = Bs3TestQueryCfgBool(VMMDEV_TESTING_CFG_IS_NEM_LINUX);
     179    bool const          fMayHaveZeroStEnvSels   = Bs3TestQueryCfgBool(VMMDEV_TESTING_CFG_IS_NEM_LINUX);
     180    bool const          fFastFxSaveRestore      = RT_BOOL(ASMCpuId_EDX(0x80000001) & X86_CPUID_AMD_FEATURE_EDX_FFXSR);
     181    //bool const          fFdpXcptOnly       = (ASMCpuIdEx_EBX(7, 0) & X86_CPUID_STEXT_FEATURE_EBX_FDP_EXCPTN_ONLY)
     182    //                                      && ASMCpuId_EAX(0) >= 7;
     183    RT_NOREF(bMode);
    140184
    141185    if (fSkipStorIdt)
     
    143187
    144188# undef  CHECK_STATE
    145 # define CHECK_STATE(a_Instr) \
     189# define CHECK_STATE(a_Instr, a_fIsFnStEnv) \
    146190        do { \
    147191            TMPL_NM(bs3FpuState1_Save)(pChecking); \
     
    202246    for (iLoop = 0; iLoop < _16M; iLoop++)
    203247    {
    204         CHECK_STATE(nop);
     248        CHECK_STATE(nop, false);
    205249        if (   (iLoop & 0xffff) == 0xffff
    206250            && g_cBs3PitTicks - uStartTick >= 20 * 20) /* 20 seconds*/
     
    224268        /* Macros  */
    225269# undef  CHECK_READBACK_WRITE_RUN
    226 # define CHECK_READBACK_WRITE_RUN(a_Instr, a_Worker, a_Type) \
     270# define CHECK_READBACK_WRITE_RUN(a_Instr, a_Worker, a_Type, a_fIsFnStEnv) \
    227271            do { \
    228272                off = (unsigned)(iLoop & (VMMDEV_TESTING_READBACK_SIZE / 2 - 1)); \
     
    234278                    a_Worker((a_Type *)&abCompare[0]); \
    235279                    Bs3MemCpy(abReadback, &MmioReg.pb[off], sizeof(a_Type)); \
    236                     if (Bs3MemCmp(abReadback, abCompare, sizeof(a_Type)) != 0) \
     280                    if (Bs3MemCmp(abReadback, abCompare, sizeof(a_Type)) == 0) \
     281                    { /* likely */ } \
     282                    else if (   (a_fIsFnStEnv) \
     283                             && fMayHaveZeroStEnvSels \
     284                             && TMPL_NM(bs3FpuState1_IsZeroFnStEnvSelectorsProblem)(abReadback, abCompare)) \
     285                        cFnStEnvSelectorsZero += 1; \
     286                    else \
    237287                    { \
    238288                        Bs3TestFailedF("Read back error for " #a_Instr " in loop #%RU32:\n%.*Rhxs expected:\n%.*Rhxs\n", \
     
    244294
    245295# undef  CHECK_READBACK_WRITE
    246 # define CHECK_READBACK_WRITE(a_Instr, a_Worker, a_Type) \
    247             CHECK_READBACK_WRITE_RUN(a_Instr, a_Worker, a_Type); \
    248             CHECK_STATE(a_Instr)
     296# define CHECK_READBACK_WRITE(a_Instr, a_Worker, a_Type, a_fIsFnStEnv) \
     297            CHECK_READBACK_WRITE_RUN(a_Instr, a_Worker, a_Type, a_fIsFnStEnv); \
     298            CHECK_STATE(a_Instr, a_fIsFnStEnv)
    249299# undef  CHECK_READBACK_WRITE_Z
    250 # define CHECK_READBACK_WRITE_Z(a_Instr, a_Worker, a_Type) \
     300# define CHECK_READBACK_WRITE_Z(a_Instr, a_Worker, a_Type, a_fIsFnStEnv) \
    251301            do { \
    252302                if (fMmioReadback && (!fReadBackError || iLoop == 0)) \
     
    258308                    Bs3MemZero(&MmioReg.pb[off], sizeof(a_Type)); \
    259309                } \
    260                 CHECK_READBACK_WRITE(a_Instr, a_Worker, a_Type); \
     310                CHECK_READBACK_WRITE(a_Instr, a_Worker, a_Type, a_fIsFnStEnv); \
    261311            } while (0)
    262312
     
    275325                Bs3MemSet(&abReadback[0], 0xcc, sizeof(abReadback)); \
    276326                CHECK_READBACK_READ_RUN(a_Instr, a_Worker, a_Type); \
    277                 CHECK_STATE(a_Instr); \
     327                CHECK_STATE(a_Instr, false); \
    278328                if (!fReadError || iLoop == 0) \
    279329                { \
     
    291341        /* The tests. */
    292342        if (!fSkipStorIdt) /* KVM doesn't advance RIP executing a SIDT [MMIO-memory], it seems. (Linux 5.13.1) */
    293             CHECK_READBACK_WRITE_Z(SIDT, ASMGetIDTR,                         RTIDTR);
    294         CHECK_READBACK_WRITE_Z(FNSTENV,  TMPL_NM(bs3FpuState1_FNStEnv),      X86FSTENV32P); /** @todo x86.h is missing types */
    295         CHECK_READBACK_WRITE(  MOVDQU,   TMPL_NM(bs3FpuState1_MovDQU_Write), X86XMMREG);
     343            CHECK_READBACK_WRITE_Z(SIDT, ASMGetIDTR,                         RTIDTR,       false);
     344        CHECK_READBACK_WRITE_Z(FNSTENV,  TMPL_NM(bs3FpuState1_FNStEnv),      X86FSTENV32P, true); /** @todo x86.h is missing types */
     345        CHECK_READBACK_WRITE(  MOVDQU,   TMPL_NM(bs3FpuState1_MovDQU_Write), X86XMMREG,    false);
    296346        CHECK_READBACK_READ(   MOVDQU,   TMPL_NM(bs3FpuState1_MovDQU_Read),  X86XMMREG);
    297         CHECK_READBACK_WRITE(  MOVUPS,   TMPL_NM(bs3FpuState1_MovUPS_Write), X86XMMREG);
     347        CHECK_READBACK_WRITE(  MOVUPS,   TMPL_NM(bs3FpuState1_MovUPS_Write), X86XMMREG,    false);
    298348        CHECK_READBACK_READ(   MOVUPS,   TMPL_NM(bs3FpuState1_MovUPS_Read),  X86XMMREG);
    299349
     
    321371        if (enmCpuVendor == BS3CPUVENDOR_AMD && fFastFxSaveRestore)
    322372            pExpected->FPUDP = 0; // Zen2 (3990x)
    323         CHECK_STATE(FMUL);
     373        CHECK_STATE(FMUL, false);
    324374
    325375        /* check for timeout every now an then. */
     
    330380
    331381    Bs3PitDisable();
     382
     383    /*
     384     * Warn if selectors are borked (for real VBox we'll fail and not warn).
     385     */
     386    if (cFnStEnvSelectorsZero > 0)
     387        Bs3TestPrintf("Warning! NEM borked the FPU selectors %u times.\n", cFnStEnvSelectorsZero);
    332388    return 0;
    333389}
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