VirtualBox

Changeset 93877 in vbox


Ignore:
Timestamp:
Feb 21, 2022 8:49:18 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150094
Message:

VMM/IEM: Fixed EFlags for LOCK XADD, adding tests for it. bugref:9898

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllAImplC.cpp

    r93869 r93877  
    13581358{
    13591359    uint64_t uOld = ASMAtomicUoReadU64(puDst);
    1360     uint64_t uTmpDst;
     1360    uint64_t uResult;
    13611361    uint32_t fEflTmp;
    13621362    do
    13631363    {
    1364         uTmpDst = uOld;
     1364        uResult = uOld;
    13651365        fEflTmp = *pfEFlags;
    1366         iemAImpl_add_u64(&uTmpDst, *puReg, pfEFlags);
    1367     } while (!ASMAtomicCmpXchgExU64(puDst, uTmpDst, uOld, &uOld));
     1366        iemAImpl_add_u64(&uResult, *puReg, &fEflTmp);
     1367    } while (!ASMAtomicCmpXchgExU64(puDst, uResult, uOld, &uOld));
    13681368    *puReg    = uOld;
    13691369    *pfEFlags = fEflTmp;
     
    13851385{
    13861386    uint32_t uOld = ASMAtomicUoReadU32(puDst);
    1387     uint32_t uTmpDst;
     1387    uint32_t uResult;
    13881388    uint32_t fEflTmp;
    13891389    do
    13901390    {
    1391         uTmpDst = uOld;
     1391        uResult = uOld;
    13921392        fEflTmp = *pfEFlags;
    1393         iemAImpl_add_u32(&uTmpDst, *puReg, pfEFlags);
    1394     } while (!ASMAtomicCmpXchgExU32(puDst, uTmpDst, uOld, &uOld));
     1393        iemAImpl_add_u32(&uResult, *puReg, &fEflTmp);
     1394    } while (!ASMAtomicCmpXchgExU32(puDst, uResult, uOld, &uOld));
    13951395    *puReg    = uOld;
    13961396    *pfEFlags = fEflTmp;
     
    14111411{
    14121412    uint16_t uOld = ASMAtomicUoReadU16(puDst);
    1413     uint16_t uTmpDst;
     1413    uint16_t uResult;
    14141414    uint32_t fEflTmp;
    14151415    do
    14161416    {
    1417         uTmpDst = uOld;
     1417        uResult = uOld;
    14181418        fEflTmp = *pfEFlags;
    1419         iemAImpl_add_u16(&uTmpDst, *puReg, pfEFlags);
    1420     } while (!ASMAtomicCmpXchgExU16(puDst, uTmpDst, uOld, &uOld));
     1419        iemAImpl_add_u16(&uResult, *puReg, &fEflTmp);
     1420    } while (!ASMAtomicCmpXchgExU16(puDst, uResult, uOld, &uOld));
    14211421    *puReg    = uOld;
    14221422    *pfEFlags = fEflTmp;
     
    14371437{
    14381438    uint8_t uOld = ASMAtomicUoReadU8(puDst);
    1439     uint8_t uTmpDst;
     1439    uint8_t uResult;
    14401440    uint32_t fEflTmp;
    14411441    do
    14421442    {
    1443         uTmpDst = uOld;
     1443        uResult = uOld;
    14441444        fEflTmp = *pfEFlags;
    1445         iemAImpl_add_u8(&uTmpDst, *puReg, pfEFlags);
    1446     } while (!ASMAtomicCmpXchgExU8(puDst, uTmpDst, uOld, &uOld));
     1445        iemAImpl_add_u8(&uResult, *puReg, &fEflTmp);
     1446    } while (!ASMAtomicCmpXchgExU8(puDst, uResult, uOld, &uOld));
    14471447    *puReg    = uOld;
    14481448    *pfEFlags = fEflTmp;
  • trunk/src/VBox/VMM/testcase/tstIEMAImpl.cpp

    r93870 r93877  
    150150*   Global Variables                                                                                                             *
    151151*********************************************************************************************************************************/
    152 static RTTEST g_hTest;
     152static RTTEST       g_hTest;
     153static uint8_t     *g_pu8,   *g_pu8Two;
     154static uint16_t    *g_pu16,  *g_pu16Two;
     155static uint32_t    *g_pu32,  *g_pu32Two,  *g_pfEfl;
     156static uint64_t    *g_pu64,  *g_pu64Two;
     157static RTUINT128U  *g_pu128, *g_pu128Two;
     158
    153159
    154160#include "tstIEMAImplData.h"
     
    287293                             EFlagsDiff(fEfl, paTests[iTest].fEflOut),
    288294                             uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
     295            else
     296            {
     297                 *g_pu8   = paTests[iTest].uDstIn;
     298                 *g_pfEfl = paTests[iTest].fEflIn;
     299                 g_aBinU8[iFn].pfn(g_pu8, paTests[iTest].uSrcIn, g_pfEfl);
     300                 RTTEST_CHECK(g_hTest, *g_pu8   == paTests[iTest].uDstOut);
     301                 RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
     302            }
    289303        }
    290304    }
     
    402416                             EFlagsDiff(fEfl, paTests[iTest].fEflOut),
    403417                             uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
     418            else
     419            {
     420                 *g_pu16  = paTests[iTest].uDstIn;
     421                 *g_pfEfl = paTests[iTest].fEflIn;
     422                 g_aBinU16[iFn].pfn(g_pu16, paTests[iTest].uSrcIn, g_pfEfl);
     423                 RTTEST_CHECK(g_hTest, *g_pu16== paTests[iTest].uDstOut);
     424                 RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
     425            }
    404426        }
    405427    }
     
    515537                             EFlagsDiff(fEfl, paTests[iTest].fEflOut),
    516538                             uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
     539            else
     540            {
     541                 *g_pu32  = paTests[iTest].uDstIn;
     542                 *g_pfEfl = paTests[iTest].fEflIn;
     543                 g_aBinU32[iFn].pfn(g_pu32, paTests[iTest].uSrcIn, g_pfEfl);
     544                 RTTEST_CHECK(g_hTest, *g_pu32  == paTests[iTest].uDstOut);
     545                 RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
     546            }
    517547        }
    518548    }
     
    628658                             EFlagsDiff(fEfl, paTests[iTest].fEflOut),
    629659                             uDst == paTests[iTest].uDstOut ? "eflags" : fEfl == paTests[iTest].fEflOut ? "dst" : "both");
     660            else
     661            {
     662                 *g_pu64  = paTests[iTest].uDstIn;
     663                 *g_pfEfl = paTests[iTest].fEflIn;
     664                 g_aBinU64[iFn].pfn(g_pu64, paTests[iTest].uSrcIn, g_pfEfl);
     665                 RTTEST_CHECK(g_hTest, *g_pu64  == paTests[iTest].uDstOut);
     666                 RTTEST_CHECK(g_hTest, *g_pfEfl == paTests[iTest].fEflOut);
     667            }
    630668        }
    631669    }
     670}
     671
     672
     673/*
     674 * XCHG
     675 */
     676static void XchgTest(void)
     677{
     678    RTTestSub(g_hTest, "xchg");
     679    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU8, (uint8_t  *pu8Mem,  uint8_t  *pu8Reg));
     680    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU16,(uint16_t *pu16Mem, uint16_t *pu16Reg));
     681    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU32,(uint32_t *pu32Mem, uint32_t *pu32Reg));
     682    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXCHGU64,(uint64_t *pu64Mem, uint64_t *pu64Reg));
     683
     684    static struct
     685    {
     686        uint8_t cb; uint64_t fMask;
     687        union
     688        {
     689            uintptr_t           pfn;
     690            FNIEMAIMPLXCHGU8   *pfnU8;
     691            FNIEMAIMPLXCHGU16  *pfnU16;
     692            FNIEMAIMPLXCHGU32  *pfnU32;
     693            FNIEMAIMPLXCHGU64  *pfnU64;
     694        } u;
     695    }
     696    s_aXchgWorkers[] =
     697    {
     698        { 1, UINT8_MAX,  { (uintptr_t)iemAImpl_xchg_u8_locked    } },
     699        { 2, UINT16_MAX, { (uintptr_t)iemAImpl_xchg_u16_locked   } },
     700        { 4, UINT32_MAX, { (uintptr_t)iemAImpl_xchg_u32_locked   } },
     701        { 8, UINT64_MAX, { (uintptr_t)iemAImpl_xchg_u64_locked   } },
     702        { 1, UINT8_MAX,  { (uintptr_t)iemAImpl_xchg_u8_unlocked  } },
     703        { 2, UINT16_MAX, { (uintptr_t)iemAImpl_xchg_u16_unlocked } },
     704        { 4, UINT32_MAX, { (uintptr_t)iemAImpl_xchg_u32_unlocked } },
     705        { 8, UINT64_MAX, { (uintptr_t)iemAImpl_xchg_u64_unlocked } },
     706    };
     707    for (size_t i = 0; i < RT_ELEMENTS(s_aXchgWorkers); i++)
     708    {
     709        RTUINT64U uIn1, uIn2, uMem, uDst;
     710        uMem.u = uIn1.u = RTRandU64Ex(0, s_aXchgWorkers[i].fMask);
     711        uDst.u = uIn2.u = RTRandU64Ex(0, s_aXchgWorkers[i].fMask);
     712        if (uIn1.u == uIn2.u)
     713            uDst.u = uIn2.u = ~uIn2.u;
     714
     715        switch (s_aXchgWorkers[i].cb)
     716        {
     717            case 1:
     718                s_aXchgWorkers[i].u.pfnU8(g_pu8, g_pu8Two);
     719                s_aXchgWorkers[i].u.pfnU8(&uMem.au8[0], &uDst.au8[0]);
     720                break;
     721            case 2:
     722                s_aXchgWorkers[i].u.pfnU16(g_pu16, g_pu16Two);
     723                s_aXchgWorkers[i].u.pfnU16(&uMem.Words.w0, &uDst.Words.w0);
     724                break;
     725            case 4:
     726                s_aXchgWorkers[i].u.pfnU32(g_pu32, g_pu32Two);
     727                s_aXchgWorkers[i].u.pfnU32(&uMem.DWords.dw0, &uDst.DWords.dw0);
     728                break;
     729            case 8:
     730                s_aXchgWorkers[i].u.pfnU64(g_pu64, g_pu64Two);
     731                s_aXchgWorkers[i].u.pfnU64(&uMem.u, &uDst.u);
     732                break;
     733            default: RTTestFailed(g_hTest, "%d\n", s_aXchgWorkers[i].cb); break;
     734        }
     735
     736        if (uMem.u != uIn2.u || uDst.u != uIn1.u)
     737            RTTestFailed(g_hTest, "i=%u: %#RX64, %#RX64 -> %#RX64, %#RX64\n", i,  uIn1.u, uIn2.u, uMem.u, uDst.u);
     738    }
     739}
     740
     741
     742/*
     743 * XADD
     744 */
     745static void XaddTest(void)
     746{
     747    RTTestSub(g_hTest, "xadd");
     748    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU8, (uint8_t  *pu8Mem,  uint8_t  *pu8Reg,  uint32_t *pEFlags));
     749    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU16,(uint16_t *pu16Mem, uint16_t *pu16Reg, uint32_t *pEFlags));
     750    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU32,(uint32_t *pu32Mem, uint32_t *pu32Reg, uint32_t *pEFlags));
     751    typedef IEM_DECL_IMPL_TYPE(void, FNIEMAIMPLXADDU64,(uint64_t *pu64Mem, uint64_t *pu64Reg, uint32_t *pEFlags));
     752
     753#define TEST_XADD(a_cBits, a_Type, a_Fmt) do {\
     754        static struct \
     755        { \
     756            const char                         *pszName; \
     757            FNIEMAIMPLXADDU ## a_cBits         *pfn; \
     758            BINU ## a_cBits ## _TEST_T const   *paTests; \
     759            uint32_t                            cTests; \
     760        } const s_aFuncs[] = \
     761        { \
     762            { "xadd_u" # a_cBits,            iemAImpl_xadd_u ## a_cBits, \
     763              g_aTests_add_u ## a_cBits, RT_ELEMENTS(g_aTests_add_u ## a_cBits) }, \
     764            { "xadd_u" # a_cBits "8_locked", iemAImpl_xadd_u ## a_cBits ## _locked, \
     765              g_aTests_add_u ## a_cBits, RT_ELEMENTS(g_aTests_add_u ## a_cBits) }, \
     766        }; \
     767        for (size_t iFn = 0; iFn < RT_ELEMENTS(s_aFuncs); iFn++) \
     768        { \
     769            BINU ## a_cBits ## _TEST_T const * const paTests = s_aFuncs[iFn].paTests; \
     770            uint32_t const                           cTests  = s_aFuncs[iFn].cTests; \
     771            for (uint32_t iTest = 0; iTest < cTests; iTest++) \
     772            { \
     773                uint32_t fEfl = paTests[iTest].fEflIn; \
     774                a_Type   uSrc = paTests[iTest].uSrcIn; \
     775                *g_pu ## a_cBits = paTests[iTest].uDstIn; \
     776                s_aFuncs[iFn].pfn(g_pu ## a_cBits, &uSrc, &fEfl); \
     777                if (   fEfl             != paTests[iTest].fEflOut \
     778                    || *g_pu ## a_cBits != paTests[iTest].uDstOut \
     779                    || uSrc             != paTests[iTest].uDstIn) \
     780                    RTTestFailed(g_hTest, "%s/#%u: efl=%#08x dst=" a_Fmt " src=" a_Fmt " -> efl=%#08x dst=" a_Fmt " src=" a_Fmt ", expected %#08x, " a_Fmt ", " a_Fmt "%s\n", \
     781                                 s_aFuncs[iFn].pszName, iTest, paTests[iTest].fEflIn, paTests[iTest].uDstIn, paTests[iTest].uSrcIn, \
     782                                 fEfl, *g_pu ## a_cBits, uSrc, paTests[iTest].fEflOut, paTests[iTest].uDstOut, paTests[iTest].uDstIn, \
     783                                 EFlagsDiff(fEfl, paTests[iTest].fEflOut)); \
     784            } \
     785        } \
     786    } while(0)
     787    TEST_XADD(8, uint8_t, "%#04x");
     788    TEST_XADD(16, uint16_t, "%#06x");
     789    TEST_XADD(32, uint32_t, "%#010RX32");
     790    TEST_XADD(64, uint64_t, "%#010RX64");
    632791}
    633792
     
    715874    if (argc > 1)
    716875    {
    717         BinU8Test();
    718         BinU16Test();
    719         BinU32Test();
    720         BinU64Test();
     876        /* Allocate guarded memory for use in the tests. */
     877#define ALLOC_GUARDED_VAR(a_uVar) do { \
     878            rc = RTTestGuardedAlloc(g_hTest, sizeof(a_uVar), sizeof(a_uVar), false /*fHead*/, (void **)&a_uVar); \
     879            if (RT_FAILURE(rc)) RTTestFailed(g_hTest, "Failed to allocate guarded mem: " #a_uVar); \
     880        } while (0)
     881        ALLOC_GUARDED_VAR(g_pu8);
     882        ALLOC_GUARDED_VAR(g_pu16);
     883        ALLOC_GUARDED_VAR(g_pu32);
     884        ALLOC_GUARDED_VAR(g_pu64);
     885        ALLOC_GUARDED_VAR(g_pu128);
     886        ALLOC_GUARDED_VAR(g_pu8Two);
     887        ALLOC_GUARDED_VAR(g_pu16Two);
     888        ALLOC_GUARDED_VAR(g_pu32Two);
     889        ALLOC_GUARDED_VAR(g_pu64Two);
     890        ALLOC_GUARDED_VAR(g_pu128Two);
     891        ALLOC_GUARDED_VAR(g_pfEfl);
     892        if (RTTestErrorCount(g_hTest) == 0)
     893        {
     894            BinU8Test();
     895            BinU16Test();
     896            BinU32Test();
     897            BinU64Test();
     898            XchgTest();
     899            XaddTest();
     900        }
    721901        return RTTestSummaryAndDestroy(g_hTest);
    722902    }
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