VirtualBox

Ignore:
Timestamp:
Dec 2, 2016 12:30:33 PM (8 years ago)
Author:
vboxsync
Message:

bs3-cpu-basic-2: updates

Location:
trunk/src/VBox/ValidationKit/bootsectors
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-basic-2-pf.c32

    r64752 r64776  
    3030*********************************************************************************************************************************/
    3131#include <bs3kit.h>
     32#include <iprt/asm-amd64-x86.h>
     33
     34
     35/*********************************************************************************************************************************
     36*   Defined Constants And Macros                                                                                                 *
     37*********************************************************************************************************************************/
     38#define CHECK_MEMBER(a_pszMode, a_szName, a_szFmt, a_Actual, a_Expected) \
     39    do { \
     40        if ((a_Actual) == (a_Expected)) { /* likely */ } \
     41        else Bs3TestFailedF("%u - %s: " a_szName "=" a_szFmt " expected " a_szFmt, \
     42                            g_usBs3TestStep, (a_pszMode), (a_Actual), (a_Expected)); \
     43    } while (0)
    3244
    3345
     
    4355    uint8_t                     cbTmpl;
    4456} FNBS3CPUBASIC2PFTSTCODE;
     57typedef FNBS3CPUBASIC2PFTSTCODE const *PCFNBS3CPUBASIC2PFTSTCODE;
    4558
    4659typedef struct BS3CPUBASIC2PFTTSTCMNMODE
    4760{
    4861    uint8_t                 bMode;
    49     FNBS3CPUBASIC2PFTSTCODE ExecTmpl;
    5062    FNBS3CPUBASIC2PFTSTCODE MovLoad;
    5163    FNBS3CPUBASIC2PFTSTCODE MovStore;
     
    6072    /** The mode we're currently testing. */
    6173    uint8_t                     bMode;
     74    /** The size of a natural access. */
     75    uint8_t                     cbAccess;
    6276    /** The common mode functions. */
    6377    PCBS3CPUBASIC2PFTTSTCMNMODE pCmnMode;
     
    8094    /** Trap context frame. */
    8195    BS3TRAPFRAME                TrapCtx;
     96    /** Expected result context. */
     97    BS3REGCTX                   ExpectCtx;
    8298
    8399} BS3CPUBASIC2PFSTATE;
     
    98114
    99115/* bs3-cpu-basic-2-template.mac: */
    100 FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_RaisePF_ExecTmpl_c16;
    101116FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ax_ds_bx__ud2_c16;
    102117FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ds_bx_ax__ud2_c16;
     
    104119FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_cmpxchg_ds_bx_cx__ud2_c16;
    105120
    106 FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_RaisePF_ExecTmpl_c32;
    107121FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ax_ds_bx__ud2_c32;
    108122FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ds_bx_ax__ud2_c32;
     
    110124FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_cmpxchg_ds_bx_cx__ud2_c32;
    111125
    112 FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_RaisePF_ExecTmpl_c64;
    113126FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ax_ds_bx__ud2_c64;
    114127FNBS3CPUBASIC2PFSNIPPET bs3CpuBasic2_mov_ds_bx_ax__ud2_c64;
     
    137150    {
    138151        BS3_MODE_CODE_16,
    139         {   bs3CpuBasic2_RaisePF_ExecTmpl_c16,      0, 3 },
    140152        {   bs3CpuBasic2_mov_ax_ds_bx__ud2_c16,     2 },
    141153        {   bs3CpuBasic2_mov_ds_bx_ax__ud2_c16,     2 },
     
    145157    {
    146158        BS3_MODE_CODE_32,
    147         {   bs3CpuBasic2_RaisePF_ExecTmpl_c32,      0, 3  },
    148159        {   bs3CpuBasic2_mov_ax_ds_bx__ud2_c32,     2 },
    149160        {   bs3CpuBasic2_mov_ds_bx_ax__ud2_c32,     2 },
     
    153164    {
    154165        BS3_MODE_CODE_64,
    155         {   bs3CpuBasic2_RaisePF_ExecTmpl_c64,      0, 3  },
    156166        {   bs3CpuBasic2_mov_ax_ds_bx__ud2_c64,     2 + 1 },
    157167        {   bs3CpuBasic2_mov_ds_bx_ax__ud2_c64,     2 + 1 },
     
    161171    {
    162172        BS3_MODE_CODE_V86,
    163         {   bs3CpuBasic2_RaisePF_ExecTmpl_c16,      0, 3  },
    164173        {   bs3CpuBasic2_mov_ax_ds_bx__ud2_c16,     2 },
    165174        {   bs3CpuBasic2_mov_ds_bx_ax__ud2_c16,     2 },
     
    170179
    171180
    172 static void bs3CpuBasic2Pf_DoExecSubTest(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t uXcpt, uint8_t uPfErrCd,
    173                                          unsigned iRing)
     181/**
     182 * Compares a CPU trap.
     183 */
     184static void bs3CpuBasic2Pf_CompareCtx(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pExpectCtx, int cbPcAdjust,
     185                                      uint8_t bXcpt, unsigned uErrCd)
     186{
     187    const char     *pszHint = "xxxx";
     188    uint16_t const  cErrorsBefore = Bs3TestSubErrorCount();
     189    uint32_t        fExtraEfl;
     190
     191    CHECK_MEMBER(pszHint, "bXcpt",   "%#04x",    pThis->TrapCtx.bXcpt,             bXcpt);
     192    CHECK_MEMBER(pszHint, "uErrCd",  "%#06RX16", (uint16_t)pThis->TrapCtx.uErrCd, (uint16_t)uErrCd); /* 486 only writes a word */
     193
     194    fExtraEfl = X86_EFL_RF;
     195    if (BS3_MODE_IS_16BIT_SYS(g_bBs3CurrentMode))
     196        fExtraEfl = 0;
     197    else
     198        fExtraEfl = X86_EFL_RF;
     199    Bs3TestCheckRegCtxEx(&pThis->TrapCtx.Ctx, pExpectCtx, cbPcAdjust, 0 /*cbSpAdjust*/, fExtraEfl, pszHint, g_usBs3TestStep);
     200    if (Bs3TestSubErrorCount() != cErrorsBefore)
     201    {
     202        Bs3TrapPrintFrame(&pThis->TrapCtx);
     203#if 1
     204        Bs3TestPrintf("Halting: g_uBs3CpuDetected=%#x\n", g_uBs3CpuDetected);
     205        Bs3TestPrintf("Halting: bXcpt=%#x uErrCd=%#x\n", bXcpt, uErrCd);
     206        ASMHalt();
     207#endif
     208    }
     209}
     210
     211
     212/**
     213 * Compares a CPU trap.
     214 */
     215static void bs3CpuBasic2Pf_CompareSimpleCtx(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pStartCtx, int offAddPC,
     216                                            uint8_t bXcpt, unsigned uErrCd, uint64_t uCr2)
     217{
     218    const char     *pszHint = "xxxx";
     219    uint16_t const  cErrorsBefore = Bs3TestSubErrorCount();
     220    uint64_t const  uSavedCr2 = pStartCtx->cr2.u;
     221    uint32_t        fExtraEfl;
     222
     223    CHECK_MEMBER(pszHint, "bXcpt",   "%#04x",    pThis->TrapCtx.bXcpt,             bXcpt);
     224    CHECK_MEMBER(pszHint, "uErrCd",  "%#06RX16", (uint16_t)pThis->TrapCtx.uErrCd, (uint16_t)uErrCd); /* 486 only writes a word */
     225
     226    fExtraEfl = X86_EFL_RF;
     227    if (BS3_MODE_IS_16BIT_SYS(g_bBs3CurrentMode))
     228        fExtraEfl = 0;
     229    else
     230        fExtraEfl = X86_EFL_RF;
     231    pStartCtx->cr2.u = uCr2;
     232    Bs3TestCheckRegCtxEx(&pThis->TrapCtx.Ctx, pStartCtx, offAddPC, 0 /*cbSpAdjust*/, fExtraEfl, pszHint, g_usBs3TestStep);
     233    pStartCtx->cr2.u = uSavedCr2;
     234    if (Bs3TestSubErrorCount() != cErrorsBefore)
     235    {
     236        Bs3TrapPrintFrame(&pThis->TrapCtx);
     237#if 1
     238        Bs3TestPrintf("Halting: g_uBs3CpuDetected=%#x\n", g_uBs3CpuDetected);
     239        Bs3TestPrintf("Halting: bXcpt=%#x uErrCd=%#x\n", bXcpt, uErrCd);
     240        ASMHalt();
     241#endif
     242    }
     243}
     244
     245
     246/**
     247 * Checks the trap context for a simple \#PF trap.
     248 */
     249static void bs3CpuBasic2Pf_CompareSimplePf(PBS3CPUBASIC2PFSTATE pThis, PCBS3REGCTX pStartCtx, int offAddPC,
     250                                           unsigned uErrCd, uint64_t uCr2)
     251{
     252    bs3CpuBasic2Pf_CompareSimpleCtx(pThis, (PBS3REGCTX)pStartCtx, offAddPC, X86_XCPT_PF, uErrCd, uCr2);
     253}
     254
     255/**
     256 * Checks the trap context for a simple \#UD trap.
     257 */
     258static void bs3CpuBasic2Pf_CompareSimpleUd(PBS3CPUBASIC2PFSTATE pThis, PCBS3REGCTX pStartCtx, int offAddPC)
     259{
     260    bs3CpuBasic2Pf_CompareSimpleCtx(pThis, (PBS3REGCTX)pStartCtx, offAddPC, X86_XCPT_UD, 0, pStartCtx->cr2.u);
     261}
     262
     263
     264static void bs3CpuBasic2Pf_DoExec(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t bXcpt, uint8_t uPfErrCd, bool fPageLevel)
    174265{
    175266    uint8_t *pbOrgTest = pThis->pbOrgTest;
    176267    unsigned off;
    177     for (off = X86_PAGE_SIZE - 2; off < X86_PAGE_SIZE + 2; off++)
    178     {
     268
     269    for (off = X86_PAGE_SIZE - 4; off < X86_PAGE_SIZE + 2; off++)
     270    {
     271        /* Emit a little bit of code (using the original allocation mapping) and point pCtx to it. */
    179272        pbOrgTest[off + 0] = X86_OP_PRF_SIZE_ADDR;
    180273        pbOrgTest[off + 1] = X86_OP_PRF_SIZE_OP;
     
    190283                break;
    191284            case BS3_MODE_CODE_16:
    192                 Bs3SelSetup16BitCode(&Bs3GdteSpare01, (uintptr_t)pThis->pbTest, iRing);
     285                Bs3SelSetup16BitCode(&Bs3GdteSpare01, (uintptr_t)pThis->pbTest, pCtx->bCpl);
    193286                pCtx->rip.u = off;
    194                 pCtx->cs    = BS3_SEL_SPARE_01;
     287                pCtx->cs    = BS3_SEL_SPARE_01 | pCtx->bCpl;
    195288                break;
    196289            case BS3_MODE_CODE_V86:
     
    198291                return;
    199292        }
     293        //Bs3TestPrintf("cs:rip=%04x:%010RX64 iRing=%d\n", pCtx->cs, pCtx->rip.u, pCtx->bCpl);
    200294
    201295        Bs3TrapSetJmpAndRestore(pCtx, &pThis->TrapCtx);
    202         //bs3CpuBasic2_CompareUdCtx(&TrapCtx, &CtxUdExpected);
    203 
    204     }
     296        //Bs3TestPrintf("off=%#06x bXcpt=%#x uErrCd=%#RX64\n", off, pThis->TrapCtx.bXcpt, pThis->TrapCtx.uErrCd);
     297        if (bXcpt == X86_XCPT_PF)
     298        {
     299            unsigned offAddPC = !fPageLevel || off >= X86_PAGE_SIZE ? 0 : X86_PAGE_SIZE - off;
     300            bs3CpuBasic2Pf_CompareSimplePf(pThis, pCtx, offAddPC, uPfErrCd, (uintptr_t)pThis->pbTest + offAddPC);
     301        }
     302        else
     303            bs3CpuBasic2Pf_CompareSimpleUd(pThis, pCtx, 3);
     304
     305    }
     306}
     307
     308
     309static void bs3CpuBasic2Pf_SetCsEip(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, PCFNBS3CPUBASIC2PFTSTCODE pCode)
     310{
     311    switch (pThis->bMode & BS3_MODE_CODE_MASK)
     312    {
     313        default:
     314            pCtx->rip.u = (uintptr_t)pCode->pfn;
     315            break;
     316
     317        case BS3_MODE_CODE_16:
     318        {
     319            uint32_t uFar16 = Bs3SelFlatCodeToProtFar16((uintptr_t)pCode->pfn);
     320            pCtx->rip.u = (uint16_t)uFar16;
     321            pCtx->cs    = (uint16_t)(uFar16 >> 16) | pCtx->bCpl;
     322            pCtx->cs   += (uint16_t)pCtx->bCpl << BS3_SEL_RING_SHIFT;
     323            break;
     324        }
     325
     326        case BS3_MODE_CODE_V86:
     327        {
     328            uint32_t uFar16 = Bs3SelFlatCodeToRealMode((uintptr_t)pCode->pfn);
     329            pCtx->rip.u = (uint16_t)uFar16;
     330            pCtx->cs    = (uint16_t)(uFar16 >> 16);
     331            break;
     332        }
     333    }
     334}
     335
     336
     337/**
     338 * Test a simple load instruction around the edges of page two.
     339 *
     340 * @param   pThis           The test stat data.
     341 * @param   pCtx            The test context.
     342 * @param   bXcpt           X86_XCPT_PF if this can cause \#PFs, otherwise
     343 *                          X86_XCPT_UD.
     344 * @param   uPfErrCd        The error code for \#PFs.
     345 * @param   fPageLevel      Set if we're pushing PTE level bits.
     346 */
     347static void bs3CpuBasic2Pf_DoMovLoad(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t bXcpt, uint8_t uPfErrCd,
     348                                     bool fPageLevel)
     349{
     350    static uint64_t const s_uValue = UINT64_C(0x7c4d0114428d);
     351    uint64_t uExpectRax;
     352    unsigned i;
     353
     354    /*
     355     * Adjust the incoming context and calculate our expections.
     356     */
     357    bs3CpuBasic2Pf_SetCsEip(pThis, pCtx, &pThis->pCmnMode->MovLoad);
     358    Bs3MemCpy(&pThis->ExpectCtx, pCtx, sizeof(pThis->ExpectCtx));
     359    switch (pThis->bMode & BS3_MODE_CODE_MASK)
     360    {
     361        case BS3_MODE_CODE_16:
     362        case BS3_MODE_CODE_V86:
     363            uExpectRax = (uint16_t)s_uValue | (pCtx->rax.u & UINT64_C(0xffffffffffff0000));
     364            break;
     365        case BS3_MODE_CODE_32:
     366            uExpectRax = (uint32_t)s_uValue | (pCtx->rax.u & UINT64_C(0xffffffff00000000));
     367            break;
     368        case BS3_MODE_CODE_64:
     369            uExpectRax = s_uValue;
     370            break;
     371    }
     372    if (uExpectRax == pCtx->rax.u)
     373        pCtx->rax.u = ~pCtx->rax.u;
     374
     375    /*
     376     * Make two approaches to the test page (the 2nd one):
     377     *  - i=0: Start on the 1st page and edge into the 2nd.
     378     *  - i=1: Start at the end of the 2nd page and edge off it and into the 3rd.
     379     */
     380    for (i = 0; i < 2; i++)
     381    {
     382        unsigned off    = X86_PAGE_SIZE * (i + 1) - pThis->cbAccess;
     383        unsigned offEnd = X86_PAGE_SIZE * (i + 1) + (i == 0 ? 8 : 7);
     384        for (; off < offEnd; off++)
     385        {
     386            *(uint64_t *)&pThis->pbOrgTest[off] = s_uValue;
     387            if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
     388                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = off;
     389            else
     390                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = (uintptr_t)pThis->pbTest + off;
     391
     392            Bs3TrapSetJmpAndRestore(pCtx, &pThis->TrapCtx);
     393            //Bs3TestPrintf("off=%#06x bXcpt=%#x uErrCd=%#RX64\n", off, pThis->TrapCtx.bXcpt, pThis->TrapCtx.uErrCd);
     394
     395            if (   bXcpt != X86_XCPT_PF
     396                || (fPageLevel && off >= X86_PAGE_SIZE * 2)
     397                || (fPageLevel && off <= X86_PAGE_SIZE - pThis->cbAccess) )
     398            {
     399                pThis->ExpectCtx.rax.u = uExpectRax;
     400                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, pThis->pCmnMode->MovLoad.offUd2, bXcpt, 0 /*uErrCd*/);
     401                pThis->ExpectCtx.rax = pCtx->rax;
     402            }
     403            else
     404            {
     405                if (off < X86_PAGE_SIZE)
     406                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + X86_PAGE_SIZE;
     407                else
     408                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + off;
     409                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, 0 /*cbPcAdjust*/, bXcpt, uPfErrCd);
     410                pThis->ExpectCtx.cr2 = pCtx->cr2;
     411            }
     412        }
     413    }
     414}
     415
     416
     417/**
     418 * Test a simple store instruction around the edges of page two.
     419 *
     420 * @param   pThis           The test stat data.
     421 * @param   pCtx            The test context.
     422 * @param   bXcpt           X86_XCPT_PF if this can cause \#PFs, otherwise
     423 *                          X86_XCPT_UD.
     424 * @param   uPfErrCd        The error code for \#PFs.
     425 * @param   fPageLevel      Set if we're pushing PTE level bits.
     426 */
     427static void bs3CpuBasic2Pf_DoMovStore(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t bXcpt, uint8_t uPfErrCd,
     428                                      bool fPageLevel)
     429{
     430    static uint64_t const s_uValue        = UINT64_C(0x3af45ead86a34a26);
     431    static uint64_t const s_uValueFlipped = UINT64_C(0xc50ba152795cb5d9);
     432    uint64_t const uRaxSaved = pCtx->rax.u;
     433    uint64_t uExpectStored;
     434    unsigned i;
     435
     436    /*
     437     * Adjust the incoming context and calculate our expections.
     438     */
     439    bs3CpuBasic2Pf_SetCsEip(pThis, pCtx, &pThis->pCmnMode->MovStore);
     440    if ((pThis->bMode & BS3_MODE_CODE_MASK) != BS3_MODE_CODE_64)
     441        pCtx->rax.u = (uint32_t)s_uValue; /* leave the upper part zero */
     442    else
     443        pCtx->rax.u = s_uValue;
     444
     445    Bs3MemCpy(&pThis->ExpectCtx, pCtx, sizeof(pThis->ExpectCtx));
     446    switch (pThis->bMode & BS3_MODE_CODE_MASK)
     447    {
     448        case BS3_MODE_CODE_16:
     449        case BS3_MODE_CODE_V86:
     450            uExpectStored = (uint16_t)s_uValue | (s_uValueFlipped & UINT64_C(0xffffffffffff0000));
     451            break;
     452        case BS3_MODE_CODE_32:
     453            uExpectStored = (uint32_t)s_uValue | (s_uValueFlipped & UINT64_C(0xffffffff00000000));
     454            break;
     455        case BS3_MODE_CODE_64:
     456            uExpectStored = s_uValue;
     457            break;
     458    }
     459
     460    /*
     461     * Make two approaches to the test page (the 2nd one):
     462     *  - i=0: Start on the 1st page and edge into the 2nd.
     463     *  - i=1: Start at the end of the 2nd page and edge off it and into the 3rd.
     464     */
     465    for (i = 0; i < 2; i++)
     466    {
     467        unsigned off    = X86_PAGE_SIZE * (i + 1) - pThis->cbAccess;
     468        unsigned offEnd = X86_PAGE_SIZE * (i + 1) + (i == 0 ? 8 : 7);
     469        for (; off < offEnd; off++)
     470        {
     471            *(uint64_t *)&pThis->pbOrgTest[off] = s_uValueFlipped;
     472            if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
     473                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = off;
     474            else
     475                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = (uintptr_t)pThis->pbTest + off;
     476
     477            Bs3TrapSetJmpAndRestore(pCtx, &pThis->TrapCtx);
     478            //Bs3TestPrintf("off=%#06x bXcpt=%#x uErrCd=%#RX64\n", off, pThis->TrapCtx.bXcpt, pThis->TrapCtx.uErrCd);
     479
     480            if (   bXcpt != X86_XCPT_PF
     481                || (fPageLevel && off >= X86_PAGE_SIZE * 2)
     482                || (fPageLevel && off <= X86_PAGE_SIZE - pThis->cbAccess) )
     483            {
     484                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, pThis->pCmnMode->MovStore.offUd2, bXcpt, 0 /*uErrCd*/);
     485                if (*(uint64_t *)&pThis->pbOrgTest[off] != uExpectStored)
     486                    Bs3TestFailedF("%u - %s: Stored %#RX64, expected %#RX64",
     487                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], uExpectStored);
     488            }
     489            else
     490            {
     491                if (off < X86_PAGE_SIZE)
     492                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + X86_PAGE_SIZE;
     493                else
     494                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + off;
     495                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, 0 /*cbPcAdjust*/, bXcpt, uPfErrCd);
     496                pThis->ExpectCtx.cr2 = pCtx->cr2;
     497                if (*(uint64_t *)&pThis->pbOrgTest[off] != s_uValueFlipped)
     498                    Bs3TestFailedF("%u - %s: #PF'ed store modified memory: %#RX64, expected %#RX64",
     499                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], s_uValueFlipped);
     500
     501            }
     502        }
     503    }
     504
     505    pCtx->rax.u = uRaxSaved;
     506}
     507
     508
     509/**
     510 * Test a xchg instruction around the edges of page two.
     511 *
     512 * @param   pThis           The test stat data.
     513 * @param   pCtx            The test context.
     514 * @param   bXcpt           X86_XCPT_PF if this can cause \#PFs, otherwise
     515 *                          X86_XCPT_UD.
     516 * @param   uPfErrCd        The error code for \#PFs.
     517 * @param   fPageLevel      Set if we're pushing PTE level bits.
     518 */
     519static void bs3CpuBasic2Pf_DoXchg(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t bXcpt, uint8_t uPfErrCd, bool fPageLevel)
     520{
     521    static uint64_t const s_uValue        = UINT64_C(0xea58699648e2f32c);
     522    static uint64_t const s_uValueFlipped = UINT64_C(0x15a79669b71d0cd3);
     523    uint64_t const uRaxSaved = pCtx->rax.u;
     524    uint64_t uRaxIn;
     525    uint64_t uExpectedRax;
     526    uint64_t uExpectStored;
     527    unsigned i;
     528
     529    /*
     530     * Adjust the incoming context and calculate our expections.
     531     */
     532    bs3CpuBasic2Pf_SetCsEip(pThis, pCtx, &pThis->pCmnMode->Xchg);
     533    if ((pThis->bMode & BS3_MODE_CODE_MASK) != BS3_MODE_CODE_64)
     534        uRaxIn = (uint32_t)s_uValue; /* leave the upper part zero */
     535    else
     536        uRaxIn = s_uValue;
     537
     538    Bs3MemCpy(&pThis->ExpectCtx, pCtx, sizeof(pThis->ExpectCtx));
     539    switch (pThis->bMode & BS3_MODE_CODE_MASK)
     540    {
     541        case BS3_MODE_CODE_16:
     542        case BS3_MODE_CODE_V86:
     543            uExpectedRax  = (uint16_t)s_uValueFlipped | (uRaxIn          & UINT64_C(0xffffffffffff0000));
     544            uExpectStored = (uint16_t)s_uValue        | (s_uValueFlipped & UINT64_C(0xffffffffffff0000));
     545            break;
     546        case BS3_MODE_CODE_32:
     547            uExpectedRax  = (uint32_t)s_uValueFlipped | (uRaxIn          & UINT64_C(0xffffffff00000000));
     548            uExpectStored = (uint32_t)s_uValue        | (s_uValueFlipped & UINT64_C(0xffffffff00000000));
     549            break;
     550        case BS3_MODE_CODE_64:
     551            uExpectedRax  = s_uValueFlipped;
     552            uExpectStored = s_uValue;
     553            break;
     554    }
     555
     556    /*
     557     * Make two approaches to the test page (the 2nd one):
     558     *  - i=0: Start on the 1st page and edge into the 2nd.
     559     *  - i=1: Start at the end of the 2nd page and edge off it and into the 3rd.
     560     */
     561    for (i = 0; i < 2; i++)
     562    {
     563        unsigned off    = X86_PAGE_SIZE * (i + 1) - pThis->cbAccess;
     564        unsigned offEnd = X86_PAGE_SIZE * (i + 1) + (i == 0 ? 8 : 7);
     565        for (; off < offEnd; off++)
     566        {
     567            *(uint64_t *)&pThis->pbOrgTest[off] = s_uValueFlipped;
     568            pCtx->rax.u = uRaxIn;
     569            if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
     570                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = off;
     571            else
     572                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = (uintptr_t)pThis->pbTest + off;
     573
     574            Bs3TrapSetJmpAndRestore(pCtx, &pThis->TrapCtx);
     575            //Bs3TestPrintf("off=%#06x bXcpt=%#x uErrCd=%#RX64\n", off, pThis->TrapCtx.bXcpt, pThis->TrapCtx.uErrCd);
     576
     577            if (   bXcpt != X86_XCPT_PF
     578                || (fPageLevel && off >= X86_PAGE_SIZE * 2)
     579                || (fPageLevel && off <= X86_PAGE_SIZE - pThis->cbAccess) )
     580            {
     581                pThis->ExpectCtx.rax.u = uExpectedRax;
     582                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, pThis->pCmnMode->Xchg.offUd2, bXcpt, 0 /*uErrCd*/);
     583                if (*(uint64_t *)&pThis->pbOrgTest[off] != uExpectStored)
     584                    Bs3TestFailedF("%u - %s: Stored %#RX64, expected %#RX64",
     585                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], uExpectStored);
     586            }
     587            else
     588            {
     589                pThis->ExpectCtx.rax.u = uRaxIn;
     590                if (off < X86_PAGE_SIZE)
     591                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + X86_PAGE_SIZE;
     592                else
     593                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + off;
     594                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, 0 /*cbPcAdjust*/, bXcpt, uPfErrCd);
     595                pThis->ExpectCtx.cr2 = pCtx->cr2;
     596                if (*(uint64_t *)&pThis->pbOrgTest[off] != s_uValueFlipped)
     597                    Bs3TestFailedF("%u - %s: #PF'ed store modified memory: %#RX64, expected %#RX64",
     598                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], s_uValueFlipped);
     599            }
     600        }
     601    }
     602
     603    pCtx->rax.u = uRaxSaved;
     604}
     605
     606
     607/**
     608 * Test a cmpxchg instruction around the edges of page two.
     609 *
     610 * @param   pThis           The test stat data.
     611 * @param   pCtx            The test context.
     612 * @param   bXcpt           X86_XCPT_PF if this can cause \#PFs, otherwise
     613 *                          X86_XCPT_UD.
     614 * @param   uPfErrCd        The error code for \#PFs.
     615 * @param   fPageLevel      Set if we're pushing PTE level bits.
     616 * @param   fMissmatch      Whether to fail and not store (@c true), or succeed
     617 *                          and do the store.
     618 */
     619static void bs3CpuBasic2Pf_DoCmpXchg(PBS3CPUBASIC2PFSTATE pThis, PBS3REGCTX pCtx, uint8_t bXcpt, uint8_t uPfErrCd,
     620                                     bool fPageLevel, bool fMissmatch)
     621{
     622    static uint64_t const s_uValue        = UINT64_C(0xea58699648e2f32c);
     623    static uint64_t const s_uValueFlipped = UINT64_C(0x15a79669b71d0cd3);
     624    static uint64_t const s_uValueOther   = UINT64_C(0x2171239bcb044c81);
     625    uint64_t const uRaxSaved = pCtx->rax.u;
     626    uint64_t const uRcxSaved = pCtx->rcx.u;
     627    uint64_t uRaxIn;
     628    uint64_t uExpectedRax;
     629    uint32_t uExpectedFlags;
     630    uint64_t uExpectStored;
     631    unsigned i;
     632
     633    /*
     634     * Adjust the incoming context and calculate our expections.
     635     * Hint: CMPXCHG  [xBX],xCX     ; xAX compare and update implicit, ZF set to !fMissmatch.
     636     */
     637    bs3CpuBasic2Pf_SetCsEip(pThis, pCtx, &pThis->pCmnMode->CmpXchg);
     638    if ((pThis->bMode & BS3_MODE_CODE_MASK) != BS3_MODE_CODE_64)
     639    {
     640        uRaxIn      = (uint32_t)(fMissmatch ? s_uValueOther : s_uValueFlipped); /* leave the upper part zero */
     641        pCtx->rcx.u = (uint32_t)s_uValue;                                        /* ditto */
     642    }
     643    else
     644    {
     645        uRaxIn      = fMissmatch ? s_uValueOther : s_uValueFlipped;
     646        pCtx->rcx.u = s_uValue;
     647    }
     648    if (fMissmatch)
     649        pCtx->rflags.u32 |= X86_EFL_ZF;
     650    else
     651        pCtx->rflags.u32 &= ~X86_EFL_ZF;
     652
     653    Bs3MemCpy(&pThis->ExpectCtx, pCtx, sizeof(pThis->ExpectCtx));
     654    uExpectedFlags = pCtx->rflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_SF | X86_EFL_OF | X86_EFL_ZF);
     655    switch (pThis->bMode & BS3_MODE_CODE_MASK)
     656    {
     657        case BS3_MODE_CODE_16:
     658        case BS3_MODE_CODE_V86:
     659            uExpectedRax  = (uint16_t)s_uValueFlipped | (uRaxIn          & UINT64_C(0xffffffffffff0000));
     660            uExpectStored = (uint16_t)s_uValue        | (s_uValueFlipped & UINT64_C(0xffffffffffff0000));
     661            uExpectedFlags |= !fMissmatch ? X86_EFL_ZF | X86_EFL_PF : X86_EFL_AF;
     662            break;
     663        case BS3_MODE_CODE_32:
     664            uExpectedRax  = (uint32_t)s_uValueFlipped | (uRaxIn          & UINT64_C(0xffffffff00000000));
     665            uExpectStored = (uint32_t)s_uValue        | (s_uValueFlipped & UINT64_C(0xffffffff00000000));
     666            uExpectedFlags |= !fMissmatch ? X86_EFL_ZF | X86_EFL_PF : X86_EFL_AF;
     667            break;
     668        case BS3_MODE_CODE_64:
     669            uExpectedRax  = s_uValueFlipped;
     670            uExpectStored = s_uValue;
     671            uExpectedFlags |= !fMissmatch ? X86_EFL_ZF | X86_EFL_PF : X86_EFL_AF;
     672            break;
     673    }
     674    if (fMissmatch)
     675        uExpectStored = s_uValueFlipped;
     676
     677    /*
     678     * Make two approaches to the test page (the 2nd one):
     679     *  - i=0: Start on the 1st page and edge into the 2nd.
     680     *  - i=1: Start at the end of the 2nd page and edge off it and into the 3rd.
     681     */
     682    for (i = 0; i < 2; i++)
     683    {
     684        unsigned off    = X86_PAGE_SIZE * (i + 1) - pThis->cbAccess;
     685        unsigned offEnd = X86_PAGE_SIZE * (i + 1) + (i == 0 ? 8 : 7);
     686        for (; off < offEnd; off++)
     687        {
     688            *(uint64_t *)&pThis->pbOrgTest[off] = s_uValueFlipped;
     689            pCtx->rax.u = uRaxIn;
     690            if (BS3_MODE_IS_16BIT_CODE(pThis->bMode))
     691                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = off;
     692            else
     693                pThis->ExpectCtx.rbx.u = pCtx->rbx.u = (uintptr_t)pThis->pbTest + off;
     694
     695            Bs3TrapSetJmpAndRestore(pCtx, &pThis->TrapCtx);
     696            //Bs3TestPrintf("off=%#06x bXcpt=%#x uErrCd=%#RX64\n", off, pThis->TrapCtx.bXcpt, pThis->TrapCtx.uErrCd);
     697
     698            if (   bXcpt != X86_XCPT_PF
     699                || (fPageLevel && off >= X86_PAGE_SIZE * 2)
     700                || (fPageLevel && off <= X86_PAGE_SIZE - pThis->cbAccess) )
     701            {
     702                pThis->ExpectCtx.rax.u = uExpectedRax;
     703                pThis->ExpectCtx.rflags.u32 = uExpectedFlags;
     704                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, pThis->pCmnMode->CmpXchg.offUd2, bXcpt, 0 /*uErrCd*/);
     705                if (*(uint64_t *)&pThis->pbOrgTest[off] != uExpectStored)
     706                    Bs3TestFailedF("%u - %s: Stored %#RX64, expected %#RX64",
     707                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], uExpectStored);
     708            }
     709            else
     710            {
     711                pThis->ExpectCtx.rax.u = uRaxIn;
     712                pThis->ExpectCtx.rflags = pCtx->rflags;
     713                if (off < X86_PAGE_SIZE)
     714                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + X86_PAGE_SIZE;
     715                else
     716                    pThis->ExpectCtx.cr2.u = (uintptr_t)pThis->pbTest + off;
     717                bs3CpuBasic2Pf_CompareCtx(pThis, &pThis->ExpectCtx, 0 /*cbPcAdjust*/, bXcpt, uPfErrCd);
     718                pThis->ExpectCtx.cr2 = pCtx->cr2;
     719                if (*(uint64_t *)&pThis->pbOrgTest[off] != s_uValueFlipped)
     720                    Bs3TestFailedF("%u - %s: #PF'ed store modified memory: %#RX64, expected %#RX64",
     721                                   g_usBs3TestStep, "xxxx", *(uint64_t *)&pThis->pbOrgTest[off], s_uValueFlipped);
     722            }
     723        }
     724    }
     725
     726    pCtx->rax.u = uRaxSaved;
     727    pCtx->rcx.u = uRcxSaved;
    205728}
    206729
     
    219742    BS3REGCTX           aCtxts[4];
    220743
     744    /** @todo figure out V8086 testing. */
     745    if ((pThis->bMode & BS3_MODE_CODE_MASK) == BS3_MODE_CODE_V86)
     746        return BS3TESTDOMODE_SKIPPED;
     747
     748
    221749    /* paranoia: Touch the various big stack structures to ensure the compiler has allocated stack for them. */
    222750    for (iRing = 0; iRing < RT_ELEMENTS(aCtxts); iRing++)
     
    247775    }
    248776
    249 
    250     /*
    251      * Check basic operation.
     777    /*
     778     * Check basic operation:
    252779     */
    253780    for (iRing = 0; iRing < 4; iRing++)
    254781    {
    255         /* we can execute the test page. */
    256         bs3CpuBasic2Pf_DoExecSubTest(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, iRing);
    257     }
    258 
    259 
     782        /* 1. we can execute the test page. */
     783        bs3CpuBasic2Pf_DoExec(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/);
     784        /* 2. we can read from the test page. */
     785        bs3CpuBasic2Pf_DoMovLoad(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/);
     786        /* 3. we can write to the test page. */
     787        bs3CpuBasic2Pf_DoMovStore(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/);
     788        /* 4. we can do locked read+write (a few variants). */
     789        bs3CpuBasic2Pf_DoXchg(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/);
     790        bs3CpuBasic2Pf_DoCmpXchg(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/, false /*fMissmatch*/);
     791        bs3CpuBasic2Pf_DoCmpXchg(pThis, &aCtxts[iRing], X86_XCPT_UD, UINT8_MAX, true /*fPageLevel*/, true  /*fMissmatch*/);
     792    }
     793
     794    /*
     795     * Check the U bit on PTE level.
     796     */
    260797
    261798
     
    277814    Bs3MemZero(&State, sizeof(State));
    278815    State.bMode = bMode;
     816    switch (bMode & BS3_MODE_CODE_MASK)
     817    {
     818        case BS3_MODE_CODE_16:  State.cbAccess = sizeof(uint16_t); break;
     819        case BS3_MODE_CODE_V86: State.cbAccess = sizeof(uint16_t); break;
     820        case BS3_MODE_CODE_32:  State.cbAccess = sizeof(uint32_t); break;
     821        case BS3_MODE_CODE_64:  State.cbAccess = sizeof(uint64_t); break;
     822    }
    279823    State.pCmnMode = &g_aCmnModes[0];
    280824    while (State.pCmnMode->bMode != (bMode & BS3_MODE_CODE_MASK))
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-basic-2-template.mac

    r64752 r64776  
    321321;
    322322
    323 ; For testing exec access.
    324 BS3_PROC_BEGIN_CMN bs3CpuBasic2_RaisePF_ExecTmpl, BS3_PBC_NEAR
    325 .again: ud2
    326         jmp     .again
    327 BS3_PROC_END_CMN   bs3CpuBasic2_RaisePF_ExecTmpl
    328 
    329 
    330323; For testing read access.
    331324BS3_PROC_BEGIN_CMN bs3CpuBasic2_mov_ax_ds_bx__ud2, BS3_PBC_NEAR
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-basic-2.c

    r64704 r64776  
    7777     */
    7878    NOREF(g_aModeTest); NOREF(g_aModeByOneTests); /* for when commenting out bits */
     79#if 0
    7980    Bs3TestDoModes_rm(g_aModeTest, RT_ELEMENTS(g_aModeTest));
    8081    Bs3TestDoModesByOne_rm(g_aModeByOneTests, RT_ELEMENTS(g_aModeByOneTests), 0);
     82#endif
    8183
    8284    /*
     
    8688
    8789    Bs3TestTerm();
    88 for (;;) { ASMHalt(); }
     90//for (;;) { ASMHalt(); }
    8991}
    9092
  • trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-PagingQueryAddressInfo.c

    r64734 r64776  
    7070                if (!pPgInfo->u.Pae.pPml4e->n.u1Present)
    7171                    rc = VERR_PAGE_NOT_PRESENT;
    72                 else if (pPgInfo->u.Pae.pPml4e->u <= uMaxAddr)
     72                else if ((pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK) <= uMaxAddr)
    7373                {
    74                     pPgInfo->u.Pae.pPdpe  = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPml4e->u & X86_PAGE_BASE_MASK);
     74                    pPgInfo->u.Pae.pPdpe  = (X86PDPE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPml4e->u & X86_PML4E_PG_MASK);
    7575                    pPgInfo->u.Pae.pPdpe += (uFlat >> X86_PDPT_SHIFT) & X86_PDPT_MASK_AMD64;
    7676                    if (!pPgInfo->u.Pae.pPdpe->n.u1Present)
     
    9696            /* Common code for the PD and PT levels. */
    9797            if (   rc == VINF_TRY_AGAIN
    98                 && pPgInfo->u.Pae.pPdpe->u <= uMaxAddr)
     98                && (pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK) <= uMaxAddr)
    9999            {
    100100                rc = VERR_OUT_OF_RANGE;
    101                 pPgInfo->u.Pae.pPde  = (X86PDEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPdpe->u & X86_PAGE_BASE_MASK);
     101                pPgInfo->u.Pae.pPde  = (X86PDEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPdpe->u & X86_PDPE_PG_MASK);
    102102                pPgInfo->u.Pae.pPde += (uFlat >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
    103103                if (!pPgInfo->u.Pae.pPde->n.u1Present)
     
    105105                else if (pPgInfo->u.Pae.pPde->b.u1Size)
    106106                    rc = VINF_SUCCESS;
    107                 else if (pPgInfo->u.Pae.pPde->u <= uMaxAddr)
     107                else if ((pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK) <= uMaxAddr)
    108108                {
    109                     pPgInfo->u.Pae.pPte  = (X86PTEPAE BS3_FAR *)Bs3XptrFlatToCurrent(  pPgInfo->u.Pae.pPde->u
    110                                                                                      & X86_PAGE_BASE_MASK);
     109                    pPgInfo->u.Pae.pPte = (X86PTEPAE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Pae.pPde->u & X86_PDE_PAE_PG_MASK);
     110                    rc = VINF_SUCCESS;
    111111                }
    112112            }
     
    136136            else if (pPgInfo->u.Legacy.pPde->u <= uMaxAddr)
    137137            {
    138                 pPgInfo->u.Legacy.pPte  = (X86PTE BS3_FAR *)Bs3XptrFlatToCurrent(  pPgInfo->u.Legacy.pPde->u
    139                                                                                  & X86_PAGE_BASE_MASK_32);
     138                pPgInfo->u.Legacy.pPte  = (X86PTE BS3_FAR *)Bs3XptrFlatToCurrent(pPgInfo->u.Legacy.pPde->u & X86_PDE_PG_MASK);
    140139                pPgInfo->u.Legacy.pPte += ((uint32_t)uFlat >> X86_PT_SHIFT) & X86_PT_MASK;
    141140                if (pPgInfo->u.Legacy.pPte->n.u1Present)
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