VirtualBox

Changeset 102779 in vbox for trunk


Ignore:
Timestamp:
Jan 7, 2024 1:02:16 AM (13 months ago)
Author:
vboxsync
Message:

ValKit/bs3-cpu-weird-1: Added a PUSH/POP FS testcase with operand size override variations. Weird stuff. 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

    r102778 r102779  
    221221
    222222
     223;
     224; PUSH / POP SREG.
     225;
     226
     227BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_fs_Ud2, BS3_PBC_NEAR
     228        push    fs
     229.ud2_again:
     230        ud2
     231        jmp     .ud2_again
     232AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_fs_Ud2) == 2)
     233BS3_PROC_END_CMN   bs3CpuWeird1_Push_fs_Ud2
     234
     235
     236BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_fs_Ud2, BS3_PBC_NEAR
     237        pop     fs
     238.ud2_again:
     239        ud2
     240        jmp     .ud2_again
     241AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_fs_Ud2) == 2)
     242BS3_PROC_END_CMN   bs3CpuWeird1_Pop_fs_Ud2
     243
     244
     245BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_opsize_fs_Ud2, BS3_PBC_NEAR
     246        db      066h
     247        push    fs
     248.ud2_again:
     249        ud2
     250        jmp     .ud2_again
     251AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_opsize_fs_Ud2) == 3)
     252BS3_PROC_END_CMN   bs3CpuWeird1_Push_opsize_fs_Ud2
     253
     254
     255BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_opsize_fs_Ud2, BS3_PBC_NEAR
     256        db      066h
     257        pop     fs
     258.ud2_again:
     259        ud2
     260        jmp     .ud2_again
     261AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_opsize_fs_Ud2) == 3)
     262BS3_PROC_END_CMN   bs3CpuWeird1_Pop_opsize_fs_Ud2
     263
     264
    223265%endif ; BS3_INSTANTIATING_CMN
    224266
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1-x0.c

    r102778 r102779  
    10121012             * For 64-bit we have to alias the two buffer pages to the first and
    10131013             * last page in the address space. To test that the 32-bit 4G rollover
    1014              * isn't incorrectly applied to LM64, we repeat this mappingfor the 4G
    1015              * and 8G boundaries too.
     1014             * isn't incorrectly applied to LM64, we repeat this mapping for the
     1015             * 4G  and 8G boundaries too.
    10161016             *
    10171017             * This ASSUMES there is nothing important in page 0 when in LM64.
     
    13811381}
    13821382
     1383
     1384
     1385/*********************************************************************************************************************************
     1386*   PUSH SREG / POP SREG                                                                                                         *
     1387*********************************************************************************************************************************/
     1388#define PROTO_ALL(a_Template) \
     1389    FNBS3FAR a_Template ## _c16, \
     1390             a_Template ## _c32, \
     1391             a_Template ## _c64
     1392PROTO_ALL(bs3CpuWeird1_Push_fs_Ud2);
     1393PROTO_ALL(bs3CpuWeird1_Pop_fs_Ud2);
     1394PROTO_ALL(bs3CpuWeird1_Push_opsize_fs_Ud2);
     1395PROTO_ALL(bs3CpuWeird1_Pop_opsize_fs_Ud2);
     1396#undef PROTO_ALL
     1397
     1398
     1399BS3_DECL_FAR(uint8_t) BS3_CMN_FAR_NM(bs3CpuWeird1_PushPopSReg)(uint8_t bTestMode)
     1400{
     1401    static struct
     1402    {
     1403        FPFNBS3FAR  pfnStart;
     1404        uint8_t     cBits;
     1405        bool        fPush;      /**< true if push, false if pop. */
     1406        int8_t      cbAdjSp;    /**< The SP adjustment value. */
     1407        uint8_t     offReg;     /**< The offset of the register in BS3REGCTX. */
     1408        uint8_t     offUd2;     /**< The UD2 offset into the code. */
     1409    } s_aTests[] =
     1410    {
     1411        { bs3CpuWeird1_Push_fs_Ud2_c16,         16, true,  -2, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1412        { bs3CpuWeird1_Pop_fs_Ud2_c16,          16, false, +2, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1413        { bs3CpuWeird1_Push_opsize_fs_Ud2_c16,  16, true,  -4, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1414        { bs3CpuWeird1_Pop_opsize_fs_Ud2_c16,   16, false, +4, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1415
     1416        { bs3CpuWeird1_Push_fs_Ud2_c32,         32, true,  -4, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1417        { bs3CpuWeird1_Pop_fs_Ud2_c32,          32, false, +4, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1418        { bs3CpuWeird1_Push_opsize_fs_Ud2_c32,  32, true,  -2, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1419        { bs3CpuWeird1_Pop_opsize_fs_Ud2_c32,   32, false, +2, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1420
     1421        { bs3CpuWeird1_Push_fs_Ud2_c64,         64, true,  -8, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1422        { bs3CpuWeird1_Pop_fs_Ud2_c64,          64, false, +8, RT_UOFFSETOF(BS3REGCTX, fs), 2 },
     1423        { bs3CpuWeird1_Push_opsize_fs_Ud2_c64,  64, true,  -2, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1424        { bs3CpuWeird1_Pop_opsize_fs_Ud2_c64,   64, false, +2, RT_UOFFSETOF(BS3REGCTX, fs), 3 },
     1425    };
     1426    BS3TRAPFRAME            TrapCtx;
     1427    BS3TRAPFRAME            TrapExpect;
     1428    BS3REGCTX               Ctx;
     1429    uint16_t const          uInitialSel  = bTestMode != BS3_MODE_RM ? BS3_SEL_R3_DS16 : 0x8080;
     1430    uint16_t const          uPopSel      = BS3_SEL_R3_SS16;
     1431    bool const              fFullWrite   = BS3_MODE_IS_64BIT_CODE(bTestMode);   /* 64-bit mode writes are full (10980XE). */
     1432    bool const              fFullRead    = false; /* But, 64-bit mode reads are word sized (10980XE). */
     1433    bool const              fInRmWrHiEfl = true; /* 10890XE writes EFLAGS[31:16] in the high word of a 'o32 PUSH FS'. */
     1434    uint8_t const           cTestBits    = BS3_MODE_IS_16BIT_CODE(bTestMode) ? 16
     1435                                         : BS3_MODE_IS_32BIT_CODE(bTestMode) ? 32 : 64;
     1436    unsigned const          cbAltStack   = 2 * X86_PAGE_SIZE;
     1437    uint8_t BS3_FAR        *pbAltStack   = NULL;
     1438    uint32_t                uFlatAltStack;
     1439    uint32_t                uFlatAltStackAlias;
     1440    BS3PTRUNION             PtrStack;
     1441    unsigned                iVariation;
     1442
     1443    /* make sure they're allocated  */
     1444    Bs3MemZero(&Ctx, sizeof(Ctx));
     1445    Bs3MemZero(&TrapCtx, sizeof(TrapCtx));
     1446    Bs3MemZero(&TrapExpect, sizeof(TrapExpect));
     1447
     1448    bs3CpuWeird1_SetGlobals(bTestMode);
     1449
     1450    /* Construct a basic context. */
     1451    Bs3RegCtxSaveEx(&Ctx, bTestMode, 1024);
     1452    Ctx.rflags.u32 &= ~X86_EFL_RF;
     1453    if (g_uBs3CpuDetected & BS3CPU_F_CPUID)
     1454        Ctx.rflags.u32 |= X86_EFL_ID; /* Make sure it's set as it bleeds in in real-mode on my intel 10890XE. */
     1455
     1456    if (BS3_MODE_IS_64BIT_CODE(bTestMode))
     1457    {
     1458        Ctx.rbx.au32[1] ^= UINT32_C(0x12305c78);
     1459        Ctx.rcx.au32[1] ^= UINT32_C(0x33447799);
     1460        Ctx.rax.au32[1] ^= UINT32_C(0x9983658a);
     1461        Ctx.r11.au32[1] ^= UINT32_C(0xbbeeffdd);
     1462        Ctx.r12.au32[1] ^= UINT32_C(0x87272728);
     1463    }
     1464
     1465    /* ring-3 if possible, since that'll enable automatic stack switching. */
     1466    if (!BS3_MODE_IS_RM_OR_V86(bTestMode))
     1467        Bs3RegCtxConvertToRingX(&Ctx, 3);
     1468
     1469    /* Make PtrStack == SS:xSP from Ctx. */
     1470    PtrStack.pv = Bs3RegCtxGetRspSsAsCurPtr(&Ctx);
     1471
     1472    /* Use our own stack so we can analyze the PUSH/POP FS behaviour using
     1473       both the SS limit (except 64-bit code) and paging (when enabled).
     1474       Two pages suffices here, but we allocate two more for aliasing the
     1475       first to onto. */
     1476    if (!BS3_MODE_IS_RM_OR_V86(bTestMode)) /** @todo test V86 mode w/ paging */
     1477    {
     1478        pbAltStack = (uint8_t BS3_FAR *)Bs3MemAlloc(BS3MEMKIND_TILED, cbAltStack * 2);
     1479        if (!pbAltStack)
     1480            return !Bs3TestFailed("Failed to allocate 2*2 pages for an alternative stack!");
     1481        uFlatAltStack = Bs3SelPtrToFlat(pbAltStack);
     1482        if (uFlatAltStack & X86_PAGE_OFFSET_MASK)
     1483            return !Bs3TestFailedF("Misaligned allocation: %p / %RX32!", pbAltStack, uFlatAltStack);
     1484    }
     1485
     1486    /*
     1487     * The outer loop does setup variations:
     1488     *      - 0: Standard push and pop w/o off default stack w/o any restrictions.
     1489     *      - 1: Apply segment limit as tightly as possible w/o #SS.
     1490     *      - 2: Apply the segment limit too tight and field #SS.
     1491     *      - 3: Put the segment number right next to a page that's not present.
     1492     *           No segment trickery.
     1493     *      - 4: Make the segment number word straddle a page boundrary where
     1494     *           the 2nd page is not present.
     1495     */
     1496    for (iVariation = 0; iVariation <= 4; iVariation++)
     1497    {
     1498        uint16_t const uSavedSs   = Ctx.ss;
     1499        uint64_t const uSavedRsp  = Ctx.rsp.u;
     1500        uint32_t       uNominalEsp;
     1501        unsigned iTest;
     1502
     1503        /* Skip variation if not supported by the test mode. */
     1504        if (iVariation >= 1 && BS3_MODE_IS_RM_OR_V86(bTestMode)) /** @todo test V86 mode w/ paging */
     1505            break;
     1506
     1507        if ((iVariation == 1 || iVariation == 2) && BS3_MODE_IS_64BIT_CODE(bTestMode))
     1508            continue;
     1509        if ((iVariation == 3 || iVariation == 4) && !BS3_MODE_IS_PAGED(bTestMode))
     1510            continue;
     1511
     1512        uFlatAltStackAlias = uFlatAltStack;
     1513        if (iVariation != 0)
     1514        {
     1515            /* Alias the two stack pages for variation #3 and #4 so we can keep
     1516               accessing them via pbAltStack while testing. */
     1517            if (iVariation == 3 || iVariation == 4)
     1518            {
     1519                int rc = Bs3PagingAlias(uFlatAltStackAlias = uFlatAltStack + X86_PAGE_SIZE * 2, uFlatAltStack, X86_PAGE_SIZE,
     1520                                        X86_PTE_P | X86_PTE_RW | X86_PTE_A | X86_PTE_D | X86_PTE_US);
     1521                if (RT_SUCCESS(rc))
     1522                {
     1523                    rc = Bs3PagingAlias(uFlatAltStackAlias + X86_PAGE_SIZE, uFlatAltStack + X86_PAGE_SIZE, X86_PAGE_SIZE, 0);
     1524                    if (RT_FAILURE(rc))
     1525                    {
     1526                        Bs3TestFailedF("Alias of 2nd stack page failed: %d", rc);
     1527                        Bs3PagingUnalias(uFlatAltStackAlias, X86_PAGE_SIZE);
     1528                    }
     1529                }
     1530                else
     1531                    Bs3TestFailedF("Alias of 2nd stack page failed: %d", rc);
     1532                if (RT_FAILURE(rc))
     1533                    break;
     1534            }
     1535
     1536            if (iVariation == 1 || iVariation == 2 || BS3_MODE_IS_16BIT_CODE(bTestMode))
     1537            {
     1538                /* Setup a 16-bit stack with two pages and ESP pointing at the last
     1539                   word in the first page.  The SS limit is at 4KB for variation #1
     1540                   (shouldn't fault unless the CPU does full dword writes), one byte
     1541                   lower for variation #2 (must always fault), and max limit for
     1542                   variations #3 and #4. */
     1543                Bs3SelSetup16BitData(&Bs3GdteSpare00, uFlatAltStackAlias);
     1544                if (iVariation <= 2)
     1545                {
     1546                    Bs3GdteSpare00.Gen.u16LimitLow = _4K - 1;
     1547                    if (iVariation == 2)
     1548                        Bs3GdteSpare00.Gen.u16LimitLow -= 1;
     1549                    Bs3GdteSpare00.Gen.u4LimitHigh = 0;
     1550                }
     1551                Ctx.ss     = BS3_SEL_SPARE_00 | 3;
     1552                Ctx.rsp.u  = _4K - sizeof(uint16_t);
     1553            }
     1554            else
     1555            {
     1556                /* Setup flat stack similar to above for variation #3 and #4. */
     1557                Ctx.rsp.u = uFlatAltStackAlias + _4K - sizeof(uint16_t);
     1558            }
     1559
     1560            /* Update the stack pointer to match the new ESP. */
     1561            PtrStack.pv = &pbAltStack[_4K - sizeof(uint16_t)];
     1562
     1563            /* For variation #4 we move the stack position up by one byte so we'll
     1564               always cross the page boundrary and hit the non-existing page. */
     1565            if (iVariation == 4)
     1566            {
     1567                Ctx.rsp.u   += 1;
     1568                PtrStack.pb += 1;
     1569            }
     1570        }
     1571        uNominalEsp = Ctx.rsp.u32;
     1572
     1573        for (iTest = 0; iTest < RT_ELEMENTS(s_aTests); iTest++)
     1574        {
     1575            if (s_aTests[iTest].cBits == cTestBits)
     1576            {
     1577                uint16_t BS3_FAR   *pRegCtx    = (uint16_t BS3_FAR *)((uint8_t BS3_FAR *)&Ctx            + s_aTests[iTest].offReg);
     1578                uint16_t BS3_FAR   *pRegExpect = (uint16_t BS3_FAR *)((uint8_t BS3_FAR *)&TrapExpect.Ctx + s_aTests[iTest].offReg);
     1579                uint16_t const      uSavedSel  = *pRegCtx;
     1580                uint8_t const       cbItem     = RT_ABS(s_aTests[iTest].cbAdjSp);
     1581                unsigned            iRep;          /**< This is to trigger native recompilation. */
     1582                BS3PTRUNION         PtrStack2;
     1583
     1584                *pRegCtx = uInitialSel;
     1585
     1586                /* Calculate the stack read/write location for this test. PtrStack
     1587                   ASSUMES word writes, so we have to adjust it and RSP if the CPU
     1588                   does full read+writes. */
     1589                PtrStack2.pv = PtrStack.pv;
     1590                if (cbItem != 2 && (s_aTests[iTest].cbAdjSp < 0 ? fFullWrite : fFullRead))
     1591                {
     1592                    PtrStack2.pb -= cbItem - 2;
     1593                    Ctx.rsp.u32  -= cbItem - 2;
     1594                }
     1595
     1596                /* Setup the test context. */
     1597                Bs3RegCtxSetRipCsFromLnkPtr(&Ctx, s_aTests[iTest].pfnStart);
     1598                if (BS3_MODE_IS_16BIT_SYS(bTestMode))
     1599                    g_uBs3TrapEipHint = Ctx.rip.u32;
     1600
     1601                /* Use the same access location for both PUSH and POP instructions (PtrStack). */
     1602                if (s_aTests[iTest].cbAdjSp < 0)
     1603                    Ctx.rsp.u16 += -s_aTests[iTest].cbAdjSp;
     1604
     1605                /* The basic expected trap context. */
     1606                TrapExpect.bXcpt  = iVariation == 2 ? X86_XCPT_SS : iVariation == 4 ? X86_XCPT_PF : X86_XCPT_UD;
     1607                TrapExpect.uErrCd = 0;
     1608                Bs3MemCpy(&TrapExpect.Ctx, &Ctx, sizeof(TrapExpect.Ctx));
     1609                if (TrapExpect.bXcpt == X86_XCPT_UD)
     1610                {
     1611                    TrapExpect.Ctx.rsp.u += s_aTests[iTest].cbAdjSp;
     1612                    TrapExpect.Ctx.rip.u += s_aTests[iTest].offUd2;
     1613                }
     1614                else if (iVariation == 4)
     1615                {
     1616                    TrapExpect.uErrCd    = s_aTests[iTest].cbAdjSp < 0 ? X86_TRAP_PF_RW | X86_TRAP_PF_US : X86_TRAP_PF_US;
     1617                    TrapExpect.Ctx.cr2.u = uFlatAltStackAlias + X86_PAGE_SIZE;
     1618                }
     1619                if (!BS3_MODE_IS_16BIT_SYS(bTestMode))
     1620                    TrapExpect.Ctx.rflags.u32 |= X86_EFL_RF;
     1621
     1622                g_usBs3TestStep = iVariation * 1000 + iTest;
     1623
     1624                if (s_aTests[iTest].cbAdjSp < 0)
     1625                {
     1626#if 1
     1627                    /*
     1628                     * PUSH
     1629                     */
     1630                    RTUINT64U u64ExpectPushed;
     1631
     1632                    bs3CpuWeird1_PushPopInitStack(PtrStack2);
     1633                    u64ExpectPushed.u = *PtrStack2.pu64;
     1634                    if (TrapExpect.bXcpt == X86_XCPT_UD)
     1635                    {
     1636                        u64ExpectPushed.au16[0] = *pRegCtx;
     1637                        if (s_aTests[iTest].cbAdjSp < -2)
     1638                        {
     1639                            if (fFullWrite) /* enable for CPUs that writes more than a word */
     1640                            {
     1641                                u64ExpectPushed.au16[1] = 0;
     1642                                if (s_aTests[iTest].cbAdjSp == -8)
     1643                                    u64ExpectPushed.au32[1] = 0;
     1644                            }
     1645                            /* Intel 10980XE real mode: high word appears to be from EFLAGS. Weird! */
     1646                            else if (bTestMode == BS3_MODE_RM && fInRmWrHiEfl)
     1647                                u64ExpectPushed.au16[1] = Ctx.rflags.au16[1];
     1648                        }
     1649                    }
     1650
     1651                    for (iRep = 0; iRep < 256; iRep++)
     1652                    {
     1653                        if (iVariation < 3)
     1654                            bs3CpuWeird1_PushPopInitStack(PtrStack2);
     1655                        Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
     1656                        if (bs3CpuWeird1_ComparePushPop(&TrapCtx, &TrapExpect))
     1657                            break;
     1658
     1659                        //if (iVariation < 3)
     1660                        {
     1661                            if (*PtrStack2.pu64 != u64ExpectPushed.u)
     1662                            {
     1663                                Bs3TestFailedF("%u - Unexpected stack value after push: %RX64, expected %RX64",
     1664                                               g_usBs3TestStep, *PtrStack2.pu64, u64ExpectPushed);
     1665                                break;
     1666                            }
     1667                        }
     1668                        //else if (*PtrStack2.pu16 != u64ExpectPushed.au16[0])
     1669                        //{
     1670                        //    Bs3TestFailedF("%u - Unexpected stack value after push: %RX16, expected %RX16",
     1671                        //                   g_usBs3TestStep, *PtrStack2.pu16, u64ExpectPushed.au16[0]);
     1672                        //    break;
     1673                        //}
     1674                    }
     1675#endif
     1676                }
     1677                else
     1678                {
     1679#if 1
     1680                    /*
     1681                     * POP.
     1682                     */
     1683                    if (TrapExpect.bXcpt == X86_XCPT_UD)
     1684                        *pRegExpect = uPopSel;
     1685
     1686                    for (iRep = 0; iRep < 256; iRep++)
     1687                    {
     1688                        bs3CpuWeird1_PushPopInitStack(PtrStack2);
     1689                        *PtrStack2.pu16 = uPopSel;
     1690                        Bs3TrapSetJmpAndRestore(&Ctx, &TrapCtx);
     1691                        if (bs3CpuWeird1_ComparePushPop(&TrapCtx, &TrapExpect))
     1692                            break;
     1693                    }
     1694#endif
     1695                }
     1696
     1697                /* Restore context (except cs:rip): */
     1698                *pRegCtx    = uSavedSel;
     1699                Ctx.rsp.u32 = uNominalEsp;
     1700            }
     1701        }
     1702
     1703        /* Restore original SS:RSP value. */
     1704        Ctx.rsp.u = uSavedRsp;
     1705        Ctx.ss    = uSavedSs;
     1706    }
     1707
     1708    if (pbAltStack)
     1709        Bs3MemFree(pbAltStack, cbAltStack);
     1710
     1711    return 0;
     1712}
     1713
  • trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1.c

    r102778 r102779  
    4949FNBS3TESTDOMODE bs3CpuWeird1_PcWrapping_f16;
    5050FNBS3TESTDOMODE bs3CpuWeird1_PushPop_f16;
     51FNBS3TESTDOMODE bs3CpuWeird1_PushPopSReg_f16;
    5152
    5253
     
    6364#endif
    6465    { "push/pop", bs3CpuWeird1_PushPop_f16, 0 },
     66    { "push/pop sreg", bs3CpuWeird1_PushPopSReg_f16, 0 },
    6567};
    6668
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