- Timestamp:
- Jan 7, 2024 1:02:16 AM (13 months ago)
- 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 221 221 222 222 223 ; 224 ; PUSH / POP SREG. 225 ; 226 227 BS3_PROC_BEGIN_CMN bs3CpuWeird1_Push_fs_Ud2, BS3_PBC_NEAR 228 push fs 229 .ud2_again: 230 ud2 231 jmp .ud2_again 232 AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_fs_Ud2) == 2) 233 BS3_PROC_END_CMN bs3CpuWeird1_Push_fs_Ud2 234 235 236 BS3_PROC_BEGIN_CMN bs3CpuWeird1_Pop_fs_Ud2, BS3_PBC_NEAR 237 pop fs 238 .ud2_again: 239 ud2 240 jmp .ud2_again 241 AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_fs_Ud2) == 2) 242 BS3_PROC_END_CMN bs3CpuWeird1_Pop_fs_Ud2 243 244 245 BS3_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 251 AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Push_opsize_fs_Ud2) == 3) 252 BS3_PROC_END_CMN bs3CpuWeird1_Push_opsize_fs_Ud2 253 254 255 BS3_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 261 AssertCompile(.ud2_again - BS3_CMN_NM(bs3CpuWeird1_Pop_opsize_fs_Ud2) == 3) 262 BS3_PROC_END_CMN bs3CpuWeird1_Pop_opsize_fs_Ud2 263 264 223 265 %endif ; BS3_INSTANTIATING_CMN 224 266 -
trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-weird-1-x0.c
r102778 r102779 1012 1012 * For 64-bit we have to alias the two buffer pages to the first and 1013 1013 * last page in the address space. To test that the 32-bit 4G rollover 1014 * isn't incorrectly applied to LM64, we repeat this mapping for the 4G1015 * and 8G boundaries too.1014 * isn't incorrectly applied to LM64, we repeat this mapping for the 1015 * 4G and 8G boundaries too. 1016 1016 * 1017 1017 * This ASSUMES there is nothing important in page 0 when in LM64. … … 1381 1381 } 1382 1382 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 1392 PROTO_ALL(bs3CpuWeird1_Push_fs_Ud2); 1393 PROTO_ALL(bs3CpuWeird1_Pop_fs_Ud2); 1394 PROTO_ALL(bs3CpuWeird1_Push_opsize_fs_Ud2); 1395 PROTO_ALL(bs3CpuWeird1_Pop_opsize_fs_Ud2); 1396 #undef PROTO_ALL 1397 1398 1399 BS3_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 49 49 FNBS3TESTDOMODE bs3CpuWeird1_PcWrapping_f16; 50 50 FNBS3TESTDOMODE bs3CpuWeird1_PushPop_f16; 51 FNBS3TESTDOMODE bs3CpuWeird1_PushPopSReg_f16; 51 52 52 53 … … 63 64 #endif 64 65 { "push/pop", bs3CpuWeird1_PushPop_f16, 0 }, 66 { "push/pop sreg", bs3CpuWeird1_PushPopSReg_f16, 0 }, 65 67 }; 66 68
Note:
See TracChangeset
for help on using the changeset viewer.