VirtualBox

Changeset 102778 in vbox for trunk/src


Ignore:
Timestamp:
Jan 6, 2024 1:43:05 AM (16 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
160959
Message:

ValKit/bs3-cpu-weird-1: Added a PUSH/POP xSP testcase with operand size override variations. bugref:10371

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1-template.mac

    r98103 r102778  
    162162
    163163
     164;
     165; PUSH / POP.
     166;
     167
     168BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_xSP_Ud2, BS3_PBC_NEAR
     169        push    xSP
     170.ud2_again:
     171        ud2
     172        jmp     .ud2_again
     173AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_xSP_Ud2) == 1)
     174BS3_PROC_END_CMN   bs3CpuWeird1_Push_xSP_Ud2
     175
     176BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_xSP_Ud2, BS3_PBC_NEAR
     177        pop     xSP
     178.ud2_again:
     179        ud2
     180        jmp     .ud2_again
     181AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_xSP_Ud2) == 1)
     182BS3_PROC_END_CMN   bs3CpuWeird1_Pop_xSP_Ud2
     183
     184
     185BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_opsize_xSP_Ud2, BS3_PBC_NEAR
     186        db      066h
     187        push    xSP
     188.ud2_again:
     189        ud2
     190        jmp     .ud2_again
     191AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_opsize_xSP_Ud2) == 2)
     192BS3_PROC_END_CMN   bs3CpuWeird1_Push_opsize_xSP_Ud2
     193
     194BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_opsize_xSP_Ud2, BS3_PBC_NEAR
     195        db      066h
     196        pop     xSP
     197.ud2_again:
     198        ud2
     199        jmp     .ud2_again
     200AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_opsize_xSP_Ud2) == 2)
     201BS3_PROC_END_CMN   bs3CpuWeird1_Pop_opsize_xSP_Ud2
     202
     203
     204BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_opsize_xBX_Ud2, BS3_PBC_NEAR
     205        db      066h
     206        push    xBX
     207.ud2_again:
     208        ud2
     209        jmp     .ud2_again
     210AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_opsize_xBX_Ud2) == 2)
     211BS3_PROC_END_CMN   bs3CpuWeird1_Push_opsize_xBX_Ud2
     212
     213BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_opsize_xBX_Ud2, BS3_PBC_NEAR
     214        db      066h
     215        pop     xBX
     216.ud2_again:
     217        ud2
     218        jmp     .ud2_again
     219AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_opsize_xBX_Ud2) == 2)
     220BS3_PROC_END_CMN   bs3CpuWeird1_Pop_opsize_xBX_Ud2
     221
     222
    164223%endif ; BS3_INSTANTIATING_CMN
    165224
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1-x0.c

    r98103 r102778  
    10851085}
    10861086
     1087
     1088/*********************************************************************************************************************************
     1089*   PUSH / POP                                                                                                                   *
     1090*********************************************************************************************************************************/
     1091#define PROTO_ALL(a_Template) \
     1092    FNBS3FAR a_Template ## _c16, \
     1093             a_Template ## _c32, \
     1094             a_Template ## _c64
     1095PROTO_ALL(bs3CpuWeird1_Push_xSP_Ud2);
     1096PROTO_ALL(bs3CpuWeird1_Push_opsize_xSP_Ud2);
     1097PROTO_ALL(bs3CpuWeird1_Push_opsize_xBX_Ud2);
     1098PROTO_ALL(bs3CpuWeird1_Pop_xSP_Ud2);
     1099PROTO_ALL(bs3CpuWeird1_Pop_opsize_xSP_Ud2);
     1100PROTO_ALL(bs3CpuWeird1_Pop_opsize_xBX_Ud2);
     1101#undef PROTO_ALL
     1102
     1103
     1104/**
     1105 * Compares push/pop result.
     1106 */
     1107static uint8_t bs3CpuWeird1_ComparePushPop(PCBS3TRAPFRAME pTrapCtx, PCBS3TRAPFRAME pTrapExpect)
     1108{
     1109    uint16_t const cErrorsBefore = Bs3TestSubErrorCount();
     1110    CHECK_MEMBER("bXcpt",       "%#04x",    pTrapCtx->bXcpt,        pTrapExpect->bXcpt);
     1111    CHECK_MEMBER("bErrCd",      "%#06RX64", pTrapCtx->uErrCd,       pTrapExpect->uErrCd);
     1112    Bs3TestCheckRegCtxEx(&pTrapCtx->Ctx, &pTrapExpect->Ctx, 0 /*cbPcAdjust*/, 0 /*cbSpAdjust*/, 0 /*fExtraEfl*/,
     1113                         g_pszTestMode, g_usBs3TestStep);
     1114    if (Bs3TestSubErrorCount() != cErrorsBefore)
     1115    {
     1116        Bs3TrapPrintFrame(pTrapCtx);
     1117        Bs3TestPrintf("CS=%04RX16 SS:ESP=%04RX16:%08RX64 EFL=%RX64 cbIret=%#x\n",
     1118                      pTrapCtx->uHandlerCs, pTrapCtx->uHandlerSs, pTrapCtx->uHandlerRsp,
     1119                      pTrapCtx->fHandlerRfl, pTrapCtx->cbIretFrame);
     1120#if 0
     1121        Bs3TestPrintf("Halting in ComparePushPop: bXcpt=%#x\n", pTrapCtx->bXcpt);
     1122        ASMHalt();
     1123#endif
     1124        return 1;
     1125    }
     1126    return 0;
     1127}
     1128
     1129
     1130/** Initialize the stack around the CS:RSP with fixed values. */
     1131static void bs3CpuWeird1_PushPopInitStack(BS3PTRUNION PtrStack)
     1132{
     1133    PtrStack.pu16[-8] = UINT16_C(0x1e0f);
     1134    PtrStack.pu16[-7] = UINT16_C(0x3c2d);
     1135    PtrStack.pu16[-6] = UINT16_C(0x5a4b);
     1136    PtrStack.pu16[-5] = UINT16_C(0x7869);
     1137    PtrStack.pu16[-4] = UINT16_C(0x9687);
     1138    PtrStack.pu16[-3] = UINT16_C(0xb4a5);
     1139    PtrStack.pu16[-2] = UINT16_C(0xd2c3);
     1140    PtrStack.pu16[-1] = UINT16_C(0xf0e1);
     1141    PtrStack.pu16[0]  = UINT16_C(0xfdec);
     1142    PtrStack.pu16[1]  = UINT16_C(0xdbca);
     1143    PtrStack.pu16[2]  = UINT16_C(0xb9a8);
     1144    PtrStack.pu16[3]  = UINT16_C(0x9786);
     1145    PtrStack.pu16[4]  = UINT16_C(0x7564);
     1146    PtrStack.pu16[5]  = UINT16_C(0x5342);
     1147    PtrStack.pu16[6]  = UINT16_C(0x3120);
     1148}
     1149
     1150
     1151BS3_DECL_FAR(uint8_t) BS3_CMN_FAR_NM(bs3CpuWeird1_PushPop)(uint8_t bTestMode)
     1152{
     1153    static struct
     1154    {
     1155        FPFNBS3FAR  pfnStart;
     1156        uint8_t     cBits;
     1157        bool        fPush;      /**< true if push, false if pop. */
     1158        int8_t      cbAdjSp;    /**< The SP adjustment value. */
     1159        uint8_t     idxReg;     /**< The X86_GREG_xXX value of the register in question. */
     1160        uint8_t     offUd2;     /**< The UD2 offset into the code. */
     1161    } s_aTests[] =
     1162    {
     1163        { bs3CpuWeird1_Push_opsize_xBX_Ud2_c16, 16, true,  -4, X86_GREG_xBX, 2 },
     1164        { bs3CpuWeird1_Pop_opsize_xBX_Ud2_c16,  16, false, +4, X86_GREG_xBX, 2 },
     1165        { bs3CpuWeird1_Push_xSP_Ud2_c16,        16, true,  -2, X86_GREG_xSP, 1 },
     1166        { bs3CpuWeird1_Push_opsize_xSP_Ud2_c16, 16, true,  -4, X86_GREG_xSP, 2 },
     1167        { bs3CpuWeird1_Pop_xSP_Ud2_c16,         16, false, +2, X86_GREG_xSP, 1 },
     1168        { bs3CpuWeird1_Pop_opsize_xSP_Ud2_c16,  16, false, +4, X86_GREG_xSP, 2 },
     1169
     1170        { bs3CpuWeird1_Push_opsize_xBX_Ud2_c32, 32, true,  -2, X86_GREG_xBX, 2 },
     1171        { bs3CpuWeird1_Pop_opsize_xBX_Ud2_c32,  32, false, +2, X86_GREG_xBX, 2 },
     1172        { bs3CpuWeird1_Push_xSP_Ud2_c32,        32, true,  -4, X86_GREG_xSP, 1 },
     1173        { bs3CpuWeird1_Push_opsize_xSP_Ud2_c32, 32, true,  -2, X86_GREG_xSP, 2 },
     1174        { bs3CpuWeird1_Pop_xSP_Ud2_c32,         32, false, +4, X86_GREG_xSP, 1 },
     1175        { bs3CpuWeird1_Pop_opsize_xSP_Ud2_c32,  32, false, +2, X86_GREG_xSP, 2 },
     1176
     1177        { bs3CpuWeird1_Push_opsize_xBX_Ud2_c64, 64, true,  -2, X86_GREG_xBX, 2 },
     1178        { bs3CpuWeird1_Pop_opsize_xBX_Ud2_c64,  64, false, +2, X86_GREG_xBX, 2 },
     1179        { bs3CpuWeird1_Push_xSP_Ud2_c64,        64, true,  -8, X86_GREG_xSP, 1 },
     1180        { bs3CpuWeird1_Push_opsize_xSP_Ud2_c64, 64, true,  -2, X86_GREG_xSP, 2 },
     1181        { bs3CpuWeird1_Pop_xSP_Ud2_c64,         64, false, +8, X86_GREG_xSP, 1 },
     1182        { bs3CpuWeird1_Pop_opsize_xSP_Ud2_c64,  64, false, +2, X86_GREG_xSP, 2 },
     1183    };
     1184    BS3TRAPFRAME            TrapCtx;
     1185    BS3TRAPFRAME            TrapExpect;
     1186    BS3REGCTX               Ctx;
     1187    uint8_t const           cTestBits    = BS3_MODE_IS_16BIT_CODE(bTestMode) ? 16
     1188                                         : BS3_MODE_IS_32BIT_CODE(bTestMode) ? 32 : 64;
     1189    uint8_t BS3_FAR        *pbAltStack   = NULL;
     1190    BS3PTRUNION             PtrStack;
     1191    unsigned                i;
     1192
     1193    /* make sure they're allocated  */
     1194    Bs3MemZero(&Ctx, sizeof(Ctx));
     1195    Bs3MemZero(&TrapCtx, sizeof(TrapCtx));
     1196    Bs3MemZero(&TrapExpect, sizeof(TrapExpect));
     1197
     1198    bs3CpuWeird1_SetGlobals(bTestMode);
     1199
     1200    /* Construct a basic context. */
     1201    Bs3RegCtxSaveEx(&Ctx, bTestMode, 1024);
     1202    Ctx.rflags.u32 &= ~X86_EFL_RF;
     1203    if (BS3_MODE_IS_64BIT_CODE(bTestMode))
     1204    {
     1205        Ctx.rbx.au32[1] ^= UINT32_C(0x12305c78);
     1206        Ctx.rcx.au32[1] ^= UINT32_C(0x33447799);
     1207        Ctx.rax.au32[1] ^= UINT32_C(0x9983658a);
     1208        Ctx.r11.au32[1] ^= UINT32_C(0xbbeeffdd);
     1209        Ctx.r12.au32[1] ^= UINT32_C(0x87272728);
     1210    }
     1211
     1212    /* ring-3 if possible, since that'll enable automatic stack switching. */
     1213    if (!BS3_MODE_IS_RM_OR_V86(bTestMode))
     1214        Bs3RegCtxConvertToRingX(&Ctx, 3);
     1215
     1216    /* Make PtrStack == SS:xSP from Ctx. */
     1217    PtrStack.pv = Bs3RegCtxGetRspSsAsCurPtr(&Ctx);
     1218
     1219#if 1
     1220    /* Use our own stack so we can observe the effect of ESP/RSP rolling across
     1221       a 64KB boundrary when just popping SP. */
     1222    if (!BS3_MODE_IS_16BIT_CODE(bTestMode)) /** @todo extend this to 16-bit code as well (except RM ofc). */
     1223    {
     1224        uint32_t uFlatNextSeg;
     1225        pbAltStack = (uint8_t BS3_FAR *)Bs3SlabAllocEx(&g_Bs3Mem4KUpperTiled.Core, 17 /*cPages*/, 0 /*fFlags*/);
     1226        if (!pbAltStack)
     1227        {
     1228            Bs3TestFailed("Failed to allocate 68K for alternative stack!");
     1229            return 1;
     1230        }
     1231
     1232        /* Modify RSP to be one byte under the 64KB boundrary. */
     1233        uFlatNextSeg = (Bs3SelPtrToFlat(pbAltStack) + _64K) & ~UINT32_C(0xffff);
     1234        Ctx.rsp.u = uFlatNextSeg - 1;
     1235        //Bs3TestPrintf("uFlatNextSeg=%RX32 rsp=%RX64 ss=%RX16\n", uFlatNextSeg, Ctx.rsp.u, Ctx.ss);
     1236
     1237        /* Modify the PtrStack accordingly, using a spare selector for addressing it. */
     1238        Bs3SelSetup16BitData(&Bs3GdteSpare00, uFlatNextSeg - _4K);
     1239        PtrStack.pv = BS3_FP_MAKE(BS3_SEL_SPARE_00 | 3, _4K - 1);
     1240    }
     1241#endif
     1242
     1243    /*
     1244     * Iterate the test snippets and run those relevant to the test context.
     1245     */
     1246    for (i = 0; i < RT_ELEMENTS(s_aTests); i++)
     1247    {
     1248        if (s_aTests[i].cBits == cTestBits)
     1249        {
     1250            PBS3REG  const  pReg = &(&Ctx.rax)[s_aTests[i].idxReg];
     1251            unsigned        iRep;          /**< This is to trigger native recompilation. */
     1252            BS3REG          SavedReg;
     1253            BS3REG          SavedRsp;
     1254
     1255            /* Save context stuff we may change: */
     1256            SavedReg.u = pReg->u;
     1257            SavedRsp.u = Ctx.rsp.u;
     1258
     1259            /* Setup the test context. */
     1260            Bs3RegCtxSetRipCsFromLnkPtr(&Ctx, s_aTests[i].pfnStart);
     1261            if (BS3_MODE_IS_16BIT_SYS(bTestMode))
     1262                g_uBs3TrapEipHint = Ctx.rip.u32;
     1263
     1264            if (BS3_MODE_IS_16BIT_CODE(bTestMode))
     1265                Ctx.rsp.u32 |= UINT32_C(0x34560000); /* This part should be ignored, as the stack is also 16-bit. */
     1266
     1267            /* The basic expected trap context. */
     1268            TrapExpect.bXcpt  = X86_XCPT_UD;
     1269            Bs3MemCpy(&TrapExpect.Ctx, &Ctx, sizeof(TrapExpect.Ctx));
     1270            TrapExpect.Ctx.rsp.u += s_aTests[i].cbAdjSp;
     1271            TrapExpect.Ctx.rip.u += s_aTests[i].offUd2;
     1272            if (!BS3_MODE_IS_16BIT_SYS(bTestMode))
     1273                TrapExpect.Ctx.rflags.u32 |= X86_EFL_RF;
     1274
     1275            g_usBs3TestStep = i;
     1276
     1277            if (s_aTests[i].cbAdjSp < 0)
     1278            {
     1279                /*
     1280                 * PUSH
     1281                 */
     1282                RTUINT64U    u64ExpectPushed;
     1283                BS3PTRUNION  PtrStack2;
     1284                PtrStack2.pb = PtrStack.pb + s_aTests[i].cbAdjSp;
     1285
     1286                bs3CpuWeird1_PushPopInitStack(PtrStack);
     1287                u64ExpectPushed.u = *PtrStack2.pu64;
     1288                switch (s_aTests[i].cbAdjSp)
     1289                {
     1290                    case -2: u64ExpectPushed.au16[0] = pReg->au16[0]; break;
     1291                    case -4: u64ExpectPushed.au32[0] = pReg->au32[0]; break;
     1292                    case -8: u64ExpectPushed.au64[0] = pReg->u; break;
     1293                }
     1294
     1295                for (iRep = 0; iRep < 256; iRep++)
     1296                {
     1297                    bs3CpuWeird1_PushPopInitStack(PtrStack);
     1298                    Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
     1299                    if (bs3CpuWeird1_ComparePushPop(&TrapCtx, &TrapExpect))
     1300                        break;
     1301                    if (*PtrStack2.pu64 != u64ExpectPushed.u)
     1302                    {
     1303                        Bs3TestFailedF("%u - Unexpected stack value after push: %RX64, expected %RX64",
     1304                                       g_usBs3TestStep, *PtrStack2.pu64, u64ExpectPushed);
     1305                        break;
     1306                    }
     1307                }
     1308            }
     1309            else
     1310            {
     1311                /*
     1312                 * POP.
     1313                 *
     1314                 * This is where it gets interesting.  When popping a partial
     1315                 * SP and the upper part also changes, this is preserved. I.e.
     1316                 * the CPU first writes the updated RSP then the register or
     1317                 * register part that it popped.
     1318                 */
     1319                PBS3REG  const  pExpectReg = &(&TrapExpect.Ctx.rax)[s_aTests[i].idxReg];
     1320                RTUINT64U       u64PopValue;
     1321
     1322                bs3CpuWeird1_PushPopInitStack(PtrStack);
     1323                u64PopValue.u = *PtrStack.pu64;
     1324                if (bTestMode != BS3_MODE_RM)
     1325                {
     1326                    /* When in ring-3 we can put whatever we want on the stack, as the UD2 will cause a stack switch. */
     1327                    switch (s_aTests[i].cbAdjSp)
     1328                    {
     1329                        case 2: u64PopValue.au16[0] = ~pReg->au16[0] ^ UINT16_C(0xf394); break;
     1330                        case 4: u64PopValue.au32[0] = ~pReg->au32[0] ^ UINT32_C(0x9e501ab3); break;
     1331                        case 8: u64PopValue.au64[0] = ~pReg->u       ^ UINT64_C(0xbf5fedd520fe9a45); break;
     1332                    }
     1333                }
     1334                else
     1335                {
     1336                    /* In real mode we have to be a little more careful. */
     1337                    if (s_aTests[i].cbAdjSp == 2)
     1338                        u64PopValue.au16[0] = pReg->au16[0] - 382;
     1339                    else
     1340                    {
     1341                        u64PopValue.au16[0] = pReg->au16[0] - 258;
     1342                        u64PopValue.au16[1] = ~pReg->au16[1];
     1343                    }
     1344                }
     1345
     1346                switch (s_aTests[i].cbAdjSp)
     1347                {
     1348                    case 2:
     1349                        pExpectReg->au16[0] = u64PopValue.au16[0];
     1350                        break;
     1351                    case 4:
     1352                        pExpectReg->au32[0] = u64PopValue.au32[0];
     1353                        pExpectReg->au32[1] = 0;
     1354                        break;
     1355                    case 8:
     1356                        pExpectReg->u = u64PopValue.u;
     1357                        break;
     1358                }
     1359                //Bs3TestPrintf("iTest=%u/%d: %RX64 -> %RX64\n", i, s_aTests[i].cbAdjSp, pReg->u, pExpectReg->u);
     1360
     1361                for (iRep = 0; iRep < 256; iRep++)
     1362                {
     1363                    bs3CpuWeird1_PushPopInitStack(PtrStack);
     1364                    *PtrStack.pu64 = u64PopValue.u;
     1365                    Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
     1366                    if (bs3CpuWeird1_ComparePushPop(&TrapCtx, &TrapExpect))
     1367                        break;
     1368                }
     1369            }
     1370
     1371            /* Restore context (except cs:rsp): */
     1372            pReg->u   = SavedReg.u;
     1373            Ctx.rsp.u = SavedRsp.u;
     1374        }
     1375    }
     1376
     1377    if (pbAltStack)
     1378        Bs3SlabFree(&g_Bs3Mem4KUpperTiled.Core, Bs3SelPtrToFlat(pbAltStack), 17);
     1379
     1380    return 0;
     1381}
     1382
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1.c

    r98103 r102778  
    4848FNBS3TESTDOMODE bs3CpuWeird1_DbgInhibitRingXfer_f16;
    4949FNBS3TESTDOMODE bs3CpuWeird1_PcWrapping_f16;
     50FNBS3TESTDOMODE bs3CpuWeird1_PushPop_f16;
    5051
    5152
     
    5556static const BS3TESTMODEBYONEENTRY g_aModeByOneTests[] =
    5657{
     58#if 1 /** @todo fails in native recompiler atm. */ /** @todo asserts in ring-0 on VT-x! */
    5759    { "dbg+inhibit+ringxfer", bs3CpuWeird1_DbgInhibitRingXfer_f16, 0 },
     60#endif
     61#if 1 /** @todo asserts in native recompiler debug builds, but seems to work otherwise. */
    5862    { "pc wrapping", bs3CpuWeird1_PcWrapping_f16, 0 },
     63#endif
     64    { "push/pop", bs3CpuWeird1_PushPop_f16, 0 },
    5965};
    6066
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