VirtualBox

Changeset 49634 in vbox for trunk/src


Ignore:
Timestamp:
Nov 22, 2013 6:11:29 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
90859
Message:

SUPDrv: Added an interface for probing MSRs.

Location:
trunk/src/VBox
Files:
13 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r48677 r49634  
    8383SUPR3_SOURCES       = \
    8484        SUPLib.cpp \
     85        SUPLibLdr.cpp \
    8586        SUPLibSem.cpp \
    8687        SUPLibTracerA.asm \
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r49622 r49634  
    125125static int                  supdrvIOCtl_CallServiceModule(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPCALLSERVICE pReq);
    126126static int                  supdrvIOCtl_LoggerSettings(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLOGGERSETTINGS pReq);
     127static int                  supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq);
    127128static int                  supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
    128129static void                 supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
     
    18911892        }
    18921893
     1894        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_MSR_PROBER):
     1895        {
     1896            /* validate */
     1897            PSUPMSRPROBER pReq = (PSUPMSRPROBER)pReqHdr;
     1898            REQ_CHECK_SIZES(SUP_IOCTL_MSR_PROBER);
     1899            REQ_CHECK_EXPR(SUP_IOCTL_MSR_PROBER,
     1900                           pReq->u.In.enmOp > SUPMSRPROBEROP_INVALID && pReq->u.In.enmOp < SUPMSRPROBEROP_END);
     1901
     1902            pReqHdr->rc = supdrvIOCtl_MsrProber(pDevExt, pReq);
     1903            return 0;
     1904        }
     1905
     1906
    18931907        default:
    18941908            Log(("Unknown IOCTL %#lx\n", (long)uIOCtl));
     
    51375151
    51385152/**
     5153 * Implements the MSR prober operations.
     5154 *
     5155 * @returns VBox status code.
     5156 * @param   pDevExt     The device extension.
     5157 * @param   pReq        The request.
     5158 */
     5159static int supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq)
     5160{
     5161#ifdef SUPDRV_WITH_MSR_PROBER
     5162    RTCPUID const idCpu = pReq->u.In.idCpu == UINT32_MAX ? NIL_RTCPUID : pReq->u.In.idCpu;
     5163    int rc;
     5164
     5165    switch (pReq->u.In.enmOp)
     5166    {
     5167        case SUPMSRPROBEROP_READ:
     5168        {
     5169            uint64_t uValue;
     5170            rc = supdrvOSMsrProberRead(pReq->u.In.uMsr, idCpu, &uValue);
     5171            if (RT_SUCCESS(rc))
     5172            {
     5173                pReq->u.Out.uResults.Read.uValue = uValue;
     5174                pReq->u.Out.uResults.Read.fGp    = false;
     5175            }
     5176            else if (rc == VERR_ACCESS_DENIED)
     5177            {
     5178                pReq->u.Out.uResults.Read.uValue = 0;
     5179                pReq->u.Out.uResults.Read.fGp    = true;
     5180                rc  = VINF_SUCCESS;
     5181            }
     5182            break;
     5183        }
     5184
     5185        case SUPMSRPROBEROP_WRITE:
     5186            rc = supdrvOSMsrProberWrite(pReq->u.In.uMsr, idCpu, pReq->u.In.uArgs.Write.uToWrite);
     5187            if (RT_SUCCESS(rc))
     5188                pReq->u.Out.uResults.Write.fGp   = false;
     5189            else if (rc == VERR_ACCESS_DENIED)
     5190            {
     5191                pReq->u.Out.uResults.Read.fGp    = true;
     5192                rc  = VINF_SUCCESS;
     5193            }
     5194            break;
     5195
     5196        case SUPMSRPROBEROP_MODIFY:
     5197        case SUPMSRPROBEROP_MODIFY_FASTER:
     5198            rc = supdrvOSMsrProberModify(idCpu, pReq);
     5199            break;
     5200
     5201        default:
     5202            return VERR_INVALID_FUNCTION;
     5203    }
     5204    return rc;
     5205#else
     5206    return VERR_NOT_IMPLEMENTED;
     5207#endif
     5208}
     5209
     5210
     5211
     5212/**
    51395213 * Creates the GIP.
    51405214 *
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r44528 r49634  
    102102#define SUP_IOCTL_FAST_DO_RAW_RUN               SUP_CTL_CODE_FAST(64)
    103103/** Fast path IOCtl: VMMR0_DO_HM_RUN */
    104 #define SUP_IOCTL_FAST_DO_HM_RUN             SUP_CTL_CODE_FAST(65)
     104#define SUP_IOCTL_FAST_DO_HM_RUN                SUP_CTL_CODE_FAST(65)
    105105/** Just a NOP call for profiling the latency of a fast ioctl call to VMMR0. */
    106106#define SUP_IOCTL_FAST_DO_NOP                   SUP_CTL_CODE_FAST(66)
     
    194194 *          - Remove RTSpinlockReleaseNoInts.
    195195 */
    196 #define SUPDRV_IOC_VERSION                              0x001a0005
     196#define SUPDRV_IOC_VERSION                              0x001a0006
    197197
    198198/** SUP_IOCTL_COOKIE. */
     
    13331333
    13341334
     1335/** @name SUP_IOCTL_MSR_PROBER
     1336 * MSR probing interface, not available in normal builds.
     1337 *
     1338 * @{
     1339 */
     1340#define SUP_IOCTL_MSR_PROBER                        SUP_CTL_CODE_SIZE(34, SUP_IOCTL_MSR_PROBER_SIZE)
     1341#define SUP_IOCTL_MSR_PROBER_SIZE                   sizeof(SUPMSRPROBER)
     1342#define SUP_IOCTL_MSR_PROBER_SIZE_IN                sizeof(SUPMSRPROBER)
     1343#define SUP_IOCTL_MSR_PROBER_SIZE_OUT               sizeof(SUPMSRPROBER)
     1344
     1345typedef enum SUPMSRPROBEROP
     1346{
     1347    SUPMSRPROBEROP_INVALID = 0,                     /**< The customary invalid zero value. */
     1348    SUPMSRPROBEROP_READ,                            /**< Read an MSR. */
     1349    SUPMSRPROBEROP_WRITE,                           /**< Write a value to an MSR (use with care!). */
     1350    SUPMSRPROBEROP_MODIFY,                          /**< Read-modify-restore-flushall. */
     1351    SUPMSRPROBEROP_MODIFY_FASTER,                   /**< Read-modify-restore, skip the flushing. */
     1352    SUPMSRPROBEROP_END,                             /**< End of valid values. */
     1353    SUPMSRPROBEROP_32BIT_HACK = 0x7fffffff          /**< The customary 32-bit type hack. */
     1354} SUPMSRPROBEROP;
     1355
     1356typedef struct SUPMSRPROBER
     1357{
     1358    /** The header. */
     1359    SUPREQHDR               Hdr;
     1360
     1361    /** Input/output union. */
     1362    union
     1363    {
     1364        /** Inputs.  */
     1365        struct
     1366        {
     1367            /** The operation. */
     1368            SUPMSRPROBEROP          enmOp;
     1369            /** The MSR to test. */
     1370            uint32_t                uMsr;
     1371            /** The CPU to perform the operation on.
     1372             * Use UINT32_MAX to indicate that any CPU will do. */
     1373            uint32_t                idCpu;
     1374            /** Alignment padding. */
     1375            uint32_t                u32Padding;
     1376            /** Operation specific arguments. */
     1377            union
     1378            {
     1379                /* SUPMSRPROBEROP_READ takes no extra arguments. */
     1380
     1381                /** For SUPMSRPROBEROP_WRITE. */
     1382                struct
     1383                {
     1384                    /** The value to write. */
     1385                    uint64_t        uToWrite;
     1386                } Write;
     1387
     1388                /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */
     1389                struct
     1390                {
     1391                    /** The value to AND the current MSR value with to construct the value to
     1392                     *  write.  This applied first. */
     1393                    uint64_t        fAndMask;
     1394                    /** The value to OR the result of the above mentioned AND operation with
     1395                     * attempting to modify the MSR. */
     1396                    uint64_t        fOrMask;
     1397                } Modify;
     1398
     1399                /** Reserve space for the future.. */
     1400                uint64_t        auPadding[3];
     1401            } uArgs;
     1402        } In;
     1403
     1404        /** Outputs. */
     1405        struct
     1406        {
     1407            /** Operation specific results. */
     1408            union
     1409            {
     1410                /** For SUPMSRPROBEROP_READ. */
     1411                struct
     1412                {
     1413                    /** The value we've read. */
     1414                    uint64_t        uValue;
     1415                    /** Set if we GPed while reading it. */
     1416                    bool            fGp;
     1417                } Read;
     1418
     1419                /** For SUPMSRPROBEROP_WRITE. */
     1420                struct
     1421                {
     1422                    /** Set if we GPed while writing it. */
     1423                    bool            fGp;
     1424                } Write;
     1425
     1426                /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */
     1427                SUPMSRPROBERMODIFYRESULT Modify;
     1428
     1429                /** Size padding/aligning. */
     1430                uint64_t        auPadding[5];
     1431            } uResults;
     1432        } Out;
     1433    } u;
     1434} SUPMSRPROBER, *PSUPMSRPROBER;
     1435AssertCompileMemberAlignment(SUPMSRPROBER, u, 8);
     1436AssertCompileMemberAlignment(SUPMSRPROBER, u.In.uArgs, 8);
     1437AssertCompileMembersSameSizeAndOffset(SUPMSRPROBER, u.In, SUPMSRPROBER, u.Out);
     1438/** @} */
     1439
     1440
    13351441#pragma pack()                          /* paranoia */
    13361442
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r47537 r49634  
    209209    (   VALID_PTR(pDevExt)\
    210210     && pDevExt->u32Cookie == BIRD)
     211
     212
     213/** @def SUPDRV_WITH_MSR_PROBER
     214 * Enables the SUP_IOCTL_MSR_PROBER function.
     215 * By default, only enabled in DEBUG builds as it's a sensitive feature.
     216 */
     217#if defined(DEBUG) && !defined(SUPDRV_WITH_MSR_PROBER) && !defined(SUPDRV_WITHOUT_MSR_PROBER)
     218# define SUPDRV_WITH_MSR_PROBER
     219#endif
     220
     221/** @def SUPDRV_WITHOUT_MSR_PROBER
     222 * Executive overide for disabling the SUP_IOCTL_MSR_PROBER function.
     223 */
     224#ifdef SUPDRV_WITHOUT_MSR_PROBER
     225# undef SUPDRV_WITH_MSR_PROBER
     226#endif
    211227
    212228
     
    685701
    686702
     703#ifdef SUPDRV_WITH_MSR_PROBER
     704
     705/**
     706 * Tries to read an MSR.
     707 *
     708 * @returns One of the listed VBox status codes.
     709 * @retval  VINF_SUCCESS if read successfully, value in *puValue.
     710 * @retval  VERR_ACCESS_DENIED if we couldn't read it (GP).
     711 * @retval  VERR_NOT_SUPPORTED if not supported.
     712 *
     713 * @param   uMsr                The MSR to read from.
     714 * @param   idCpu               The CPU to read the MSR on. NIL_RTCPUID
     715 *                              indicates any suitable CPU.
     716 * @param   puValue             Where to return the value.
     717 */
     718int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue);
     719
     720/**
     721 * Tries to write an MSR.
     722 *
     723 * @returns One of the listed VBox status codes.
     724 * @retval  VINF_SUCCESS if written successfully.
     725 * @retval  VERR_ACCESS_DENIED if we couldn't write the value to it (GP).
     726 * @retval  VERR_NOT_SUPPORTED if not supported.
     727 *
     728 * @param   uMsr                The MSR to write to.
     729 * @param   idCpu               The CPU to write the MSR on. NIL_RTCPUID
     730 *                              indicates any suitable CPU.
     731 * @param   uValue              The value to write.
     732 */
     733int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue);
     734
     735/**
     736 * Tries to modify an MSR value.
     737 *
     738 * @returns One of the listed VBox status codes.
     739 * @retval  VINF_SUCCESS if succeeded.
     740 * @retval  VERR_NOT_SUPPORTED if not supported.
     741 *
     742 * @param   idCpu               The CPU to modify the MSR on. NIL_RTCPUID
     743 *                              indicates any suitable CPU.
     744 * @param   pReq                The request packet with input arguments and
     745 *                              where to store the results.
     746 */
     747int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq);
     748
     749#endif /* SUPDRV_WITH_MSR_PROBER */
     750
     751
    687752/*******************************************************************************
    688753*   Shared Functions                                                           *
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r49039 r49634  
    6868#include <iprt/x86.h>
    6969
     70#include "SUPDrvIOC.h"
    7071#include "SUPLibInternal.h"
    71 #include "SUPDrvIOC.h"
    7272
    7373
     
    117117DECLEXPORT(PSUPGLOBALINFOPAGE)  g_pSUPGlobalInfoPage;
    118118/** Address of the ring-0 mapping of the GIP. */
    119 static PSUPGLOBALINFOPAGE       g_pSUPGlobalInfoPageR0;
     119PSUPGLOBALINFOPAGE              g_pSUPGlobalInfoPageR0;
    120120/** The physical address of the GIP. */
    121121static RTHCPHYS                 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
     
    128128PSUPDRVSESSION                  g_pSession;
    129129/** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
    130 static PSUPQUERYFUNCS           g_pFunctions;
     130PSUPQUERYFUNCS                  g_pSupFunctions;
    131131
    132132/** VMMR0 Load Address. */
     
    135135static bool                     g_fSupportsPageAllocNoKernel = true;
    136136/** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
    137 static uint32_t                 g_u32FakeMode = ~0;
     137uint32_t                        g_uSupFakeMode = ~0;
    138138
    139139
     
    248248     * we haven't ported the support driver to.
    249249     */
    250     if (g_u32FakeMode == ~0U)
     250    if (g_uSupFakeMode == ~0U)
    251251    {
    252252        const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
    253253        if (psz && !strcmp(psz, "fake"))
    254             ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
     254            ASMAtomicCmpXchgU32(&g_uSupFakeMode, 1, ~0U);
    255255        else
    256             ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
    257     }
    258     if (RT_UNLIKELY(g_u32FakeMode))
     256            ASMAtomicCmpXchgU32(&g_uSupFakeMode, 0, ~0U);
     257    }
     258    if (RT_UNLIKELY(g_uSupFakeMode))
    259259        return supInitFake(ppSession);
    260260
     
    353353                    g_u32SessionCookie  = CookieReq.u.Out.u32SessionCookie;
    354354                    g_pSession          = CookieReq.u.Out.pSession;
    355                     g_pFunctions        = pFuncsReq;
     355                    g_pSupFunctions  = pFuncsReq;
    356356                    if (ppSession)
    357357                        *ppSession = CookieReq.u.Out.pSession;
     
    505505
    506506    /* fake r0 functions. */
    507     g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
    508     if (g_pFunctions)
    509     {
    510         g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
    511         memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
    512         g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
     507    g_pSupFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
     508    if (g_pSupFunctions)
     509    {
     510        g_pSupFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
     511        memcpy(&g_pSupFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
     512        g_pSession = (PSUPDRVSESSION)(void *)g_pSupFunctions;
    513513        if (ppSession)
    514514            *ppSession = g_pSession;
     
    524524        }
    525525
    526         RTMemFree(g_pFunctions);
    527         g_pFunctions = NULL;
     526        RTMemFree(g_pSupFunctions);
     527        g_pSupFunctions = NULL;
    528528    }
    529529    return VERR_NO_MEMORY;
     
    574574{
    575575    /* fake */
    576     if (RT_UNLIKELY(g_u32FakeMode))
     576    if (RT_UNLIKELY(g_uSupFakeMode))
    577577#ifdef RT_ARCH_AMD64
    578578        return SUPPAGINGMODE_AMD64_GLOBAL_NX;
     
    640640
    641641    /* fake */
    642     if (RT_UNLIKELY(g_u32FakeMode))
     642    if (RT_UNLIKELY(g_uSupFakeMode))
    643643        return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
    644644
     
    731731SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)
    732732{
    733     if (RT_UNLIKELY(g_u32FakeMode))
     733    if (RT_UNLIKELY(g_uSupFakeMode))
    734734        return VINF_SUCCESS;
    735735
     
    755755
    756756    /* fake */
    757     if (RT_UNLIKELY(g_u32FakeMode))
     757    if (RT_UNLIKELY(g_uSupFakeMode))
    758758        return VERR_NOT_SUPPORTED;
    759759
     
    956956
    957957    /* fake */
    958     if (RT_UNLIKELY(g_u32FakeMode))
     958    if (RT_UNLIKELY(g_uSupFakeMode))
    959959    {
    960960        RTHCPHYS    Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
     
    10171017
    10181018    /* fake */
    1019     if (RT_UNLIKELY(g_u32FakeMode))
     1019    if (RT_UNLIKELY(g_uSupFakeMode))
    10201020        return VINF_SUCCESS;
    10211021
     
    10721072
    10731073    /* fake */
    1074     if (RT_UNLIKELY(g_u32FakeMode))
     1074    if (RT_UNLIKELY(g_uSupFakeMode))
    10751075    {
    10761076        void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
     
    11651165
    11661166    /* fake */
    1167     if (RT_UNLIKELY(g_u32FakeMode))
     1167    if (RT_UNLIKELY(g_uSupFakeMode))
    11681168        return VERR_NOT_SUPPORTED;
    11691169
     
    12021202
    12031203    /* fake */
    1204     if (RT_UNLIKELY(g_u32FakeMode))
     1204    if (RT_UNLIKELY(g_uSupFakeMode))
    12051205        return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
    12061206
     
    12421242
    12431243    /* fake */
    1244     if (RT_UNLIKELY(g_u32FakeMode))
     1244    if (RT_UNLIKELY(g_uSupFakeMode))
    12451245    {
    12461246        RTMemPageFree(pvPages, cPages * PAGE_SIZE);
     
    12911291
    12921292    /* fake */
    1293     if (RT_UNLIKELY(g_u32FakeMode))
     1293    if (RT_UNLIKELY(g_uSupFakeMode))
    12941294    {
    12951295        void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
     
    13401340
    13411341    /* fake */
    1342     if (RT_UNLIKELY(g_u32FakeMode))
     1342    if (RT_UNLIKELY(g_uSupFakeMode))
    13431343    {
    13441344        RTMemPageFree(pv, cPages * PAGE_SIZE);
     
    13751375
    13761376    /* fake */
    1377     if (RT_UNLIKELY(g_u32FakeMode))
     1377    if (RT_UNLIKELY(g_uSupFakeMode))
    13781378    {
    13791379        *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
     
    14431443
    14441444    /* fake */
    1445     if (RT_UNLIKELY(g_u32FakeMode))
     1445    if (RT_UNLIKELY(g_uSupFakeMode))
    14461446    {
    14471447        RTMemPageFree(pv, cPages * PAGE_SIZE);
     
    15961596
    15971597
    1598 SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
    1599 {
    1600     /*
    1601      * Check that the module can be trusted.
    1602      */
    1603     int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
    1604     if (RT_SUCCESS(rc))
    1605     {
    1606         rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
    1607         if (RT_FAILURE(rc))
    1608             RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
    1609     }
    1610     return rc;
    1611 }
    1612 
    1613 
    1614 SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
    1615                                       const char *pszSrvReqHandler, void **ppvImageBase)
    1616 {
    1617     AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
    1618 
    1619     /*
    1620      * Check that the module can be trusted.
    1621      */
    1622     int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);
    1623     if (RT_SUCCESS(rc))
    1624         rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
    1625     else
    1626         LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
    1627     return rc;
    1628 }
    1629 
    1630 
    1631 /**
    1632  * Resolve an external symbol during RTLdrGetBits().
    1633  *
    1634  * @returns VBox status code.
    1635  * @param   hLdrMod         The loader module handle.
    1636  * @param   pszModule       Module name.
    1637  * @param   pszSymbol       Symbol name, NULL if uSymbol should be used.
    1638  * @param   uSymbol         Symbol ordinal, ~0 if pszSymbol should be used.
    1639  * @param   pValue          Where to store the symbol value (address).
    1640  * @param   pvUser          User argument.
    1641  */
    1642 static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
    1643                                                     const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
    1644 {
    1645     NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);
    1646     AssertPtr(pValue);
    1647     AssertPtr(pvUser);
    1648 
    1649     /*
    1650      * Only SUPR0 and VMMR0.r0
    1651      */
    1652     if (    pszModule
    1653         &&  *pszModule
    1654         &&  strcmp(pszModule, "VBoxDrv.sys")
    1655         &&  strcmp(pszModule, "VMMR0.r0"))
    1656     {
    1657         AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
    1658         return VERR_SYMBOL_NOT_FOUND;
    1659     }
    1660 
    1661     /*
    1662      * No ordinals.
    1663      */
    1664     if (pszSymbol < (const char*)0x10000)
    1665     {
    1666         AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
    1667         return VERR_SYMBOL_NOT_FOUND;
    1668     }
    1669 
    1670     /*
    1671      * Lookup symbol.
    1672      */
    1673     /** @todo is this actually used??? */
    1674     /* skip the 64-bit ELF import prefix first. */
    1675     if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))
    1676         pszSymbol += sizeof("SUPR0$") - 1;
    1677 
    1678     /*
    1679      * Check the VMMR0.r0 module if loaded.
    1680      */
    1681     /** @todo call the SUPR3LoadModule caller.... */
    1682     /** @todo proper reference counting and such. */
    1683     if (g_pvVMMR0 != NIL_RTR0PTR)
    1684     {
    1685         void *pvValue;
    1686         if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
    1687         {
    1688             *pValue = (uintptr_t)pvValue;
    1689             return VINF_SUCCESS;
    1690         }
    1691     }
    1692 
    1693     /* iterate the function table. */
    1694     int c = g_pFunctions->u.Out.cFunctions;
    1695     PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];
    1696     while (c-- > 0)
    1697     {
    1698         if (!strcmp(pFunc->szName, pszSymbol))
    1699         {
    1700             *pValue = (uintptr_t)pFunc->pfn;
    1701             return VINF_SUCCESS;
    1702         }
    1703         pFunc++;
    1704     }
    1705 
    1706     /*
    1707      * The GIP.
    1708      */
    1709     if (    pszSymbol
    1710         &&  g_pSUPGlobalInfoPage
    1711         &&  g_pSUPGlobalInfoPageR0
    1712         &&  !strcmp(pszSymbol, "g_SUPGlobalInfoPage")
    1713        )
    1714     {
    1715         *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
    1716         return VINF_SUCCESS;
    1717     }
    1718 
    1719     /*
    1720      * Symbols that are undefined by convention.
    1721      */
    1722 #ifdef RT_OS_SOLARIS
    1723     static const char * const s_apszConvSyms[] =
    1724     {
    1725         "", "mod_getctl",
    1726         "", "mod_install",
    1727         "", "mod_remove",
    1728         "", "mod_info",
    1729         "", "mod_miscops",
    1730     };
    1731     for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)
    1732     {
    1733         if (   !RTStrCmp(s_apszConvSyms[i],     pszModule)
    1734             && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))
    1735         {
    1736             *pValue = ~(uintptr_t)0;
    1737             return VINF_SUCCESS;
    1738         }
    1739     }
    1740 #endif
    1741 
    1742     /*
    1743      * Despair.
    1744      */
    1745     c = g_pFunctions->u.Out.cFunctions;
    1746     pFunc = &g_pFunctions->u.Out.aFunctions[0];
    1747     while (c-- > 0)
    1748     {
    1749         RTAssertMsg2Weak("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);
    1750         pFunc++;
    1751     }
    1752 
    1753     AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
    1754     if (g_u32FakeMode)
    1755     {
    1756         *pValue = 0xdeadbeef;
    1757         return VINF_SUCCESS;
    1758     }
    1759     return VERR_SYMBOL_NOT_FOUND;
    1760 }
    1761 
    1762 
    1763 /** Argument package for supLoadModuleCalcSizeCB. */
    1764 typedef struct SUPLDRCALCSIZEARGS
    1765 {
    1766     size_t          cbStrings;
    1767     uint32_t        cSymbols;
    1768     size_t          cbImage;
    1769 } SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
    1770 
    1771 /**
    1772  * Callback used to calculate the image size.
    1773  * @return VINF_SUCCESS
    1774  */
    1775 static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
    1776 {
    1777     PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
    1778     if (    pszSymbol != NULL
    1779         &&  *pszSymbol
    1780         &&  Value <= pArgs->cbImage)
    1781     {
    1782         pArgs->cSymbols++;
    1783         pArgs->cbStrings += strlen(pszSymbol) + 1;
    1784     }
    1785     NOREF(hLdrMod); NOREF(uSymbol);
    1786     return VINF_SUCCESS;
    1787 }
    1788 
    1789 
    1790 /** Argument package for supLoadModuleCreateTabsCB. */
    1791 typedef struct SUPLDRCREATETABSARGS
    1792 {
    1793     size_t          cbImage;
    1794     PSUPLDRSYM      pSym;
    1795     char           *pszBase;
    1796     char           *psz;
    1797 } SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
    1798 
    1799 /**
    1800  * Callback used to calculate the image size.
    1801  * @return VINF_SUCCESS
    1802  */
    1803 static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
    1804 {
    1805     PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
    1806     if (    pszSymbol != NULL
    1807         &&  *pszSymbol
    1808         &&  Value <= pArgs->cbImage)
    1809     {
    1810         pArgs->pSym->offSymbol = (uint32_t)Value;
    1811         pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
    1812         pArgs->pSym++;
    1813 
    1814         size_t cbCopy = strlen(pszSymbol) + 1;
    1815         memcpy(pArgs->psz, pszSymbol, cbCopy);
    1816         pArgs->psz += cbCopy;
    1817     }
    1818     NOREF(hLdrMod); NOREF(uSymbol);
    1819     return VINF_SUCCESS;
    1820 }
    1821 
    1822 
    1823 /**
    1824  * Worker for SUPR3LoadModule().
    1825  *
    1826  * @returns VBox status code.
    1827  * @param   pszFilename     Name of the VMMR0 image file
    1828  */
    1829 static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
    1830 {
    1831     int rc;
    1832 
    1833     /*
    1834      * Validate input.
    1835      */
    1836     AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
    1837     AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
    1838     AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
    1839     AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
    1840     char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
    1841     rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
    1842     if (RT_FAILURE(rc))
    1843         return rc;
    1844     pszFilename = szAbsFilename;
    1845 
    1846     const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
    1847     AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
    1848     *ppvImageBase = NULL;
    1849 
    1850     /*
    1851      * Open image file and figure its size.
    1852      */
    1853     RTLDRMOD hLdrMod;
    1854     rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
    1855     if (!RT_SUCCESS(rc))
    1856     {
    1857         LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));
    1858         return rc;
    1859     }
    1860 
    1861     SUPLDRCALCSIZEARGS CalcArgs;
    1862     CalcArgs.cbStrings = 0;
    1863     CalcArgs.cSymbols = 0;
    1864     CalcArgs.cbImage = RTLdrSize(hLdrMod);
    1865     rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
    1866     if (RT_SUCCESS(rc))
    1867     {
    1868         const uint32_t  offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
    1869         const uint32_t  offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
    1870         const uint32_t  cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
    1871 
    1872         /*
    1873          * Open the R0 image.
    1874          */
    1875         SUPLDROPEN OpenReq;
    1876         OpenReq.Hdr.u32Cookie = g_u32Cookie;
    1877         OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
    1878         OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
    1879         OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
    1880         OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1881         OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
    1882         OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
    1883         OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
    1884         strcpy(OpenReq.u.In.szName, pszModule);
    1885         strcpy(OpenReq.u.In.szFilename, pszFilename);
    1886         if (!g_u32FakeMode)
    1887         {
    1888             rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
    1889             if (RT_SUCCESS(rc))
    1890                 rc = OpenReq.Hdr.rc;
    1891         }
    1892         else
    1893         {
    1894             OpenReq.u.Out.fNeedsLoading = true;
    1895             OpenReq.u.Out.pvImageBase = 0xef423420;
    1896         }
    1897         *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
    1898         if (    RT_SUCCESS(rc)
    1899             &&  OpenReq.u.Out.fNeedsLoading)
    1900         {
    1901             /*
    1902              * We need to load it.
    1903              * Allocate memory for the image bits.
    1904              */
    1905             PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
    1906             if (pLoadReq)
    1907             {
    1908                 /*
    1909                  * Get the image bits.
    1910                  */
    1911                 rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
    1912                                   supLoadModuleResolveImport, (void *)pszModule);
    1913 
    1914                 if (RT_SUCCESS(rc))
    1915                 {
    1916                     /*
    1917                      * Get the entry points.
    1918                      */
    1919                     RTUINTPTR VMMR0EntryInt = 0;
    1920                     RTUINTPTR VMMR0EntryFast = 0;
    1921                     RTUINTPTR VMMR0EntryEx = 0;
    1922                     RTUINTPTR SrvReqHandler = 0;
    1923                     RTUINTPTR ModuleInit = 0;
    1924                     RTUINTPTR ModuleTerm = 0;
    1925                     if (fIsVMMR0)
    1926                     {
    1927                         rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
    1928                         if (RT_SUCCESS(rc))
    1929                             rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
    1930                         if (RT_SUCCESS(rc))
    1931                             rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
    1932                     }
    1933                     else if (pszSrvReqHandler)
    1934                         rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
    1935                     if (RT_SUCCESS(rc))
    1936                     {
    1937                         int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
    1938                         if (RT_FAILURE(rc2))
    1939                             ModuleInit = 0;
    1940 
    1941                         rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
    1942                         if (RT_FAILURE(rc2))
    1943                             ModuleTerm = 0;
    1944                     }
    1945                     if (RT_SUCCESS(rc))
    1946                     {
    1947                         /*
    1948                          * Create the symbol and string tables.
    1949                          */
    1950                         SUPLDRCREATETABSARGS CreateArgs;
    1951                         CreateArgs.cbImage = CalcArgs.cbImage;
    1952                         CreateArgs.pSym    = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
    1953                         CreateArgs.pszBase =     (char *)&pLoadReq->u.In.abImage[offStrTab];
    1954                         CreateArgs.psz     = CreateArgs.pszBase;
    1955                         rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
    1956                         if (RT_SUCCESS(rc))
    1957                         {
    1958                             AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
    1959                             AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
    1960 
    1961                             /*
    1962                              * Upload the image.
    1963                              */
    1964                             pLoadReq->Hdr.u32Cookie = g_u32Cookie;
    1965                             pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    1966                             pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
    1967                             pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
    1968                             pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
    1969                             pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
    1970 
    1971                             pLoadReq->u.In.pfnModuleInit              = (RTR0PTR)ModuleInit;
    1972                             pLoadReq->u.In.pfnModuleTerm              = (RTR0PTR)ModuleTerm;
    1973                             if (fIsVMMR0)
    1974                             {
    1975                                 pLoadReq->u.In.eEPType                = SUPLDRLOADEP_VMMR0;
    1976                                 pLoadReq->u.In.EP.VMMR0.pvVMMR0       = OpenReq.u.Out.pvImageBase;
    1977                                 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
    1978                                 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
    1979                                 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx  = (RTR0PTR)VMMR0EntryEx;
    1980                             }
    1981                             else if (pszSrvReqHandler)
    1982                             {
    1983                                 pLoadReq->u.In.eEPType                = SUPLDRLOADEP_SERVICE;
    1984                                 pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
    1985                                 pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
    1986                                 pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
    1987                                 pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
    1988                             }
    1989                             else
    1990                                 pLoadReq->u.In.eEPType                = SUPLDRLOADEP_NOTHING;
    1991                             pLoadReq->u.In.offStrTab                  = offStrTab;
    1992                             pLoadReq->u.In.cbStrTab                   = (uint32_t)CalcArgs.cbStrings;
    1993                             AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
    1994                             pLoadReq->u.In.cbImageBits                = (uint32_t)CalcArgs.cbImage;
    1995                             pLoadReq->u.In.offSymbols                 = offSymTab;
    1996                             pLoadReq->u.In.cSymbols                   = CalcArgs.cSymbols;
    1997                             pLoadReq->u.In.cbImageWithTabs            = cbImageWithTabs;
    1998                             pLoadReq->u.In.pvImageBase                = OpenReq.u.Out.pvImageBase;
    1999                             if (!g_u32FakeMode)
    2000                             {
    2001                                 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
    2002                                 if (RT_SUCCESS(rc))
    2003                                     rc = pLoadReq->Hdr.rc;
    2004                                 else
    2005                                     LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
    2006                             }
    2007                             else
    2008                                 rc = VINF_SUCCESS;
    2009                             if (    RT_SUCCESS(rc)
    2010                                 ||  rc == VERR_ALREADY_LOADED /* A competing process. */
    2011                                )
    2012                             {
    2013                                 LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",
    2014                                         pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,
    2015                                         OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
    2016                                 if (fIsVMMR0)
    2017                                 {
    2018                                     g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
    2019                                     LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
    2020                                             VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
    2021                                 }
    2022 #ifdef RT_OS_WINDOWS
    2023                                 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
    2024 #endif
    2025 
    2026                                 RTMemTmpFree(pLoadReq);
    2027                                 RTLdrClose(hLdrMod);
    2028                                 return VINF_SUCCESS;
    2029                             }
    2030                             else
    2031                                 LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
    2032                         }
    2033                         else
    2034                             LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
    2035                     }
    2036                     else
    2037                         LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
    2038                 }
    2039                 else
    2040                     LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
    2041                 RTMemTmpFree(pLoadReq);
    2042             }
    2043             else
    2044             {
    2045                 AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
    2046                 rc = VERR_NO_TMP_MEMORY;
    2047             }
    2048         }
    2049         else if (RT_SUCCESS(rc))
    2050         {
    2051             if (fIsVMMR0)
    2052                 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
    2053             LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
    2054                     OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
    2055 #ifdef RT_OS_WINDOWS
    2056             LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
    2057 #endif
    2058         }
    2059     }
    2060     RTLdrClose(hLdrMod);
    2061     return rc;
    2062 }
    2063 
    2064 
    2065 SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
    2066 {
    2067     /* fake */
    2068     if (RT_UNLIKELY(g_u32FakeMode))
    2069     {
    2070         g_pvVMMR0 = NIL_RTR0PTR;
    2071         return VINF_SUCCESS;
    2072     }
    2073 
    2074     /*
    2075      * Free the requested module.
    2076      */
    2077     SUPLDRFREE Req;
    2078     Req.Hdr.u32Cookie = g_u32Cookie;
    2079     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    2080     Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
    2081     Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
    2082     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    2083     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    2084     Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
    2085     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
    2086     if (RT_SUCCESS(rc))
    2087         rc = Req.Hdr.rc;
    2088     if (    RT_SUCCESS(rc)
    2089         &&  (RTR0PTR)pvImageBase == g_pvVMMR0)
    2090         g_pvVMMR0 = NIL_RTR0PTR;
    2091     return rc;
    2092 }
    2093 
    2094 
    2095 SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
    2096 {
    2097     *ppvValue = NULL;
    2098 
    2099     /* fake */
    2100     if (RT_UNLIKELY(g_u32FakeMode))
    2101     {
    2102         *ppvValue = (void *)(uintptr_t)0xdeadf00d;
    2103         return VINF_SUCCESS;
    2104     }
    2105 
    2106     /*
    2107      * Do ioctl.
    2108      */
    2109     SUPLDRGETSYMBOL Req;
    2110     Req.Hdr.u32Cookie = g_u32Cookie;
    2111     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    2112     Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
    2113     Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
    2114     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    2115     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    2116     Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
    2117     size_t cchSymbol = strlen(pszSymbol);
    2118     if (cchSymbol >= sizeof(Req.u.In.szSymbol))
    2119         return VERR_SYMBOL_NOT_FOUND;
    2120     memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
    2121     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
    2122     if (RT_SUCCESS(rc))
    2123         rc = Req.Hdr.rc;
    2124     if (RT_SUCCESS(rc))
    2125         *ppvValue = (void *)Req.u.Out.pvSymbol;
    2126     return rc;
    2127 }
    2128 
    2129 
    2130 SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
    2131 {
    2132     void *pvImageBase;
    2133     return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
    2134 }
    2135 
    2136 
    2137 SUPR3DECL(int) SUPR3UnloadVMM(void)
    2138 {
    2139     return SUPR3FreeModule((void*)g_pvVMMR0);
    2140 }
    2141 
    2142 
    21431598SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
    21441599{
     
    21501605    *pHCPhys = NIL_RTHCPHYS;
    21511606    return VERR_WRONG_ORDER;
    2152 }
    2153 
    2154 
    2155 /**
    2156  * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
    2157  *
    2158  * @returns iprt status code.
    2159  * @param   pszFilename     The full file name.
    2160  * @param   phLdrMod        Where to store the handle to the loaded module.
    2161  * @param   fFlags          See RTLDFLAGS_.
    2162  * @param   pErrInfo        Where to return extended error information.
    2163  *                          Optional.
    2164  *
    2165  */
    2166 static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
    2167 {
    2168 #ifdef VBOX_WITH_HARDENING
    2169     /*
    2170      * Verify the image file.
    2171      */
    2172     int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
    2173     if (RT_FAILURE(rc))
    2174     {
    2175         LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
    2176         return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");
    2177     }
    2178 #endif
    2179 
    2180     /*
    2181      * Try load it.
    2182      */
    2183     return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);
    2184 }
    2185 
    2186 
    2187 SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
    2188 {
    2189     /*
    2190      * Validate input.
    2191      */
    2192     RTErrInfoClear(pErrInfo);
    2193     AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
    2194     AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
    2195     *phLdrMod = NIL_RTLDRMOD;
    2196     AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
    2197 
    2198     /*
    2199      * Add the default extension if it's missing.
    2200      */
    2201     if (!RTPathHasSuffix(pszFilename))
    2202     {
    2203         const char *pszSuff = RTLdrGetSuff();
    2204         size_t      cchSuff = strlen(pszSuff);
    2205         size_t      cchFilename = strlen(pszFilename);
    2206         char       *psz = (char *)alloca(cchFilename + cchSuff + 1);
    2207         AssertReturn(psz, VERR_NO_TMP_MEMORY);
    2208         memcpy(psz, pszFilename, cchFilename);
    2209         memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
    2210         pszFilename = psz;
    2211     }
    2212 
    2213     /*
    2214      * Pass it on to the common library loader.
    2215      */
    2216     return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);
    2217 }
    2218 
    2219 
    2220 SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
    2221 {
    2222     LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
    2223 
    2224     /*
    2225      * Validate input.
    2226      */
    2227     RTErrInfoClear(pErrInfo);
    2228     AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
    2229     *phLdrMod = NIL_RTLDRMOD;
    2230     AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
    2231     AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
    2232 
    2233     /*
    2234      * Check the filename.
    2235      */
    2236     size_t cchFilename = strlen(pszFilename);
    2237     AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
    2238 
    2239     const char *pszExt = "";
    2240     size_t cchExt = 0;
    2241     if (!RTPathHasSuffix(pszFilename))
    2242     {
    2243         pszExt = RTLdrGetSuff();
    2244         cchExt = strlen(pszExt);
    2245     }
    2246 
    2247     /*
    2248      * Construct the private arch path and check if the file exists.
    2249      */
    2250     char szPath[RTPATH_MAX];
    2251     int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
    2252     AssertRCReturn(rc, rc);
    2253 
    2254     char *psz = strchr(szPath, '\0');
    2255     *psz++ = RTPATH_SLASH;
    2256     memcpy(psz, pszFilename, cchFilename);
    2257     psz += cchFilename;
    2258     memcpy(psz, pszExt, cchExt + 1);
    2259 
    2260     if (!RTPathExists(szPath))
    2261     {
    2262         LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
    2263         return VERR_FILE_NOT_FOUND;
    2264     }
    2265 
    2266     /*
    2267      * Pass it on to SUPR3HardenedLdrLoad.
    2268      */
    2269     rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);
    2270 
    2271     LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
    2272     return rc;
    2273 }
    2274 
    2275 
    2276 SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
    2277 {
    2278     /*
    2279      * Validate input.
    2280      */
    2281     RTErrInfoClear(pErrInfo);
    2282     AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
    2283     *phLdrMod = NIL_RTLDRMOD;
    2284     AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
    2285     AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);
    2286 
    2287 #ifdef VBOX_WITH_HARDENING
    2288     /*
    2289      * Verify the image file.
    2290      */
    2291     int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
    2292     if (RT_FAILURE(rc))
    2293     {
    2294         if (!RTErrInfoIsSet(pErrInfo))
    2295             LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
    2296         return rc;
    2297     }
    2298 #endif
    2299 
    2300     /*
    2301      * Try load it.
    2302      */
    2303     return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);
    23041607}
    23051608
     
    23221625
    23231626    /* fake */
    2324     if (RT_UNLIKELY(g_u32FakeMode))
     1627    if (RT_UNLIKELY(g_uSupFakeMode))
    23251628        return VINF_SUCCESS;
    23261629
     
    23501653{
    23511654    /* fake */
    2352     if (RT_UNLIKELY(g_u32FakeMode))
     1655    if (RT_UNLIKELY(g_uSupFakeMode))
    23531656        return VINF_SUCCESS;
    23541657
     
    23751678{
    23761679    /* fake */
    2377     if (RT_UNLIKELY(g_u32FakeMode))
     1680    if (RT_UNLIKELY(g_uSupFakeMode))
    23781681        return VINF_SUCCESS;
    23791682
     
    23981701{
    23991702    /* fake */
    2400     if (RT_UNLIKELY(g_u32FakeMode))
     1703    if (RT_UNLIKELY(g_uSupFakeMode))
    24011704    {
    24021705        *piRetVal = -1;
     
    26241927     * Fake out.
    26251928     */
    2626     if (RT_UNLIKELY(g_u32FakeMode))
     1929    if (RT_UNLIKELY(g_uSupFakeMode))
    26271930        return VINF_SUCCESS;
    26281931
     
    27082011     * Fake out.
    27092012     */
    2710     if (RT_UNLIKELY(g_u32FakeMode))
     2013    if (RT_UNLIKELY(g_uSupFakeMode))
    27112014        return VINF_SUCCESS;
    27122015
     
    27422045}
    27432046
     2047
     2048SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp)
     2049{
     2050    SUPMSRPROBER  Req;
     2051    Req.Hdr.u32Cookie           = g_u32Cookie;
     2052    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
     2053    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
     2054    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
     2055    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
     2056    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
     2057
     2058    Req.u.In.enmOp              = SUPMSRPROBEROP_READ;
     2059    Req.u.In.uMsr               = uMsr;
     2060    Req.u.In.idCpu              = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
     2061
     2062    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
     2063    if (RT_SUCCESS(rc))
     2064        rc = Req.Hdr.rc;
     2065    if (RT_SUCCESS(rc))
     2066    {
     2067        if (puValue)
     2068            *puValue = Req.u.Out.uResults.Read.uValue;
     2069        if (pfGp)
     2070            *pfGp    = Req.u.Out.uResults.Read.fGp;
     2071    }
     2072
     2073    return rc;
     2074}
     2075
     2076
     2077SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp)
     2078{
     2079    SUPMSRPROBER  Req;
     2080    Req.Hdr.u32Cookie           = g_u32Cookie;
     2081    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
     2082    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
     2083    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
     2084    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
     2085    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
     2086
     2087    Req.u.In.enmOp                  = SUPMSRPROBEROP_WRITE;
     2088    Req.u.In.uMsr                   = uMsr;
     2089    Req.u.In.idCpu                  = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
     2090    Req.u.In.uArgs.Write.uToWrite   = uValue;
     2091
     2092    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
     2093    if (RT_SUCCESS(rc))
     2094        rc = Req.Hdr.rc;
     2095    if (RT_SUCCESS(rc) && pfGp)
     2096        *pfGp = Req.u.Out.uResults.Write.fGp;
     2097
     2098    return rc;
     2099}
     2100
     2101
     2102SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
     2103                                    PSUPMSRPROBERMODIFYRESULT pResult)
     2104{
     2105    return SUPR3MsrProberModifyEx(uMsr, idCpu, fAndMask, fOrMask, false /*fFaster*/, pResult);
     2106}
     2107
     2108
     2109SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
     2110                                      PSUPMSRPROBERMODIFYRESULT pResult)
     2111{
     2112    SUPMSRPROBER  Req;
     2113    Req.Hdr.u32Cookie           = g_u32Cookie;
     2114    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
     2115    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
     2116    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
     2117    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
     2118    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
     2119
     2120    Req.u.In.enmOp                  = fFaster ? SUPMSRPROBEROP_MODIFY_FASTER : SUPMSRPROBEROP_MODIFY;
     2121    Req.u.In.uMsr                   = uMsr;
     2122    Req.u.In.idCpu                  = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
     2123    Req.u.In.uArgs.Modify.fAndMask  = fAndMask;
     2124    Req.u.In.uArgs.Modify.fOrMask   = fOrMask;
     2125
     2126    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
     2127    if (RT_SUCCESS(rc))
     2128        rc = Req.Hdr.rc;
     2129    if (RT_SUCCESS(rc))
     2130        *pResult = Req.u.Out.uResults.Modify;
     2131
     2132    return rc;
     2133}
     2134
  • trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h

    r49211 r49634  
    280280*   Global Variables                                                           *
    281281*******************************************************************************/
    282 extern DECLHIDDEN(uint32_t)     g_u32Cookie;
    283 extern DECLHIDDEN(uint32_t)     g_u32SessionCookie;
    284 extern DECLHIDDEN(SUPLIBDATA)   g_supLibData;
     282extern DECLHIDDEN(uint32_t)             g_u32Cookie;
     283extern DECLHIDDEN(uint32_t)             g_u32SessionCookie;
     284extern DECLHIDDEN(SUPLIBDATA)           g_supLibData;
     285extern DECLHIDDEN(uint32_t)             g_uSupFakeMode;
     286extern DECLHIDDEN(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPageR0;
     287#ifdef ___SUPDrvIOC_h___
     288extern DECLHIDDEN(PSUPQUERYFUNCS)       g_pSupFunctions;
     289#endif
    285290
    286291
  • trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp

    r49620 r49634  
    11/* $Id$ */
    22/** @file
    3  * VirtualBox Support Library - Common code.
     3 * VirtualBox Support Library - Loader related bits.
    44 */
    55
     
    6868#include <iprt/x86.h>
    6969
     70#include "SUPDrvIOC.h"
    7071#include "SUPLibInternal.h"
    71 #include "SUPDrvIOC.h"
    7272
    7373
     
    8989*   Global Variables                                                           *
    9090*******************************************************************************/
    91 /** Init counter. */
    92 static uint32_t                 g_cInits = 0;
    93 /** Whether we've been preinitied. */
    94 static bool                     g_fPreInited = false;
    95 /** The SUPLib instance data.
    96  * Well, at least parts of it, specifically the parts that are being handed over
    97  * via the pre-init mechanism from the hardened executable stub.  */
    98 SUPLIBDATA                      g_supLibData =
    99 {
    100     /*.hDevice              = */    SUP_HDEVICE_NIL,
    101     /*.fUnrestricted        = */    true
    102 #if   defined(RT_OS_DARWIN)
    103     ,/* .uConnection        = */    NULL
    104 #elif defined(RT_OS_LINUX)
    105     ,/* .fSysMadviseWorks   = */    false
    106 #endif
    107 };
    108 
    109 /** Pointer to the Global Information Page.
    110  *
    111  * This pointer is valid as long as SUPLib has a open session. Anyone using
    112  * the page must treat this pointer as highly volatile and not trust it beyond
    113  * one transaction.
    114  *
    115  * @todo This will probably deserve it's own session or some other good solution...
    116  */
    117 DECLEXPORT(PSUPGLOBALINFOPAGE)  g_pSUPGlobalInfoPage;
    118 /** Address of the ring-0 mapping of the GIP. */
    119 static PSUPGLOBALINFOPAGE       g_pSUPGlobalInfoPageR0;
    120 /** The physical address of the GIP. */
    121 static RTHCPHYS                 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
    122 
    123 /** The negotiated cookie. */
    124 uint32_t                        g_u32Cookie = 0;
    125 /** The negotiated session cookie. */
    126 uint32_t                        g_u32SessionCookie;
    127 /** Session handle. */
    128 PSUPDRVSESSION                  g_pSession;
    129 /** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
    130 static PSUPQUERYFUNCS           g_pFunctions;
    131 
    13291/** VMMR0 Load Address. */
    13392static RTR0PTR                  g_pvVMMR0 = NIL_RTR0PTR;
    134 /** PAGE_ALLOC_EX sans kernel mapping support indicator. */
    135 static bool                     g_fSupportsPageAllocNoKernel = true;
    136 /** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
    137 static uint32_t                 g_u32FakeMode = ~0;
    13893
    13994
     
    14196*   Internal Functions                                                         *
    14297*******************************************************************************/
    143 static int supInitFake(PSUPDRVSESSION *ppSession);
    14498static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
    14599static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
    146 
    147 
    148 /** Touch a range of pages. */
    149 DECLINLINE(void) supR3TouchPages(void *pv, size_t cPages)
    150 {
    151     uint32_t volatile *pu32 = (uint32_t volatile *)pv;
    152     while (cPages-- > 0)
    153     {
    154         ASMAtomicCmpXchgU32(pu32, 0, 0);
    155         pu32 += PAGE_SIZE / sizeof(uint32_t);
    156     }
    157 }
    158 
    159 
    160 SUPR3DECL(int) SUPR3Install(void)
    161 {
    162     return suplibOsInstall();
    163 }
    164 
    165 
    166 SUPR3DECL(int) SUPR3Uninstall(void)
    167 {
    168     return suplibOsUninstall();
    169 }
    170 
    171 
    172 DECLEXPORT(int) supR3PreInit(PSUPPREINITDATA pPreInitData, uint32_t fFlags)
    173 {
    174     /*
    175      * The caller is kind of trustworthy, just perform some basic checks.
    176      *
    177      * Note! Do not do any fancy stuff here because IPRT has NOT been
    178      *       initialized at this point.
    179      */
    180     if (!VALID_PTR(pPreInitData))
    181         return VERR_INVALID_POINTER;
    182     if (g_fPreInited || g_cInits > 0)
    183         return VERR_WRONG_ORDER;
    184 
    185     if (    pPreInitData->u32Magic != SUPPREINITDATA_MAGIC
    186         ||  pPreInitData->u32EndMagic != SUPPREINITDATA_MAGIC)
    187         return VERR_INVALID_MAGIC;
    188     if (    !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
    189         &&  pPreInitData->Data.hDevice == SUP_HDEVICE_NIL)
    190         return VERR_INVALID_HANDLE;
    191     if (    (fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
    192         &&  pPreInitData->Data.hDevice != SUP_HDEVICE_NIL)
    193         return VERR_INVALID_PARAMETER;
    194 
    195     /*
    196      * Hand out the data.
    197      */
    198     int rc = supR3HardenedRecvPreInitData(pPreInitData);
    199     if (RT_FAILURE(rc))
    200         return rc;
    201 
    202     /** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */
    203     if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
    204     {
    205         g_supLibData = pPreInitData->Data;
    206         g_fPreInited = true;
    207     }
    208 
    209     return VINF_SUCCESS;
    210 }
    211 
    212 
    213 SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession)
    214 {
    215     /*
    216      * Perform some sanity checks.
    217      * (Got some trouble with compile time member alignment assertions.)
    218      */
    219     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz) & 0x7));
    220     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs) & 0x1f));
    221     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[1]) & 0x1f));
    222     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64NanoTS) & 0x7));
    223     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64TSC) & 0x7));
    224     Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64CpuHz) & 0x7));
    225 
    226     /*
    227      * Check if already initialized.
    228      */
    229     if (ppSession)
    230         *ppSession = g_pSession;
    231     if (g_cInits++ > 0)
    232     {
    233         if (fUnrestricted && !g_supLibData.fUnrestricted)
    234         {
    235             g_cInits--;
    236             if (ppSession)
    237                 *ppSession = NIL_RTR0PTR;
    238             return VERR_VM_DRIVER_NOT_ACCESSIBLE; /** @todo different status code? */
    239         }
    240         return VINF_SUCCESS;
    241     }
    242 
    243     /*
    244      * Check for fake mode.
    245      *
    246      * Fake mode is used when we're doing smoke testing and debugging.
    247      * It's also useful on platforms where we haven't root access or which
    248      * we haven't ported the support driver to.
    249      */
    250     if (g_u32FakeMode == ~0U)
    251     {
    252         const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
    253         if (psz && !strcmp(psz, "fake"))
    254             ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
    255         else
    256             ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
    257     }
    258     if (RT_UNLIKELY(g_u32FakeMode))
    259         return supInitFake(ppSession);
    260 
    261     /*
    262      * Open the support driver.
    263      */
    264     int rc = suplibOsInit(&g_supLibData, g_fPreInited, fUnrestricted);
    265     if (RT_SUCCESS(rc))
    266     {
    267         /*
    268          * Negotiate the cookie.
    269          */
    270         SUPCOOKIE CookieReq;
    271         memset(&CookieReq, 0xff, sizeof(CookieReq));
    272         CookieReq.Hdr.u32Cookie = SUPCOOKIE_INITIAL_COOKIE;
    273         CookieReq.Hdr.u32SessionCookie = RTRandU32();
    274         CookieReq.Hdr.cbIn = SUP_IOCTL_COOKIE_SIZE_IN;
    275         CookieReq.Hdr.cbOut = SUP_IOCTL_COOKIE_SIZE_OUT;
    276         CookieReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    277         CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
    278         strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
    279         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    280         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001a0000
    281                                    ? 0x001a0005
    282                                    : SUPDRV_IOC_VERSION & 0xffff0000;
    283         CookieReq.u.In.u32MinVersion = uMinVersion;
    284         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
    285         if (    RT_SUCCESS(rc)
    286             &&  RT_SUCCESS(CookieReq.Hdr.rc))
    287         {
    288             if (    (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)
    289                 &&  CookieReq.u.Out.u32SessionVersion >= uMinVersion)
    290             {
    291                 /*
    292                  * Query the functions.
    293                  */
    294                 PSUPQUERYFUNCS pFuncsReq = NULL;
    295                 if (g_supLibData.fUnrestricted)
    296                 {
    297                     pFuncsReq = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
    298                     if (pFuncsReq)
    299                     {
    300                         pFuncsReq->Hdr.u32Cookie            = CookieReq.u.Out.u32Cookie;
    301                         pFuncsReq->Hdr.u32SessionCookie     = CookieReq.u.Out.u32SessionCookie;
    302                         pFuncsReq->Hdr.cbIn                 = SUP_IOCTL_QUERY_FUNCS_SIZE_IN;
    303                         pFuncsReq->Hdr.cbOut                = SUP_IOCTL_QUERY_FUNCS_SIZE_OUT(CookieReq.u.Out.cFunctions);
    304                         pFuncsReq->Hdr.fFlags               = SUPREQHDR_FLAGS_DEFAULT;
    305                         pFuncsReq->Hdr.rc                   = VERR_INTERNAL_ERROR;
    306                         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_QUERY_FUNCS(CookieReq.u.Out.cFunctions), pFuncsReq,
    307                                            SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));
    308                         if (RT_SUCCESS(rc))
    309                             rc = pFuncsReq->Hdr.rc;
    310                         if (RT_SUCCESS(rc))
    311                         {
    312                             /*
    313                              * Map the GIP into userspace.
    314                              */
    315                             Assert(!g_pSUPGlobalInfoPage);
    316                             SUPGIPMAP GipMapReq;
    317                             GipMapReq.Hdr.u32Cookie         = CookieReq.u.Out.u32Cookie;
    318                             GipMapReq.Hdr.u32SessionCookie  = CookieReq.u.Out.u32SessionCookie;
    319                             GipMapReq.Hdr.cbIn              = SUP_IOCTL_GIP_MAP_SIZE_IN;
    320                             GipMapReq.Hdr.cbOut             = SUP_IOCTL_GIP_MAP_SIZE_OUT;
    321                             GipMapReq.Hdr.fFlags            = SUPREQHDR_FLAGS_DEFAULT;
    322                             GipMapReq.Hdr.rc                = VERR_INTERNAL_ERROR;
    323                             GipMapReq.u.Out.HCPhysGip       = NIL_RTHCPHYS;
    324                             GipMapReq.u.Out.pGipR0          = NIL_RTR0PTR;
    325                             GipMapReq.u.Out.pGipR3          = NULL;
    326                             rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_MAP, &GipMapReq, SUP_IOCTL_GIP_MAP_SIZE);
    327                             if (RT_SUCCESS(rc))
    328                                 rc = GipMapReq.Hdr.rc;
    329                             if (RT_SUCCESS(rc))
    330                             {
    331                                 /*
    332                                  * Set the GIP globals.
    333                                  */
    334                                 AssertRelease(GipMapReq.u.Out.pGipR3->u32Magic == SUPGLOBALINFOPAGE_MAGIC);
    335                                 AssertRelease(GipMapReq.u.Out.pGipR3->u32Version >= SUPGLOBALINFOPAGE_VERSION);
    336 
    337                                 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipMapReq.u.Out.HCPhysGip);
    338                                 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, GipMapReq.u.Out.pGipR3, NULL);
    339                                 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);
    340                             }
    341                         }
    342                     }
    343                     else
    344                         rc = VERR_NO_MEMORY;
    345                 }
    346 
    347                 if (RT_SUCCESS(rc))
    348                 {
    349                     /*
    350                      * Set the globals and return success.
    351                      */
    352                     g_u32Cookie         = CookieReq.u.Out.u32Cookie;
    353                     g_u32SessionCookie  = CookieReq.u.Out.u32SessionCookie;
    354                     g_pSession          = CookieReq.u.Out.pSession;
    355                     g_pFunctions        = pFuncsReq;
    356                     if (ppSession)
    357                         *ppSession = CookieReq.u.Out.pSession;
    358                     return VINF_SUCCESS;
    359                 }
    360 
    361                 /* bailout */
    362                 RTMemFree(pFuncsReq);
    363             }
    364             else
    365             {
    366                 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
    367                         CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, uMinVersion));
    368                 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
    369             }
    370         }
    371         else
    372         {
    373             if (RT_SUCCESS(rc))
    374             {
    375                 rc = CookieReq.Hdr.rc;
    376                 LogRel(("Support driver version mismatch: DriverVersion=%#x ClientVersion=%#x rc=%Rrc\n",
    377                         CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, rc));
    378                 if (rc != VERR_VM_DRIVER_VERSION_MISMATCH)
    379                     rc = VERR_VM_DRIVER_VERSION_MISMATCH;
    380             }
    381             else
    382             {
    383                 /* for pre 0x00060000 drivers */
    384                 LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));
    385                 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
    386             }
    387         }
    388 
    389         suplibOsTerm(&g_supLibData);
    390     }
    391     g_cInits--;
    392 
    393     return rc;
    394 }
    395 
    396 
    397 SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession)
    398 {
    399     return SUPR3InitEx(true, ppSession);
    400 }
    401 
    402 /**
    403  * Fake mode init.
    404  */
    405 static int supInitFake(PSUPDRVSESSION *ppSession)
    406 {
    407     Log(("SUP: Fake mode!\n"));
    408     static const SUPFUNC s_aFakeFunctions[] =
    409     {
    410         /* name                                     function */
    411         { "SUPR0AbsIs64bit",                        0 },
    412         { "SUPR0Abs64bitKernelCS",                  0 },
    413         { "SUPR0Abs64bitKernelSS",                  0 },
    414         { "SUPR0Abs64bitKernelDS",                  0 },
    415         { "SUPR0AbsKernelCS",                       8 },
    416         { "SUPR0AbsKernelSS",                       16 },
    417         { "SUPR0AbsKernelDS",                       16 },
    418         { "SUPR0AbsKernelES",                       16 },
    419         { "SUPR0AbsKernelFS",                       24 },
    420         { "SUPR0AbsKernelGS",                       32 },
    421         { "SUPR0ComponentRegisterFactory",          0xefeefffd },
    422         { "SUPR0ComponentDeregisterFactory",        0xefeefffe },
    423         { "SUPR0ComponentQueryFactory",             0xefeeffff },
    424         { "SUPR0ObjRegister",                       0xefef0000 },
    425         { "SUPR0ObjAddRef",                         0xefef0001 },
    426         { "SUPR0ObjAddRefEx",                       0xefef0001 },
    427         { "SUPR0ObjRelease",                        0xefef0002 },
    428         { "SUPR0ObjVerifyAccess",                   0xefef0003 },
    429         { "SUPR0LockMem",                           0xefef0004 },
    430         { "SUPR0UnlockMem",                         0xefef0005 },
    431         { "SUPR0ContAlloc",                         0xefef0006 },
    432         { "SUPR0ContFree",                          0xefef0007 },
    433         { "SUPR0MemAlloc",                          0xefef0008 },
    434         { "SUPR0MemGetPhys",                        0xefef0009 },
    435         { "SUPR0MemFree",                           0xefef000a },
    436         { "SUPR0Printf",                            0xefef000b },
    437         { "SUPR0GetPagingMode",                     0xefef000c },
    438         { "SUPR0EnableVTx",                         0xefef000e },
    439         { "RTMemAlloc",                             0xefef000f },
    440         { "RTMemAllocZ",                            0xefef0010 },
    441         { "RTMemFree",                              0xefef0011 },
    442         { "RTR0MemObjAddress",                      0xefef0012 },
    443         { "RTR0MemObjAddressR3",                    0xefef0013 },
    444         { "RTR0MemObjAllocPage",                    0xefef0014 },
    445         { "RTR0MemObjAllocPhysNC",                  0xefef0015 },
    446         { "RTR0MemObjAllocLow",                     0xefef0016 },
    447         { "RTR0MemObjEnterPhys",                    0xefef0017 },
    448         { "RTR0MemObjFree",                         0xefef0018 },
    449         { "RTR0MemObjGetPagePhysAddr",              0xefef0019 },
    450         { "RTR0MemObjMapUser",                      0xefef001a },
    451         { "RTR0MemObjMapKernel",                    0xefef001b },
    452         { "RTR0MemObjMapKernelEx",                  0xefef001c },
    453         { "RTMpGetArraySize",                       0xefef001c },
    454         { "RTProcSelf",                             0xefef001d },
    455         { "RTR0ProcHandleSelf",                     0xefef001e },
    456         { "RTSemEventCreate",                       0xefef001f },
    457         { "RTSemEventSignal",                       0xefef0020 },
    458         { "RTSemEventWait",                         0xefef0021 },
    459         { "RTSemEventWaitNoResume",                 0xefef0022 },
    460         { "RTSemEventDestroy",                      0xefef0023 },
    461         { "RTSemEventMultiCreate",                  0xefef0024 },
    462         { "RTSemEventMultiSignal",                  0xefef0025 },
    463         { "RTSemEventMultiReset",                   0xefef0026 },
    464         { "RTSemEventMultiWait",                    0xefef0027 },
    465         { "RTSemEventMultiWaitNoResume",            0xefef0028 },
    466         { "RTSemEventMultiDestroy",                 0xefef0029 },
    467         { "RTSemFastMutexCreate",                   0xefef002a },
    468         { "RTSemFastMutexDestroy",                  0xefef002b },
    469         { "RTSemFastMutexRequest",                  0xefef002c },
    470         { "RTSemFastMutexRelease",                  0xefef002d },
    471         { "RTSpinlockCreate",                       0xefef002e },
    472         { "RTSpinlockDestroy",                      0xefef002f },
    473         { "RTSpinlockAcquire",                      0xefef0030 },
    474         { "RTSpinlockRelease",                      0xefef0031 },
    475         { "RTSpinlockAcquireNoInts",                0xefef0032 },
    476         { "RTSpinlockReleaseNoInts",                0xefef0033 },
    477         { "RTTimeNanoTS",                           0xefef0034 },
    478         { "RTTimeMillieTS",                         0xefef0035 },
    479         { "RTTimeSystemNanoTS",                     0xefef0036 },
    480         { "RTTimeSystemMillieTS",                   0xefef0037 },
    481         { "RTThreadNativeSelf",                     0xefef0038 },
    482         { "RTThreadSleep",                          0xefef0039 },
    483         { "RTThreadYield",                          0xefef003a },
    484         { "RTTimerCreate",                          0xefef003a },
    485         { "RTTimerCreateEx",                        0xefef003a },
    486         { "RTTimerDestroy",                         0xefef003a },
    487         { "RTTimerStart",                           0xefef003a },
    488         { "RTTimerStop",                            0xefef003a },
    489         { "RTTimerChangeInterval",                  0xefef003a },
    490         { "RTTimerGetSystemGranularity",            0xefef003a },
    491         { "RTTimerRequestSystemGranularity",        0xefef003a },
    492         { "RTTimerReleaseSystemGranularity",        0xefef003a },
    493         { "RTTimerCanDoHighResolution",             0xefef003a },
    494         { "RTLogDefaultInstance",                   0xefef003b },
    495         { "RTLogRelDefaultInstance",                0xefef003c },
    496         { "RTLogSetDefaultInstanceThread",          0xefef003d },
    497         { "RTLogLogger",                            0xefef003e },
    498         { "RTLogLoggerEx",                          0xefef003f },
    499         { "RTLogLoggerExV",                         0xefef0040 },
    500         { "RTAssertMsg1",                           0xefef0041 },
    501         { "RTAssertMsg2",                           0xefef0042 },
    502         { "RTAssertMsg2V",                          0xefef0043 },
    503         { "SUPR0QueryVTCaps",                       0xefef0044 },
    504     };
    505 
    506     /* fake r0 functions. */
    507     g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
    508     if (g_pFunctions)
    509     {
    510         g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
    511         memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
    512         g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
    513         if (ppSession)
    514             *ppSession = g_pSession;
    515 
    516         /* fake the GIP. */
    517         g_pSUPGlobalInfoPage = (PSUPGLOBALINFOPAGE)RTMemPageAllocZ(PAGE_SIZE);
    518         if (g_pSUPGlobalInfoPage)
    519         {
    520             g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;
    521             g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;
    522             /* the page is supposed to be invalid, so don't set the magic. */
    523             return VINF_SUCCESS;
    524         }
    525 
    526         RTMemFree(g_pFunctions);
    527         g_pFunctions = NULL;
    528     }
    529     return VERR_NO_MEMORY;
    530 }
    531 
    532 
    533 SUPR3DECL(int) SUPR3Term(bool fForced)
    534 {
    535     /*
    536      * Verify state.
    537      */
    538     AssertMsg(g_cInits > 0, ("SUPR3Term() is called before SUPR3Init()!\n"));
    539     if (g_cInits == 0)
    540         return VERR_WRONG_ORDER;
    541     if (g_cInits == 1 || fForced)
    542     {
    543         /*
    544          * NULL the GIP pointer.
    545          */
    546         if (g_pSUPGlobalInfoPage)
    547         {
    548             ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPage);
    549             ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPageR0);
    550             ASMAtomicWriteSize(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);
    551             /* just a little safe guard against threads using the page. */
    552             RTThreadSleep(50);
    553         }
    554 
    555         /*
    556          * Close the support driver.
    557          */
    558         int rc = suplibOsTerm(&g_supLibData);
    559         if (rc)
    560             return rc;
    561 
    562         g_u32Cookie         = 0;
    563         g_u32SessionCookie  = 0;
    564         g_cInits            = 0;
    565     }
    566     else
    567         g_cInits--;
    568 
    569     return 0;
    570 }
    571 
    572 
    573 SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)
    574 {
    575     /* fake */
    576     if (RT_UNLIKELY(g_u32FakeMode))
    577 #ifdef RT_ARCH_AMD64
    578         return SUPPAGINGMODE_AMD64_GLOBAL_NX;
    579 #else
    580         return SUPPAGINGMODE_32_BIT_GLOBAL;
    581 #endif
    582 
    583     /*
    584      * Issue IOCtl to the SUPDRV kernel module.
    585      */
    586     SUPGETPAGINGMODE Req;
    587     Req.Hdr.u32Cookie = g_u32Cookie;
    588     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    589     Req.Hdr.cbIn = SUP_IOCTL_GET_PAGING_MODE_SIZE_IN;
    590     Req.Hdr.cbOut = SUP_IOCTL_GET_PAGING_MODE_SIZE_OUT;
    591     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    592     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    593     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);
    594     if (    RT_FAILURE(rc)
    595         ||  RT_FAILURE(Req.Hdr.rc))
    596     {
    597         LogRel(("SUPR3GetPagingMode: %Rrc %Rrc\n", rc, Req.Hdr.rc));
    598         Req.u.Out.enmMode = SUPPAGINGMODE_INVALID;
    599     }
    600 
    601     return Req.u.Out.enmMode;
    602 }
    603 
    604 
    605 /**
    606  * For later.
    607  */
    608 static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
    609 {
    610     AssertMsgFailed(("%d\n", uOperation)); NOREF(pVMR0); NOREF(uOperation); NOREF(u64Arg); NOREF(pReqHdr);
    611     return VERR_NOT_SUPPORTED;
    612 }
    613 
    614 
    615 SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
    616 {
    617     NOREF(pVMR0);
    618     if (RT_LIKELY(uOperation == SUP_VMMR0_DO_RAW_RUN))
    619         return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_RAW_RUN, idCpu);
    620     if (RT_LIKELY(uOperation == SUP_VMMR0_DO_HM_RUN))
    621         return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_HM_RUN, idCpu);
    622     if (RT_LIKELY(uOperation == SUP_VMMR0_DO_NOP))
    623         return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_NOP, idCpu);
    624 
    625     AssertMsgFailed(("%#x\n", uOperation));
    626     return VERR_INTERNAL_ERROR;
    627 }
    628 
    629 
    630 SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
    631 {
    632     /*
    633      * The following operations don't belong here.
    634      */
    635     AssertMsgReturn(    uOperation != SUP_VMMR0_DO_RAW_RUN
    636                     &&  uOperation != SUP_VMMR0_DO_HM_RUN
    637                     &&  uOperation != SUP_VMMR0_DO_NOP,
    638                     ("%#x\n", uOperation),
    639                     VERR_INTERNAL_ERROR);
    640 
    641     /* fake */
    642     if (RT_UNLIKELY(g_u32FakeMode))
    643         return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
    644 
    645     int rc;
    646     if (!pReqHdr)
    647     {
    648         /* no data. */
    649         SUPCALLVMMR0 Req;
    650         Req.Hdr.u32Cookie = g_u32Cookie;
    651         Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    652         Req.Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(0);
    653         Req.Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(0);
    654         Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    655         Req.Hdr.rc = VERR_INTERNAL_ERROR;
    656         Req.u.In.pVMR0 = pVMR0;
    657         Req.u.In.idCpu = idCpu;
    658         Req.u.In.uOperation = uOperation;
    659         Req.u.In.u64Arg = u64Arg;
    660         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(0), &Req, SUP_IOCTL_CALL_VMMR0_SIZE(0));
    661         if (RT_SUCCESS(rc))
    662             rc = Req.Hdr.rc;
    663     }
    664     else if (SUP_IOCTL_CALL_VMMR0_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
    665     {
    666         AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
    667         AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
    668         const size_t cbReq = pReqHdr->cbReq;
    669 
    670         PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)alloca(SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
    671         pReq->Hdr.u32Cookie = g_u32Cookie;
    672         pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    673         pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(cbReq);
    674         pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(cbReq);
    675         pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    676         pReq->Hdr.rc = VERR_INTERNAL_ERROR;
    677         pReq->u.In.pVMR0 = pVMR0;
    678         pReq->u.In.idCpu = idCpu;
    679         pReq->u.In.uOperation = uOperation;
    680         pReq->u.In.u64Arg = u64Arg;
    681         memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
    682         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
    683         if (RT_SUCCESS(rc))
    684             rc = pReq->Hdr.rc;
    685         memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
    686     }
    687     else if (pReqHdr->cbReq <= _512K)
    688     {
    689         AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
    690         AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);
    691         const size_t cbReq = pReqHdr->cbReq;
    692 
    693         PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)RTMemTmpAlloc(SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));
    694         pReq->Hdr.u32Cookie         = g_u32Cookie;
    695         pReq->Hdr.u32SessionCookie  = g_u32SessionCookie;
    696         pReq->Hdr.cbIn              = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_IN(cbReq);
    697         pReq->Hdr.cbOut             = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_OUT(cbReq);
    698         pReq->Hdr.fFlags            = SUPREQHDR_FLAGS_DEFAULT;
    699         pReq->Hdr.rc                = VERR_INTERNAL_ERROR;
    700         pReq->u.In.pVMR0            = pVMR0;
    701         pReq->u.In.idCpu            = idCpu;
    702         pReq->u.In.uOperation       = uOperation;
    703         pReq->u.In.u64Arg           = u64Arg;
    704         memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
    705         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0_BIG, pReq, SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));
    706         if (RT_SUCCESS(rc))
    707             rc = pReq->Hdr.rc;
    708         memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
    709         RTMemTmpFree(pReq);
    710     }
    711     else
    712         AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_OUT_OF_RANGE);
    713     return rc;
    714 }
    715 
    716 
    717 SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg)
    718 {
    719     /*
    720      * The following operations don't belong here.
    721      */
    722     AssertMsgReturn(    uOperation != SUP_VMMR0_DO_RAW_RUN
    723                     &&  uOperation != SUP_VMMR0_DO_HM_RUN
    724                     &&  uOperation != SUP_VMMR0_DO_NOP,
    725                     ("%#x\n", uOperation),
    726                     VERR_INTERNAL_ERROR);
    727     return SUPR3CallVMMR0Ex(pVMR0, idCpu, uOperation, (uintptr_t)pvArg, NULL);
    728 }
    729 
    730 
    731 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)
    732 {
    733     if (RT_UNLIKELY(g_u32FakeMode))
    734         return VINF_SUCCESS;
    735 
    736     SUPSETVMFORFAST Req;
    737     Req.Hdr.u32Cookie = g_u32Cookie;
    738     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    739     Req.Hdr.cbIn = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_IN;
    740     Req.Hdr.cbOut = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_OUT;
    741     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    742     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    743     Req.u.In.pVMR0 = pVMR0;
    744     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);
    745     if (RT_SUCCESS(rc))
    746         rc = Req.Hdr.rc;
    747     return rc;
    748 }
    749 
    750 
    751 SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
    752 {
    753     AssertReturn(cchService < RT_SIZEOFMEMB(SUPCALLSERVICE, u.In.szName), VERR_INVALID_PARAMETER);
    754     Assert(strlen(pszService) == cchService);
    755 
    756     /* fake */
    757     if (RT_UNLIKELY(g_u32FakeMode))
    758         return VERR_NOT_SUPPORTED;
    759 
    760     int rc;
    761     if (!pReqHdr)
    762     {
    763         /* no data. */
    764         SUPCALLSERVICE Req;
    765         Req.Hdr.u32Cookie = g_u32Cookie;
    766         Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    767         Req.Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(0);
    768         Req.Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(0);
    769         Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    770         Req.Hdr.rc = VERR_INTERNAL_ERROR;
    771         memcpy(Req.u.In.szName, pszService, cchService);
    772         Req.u.In.szName[cchService] = '\0';
    773         Req.u.In.uOperation = uOperation;
    774         Req.u.In.u64Arg = u64Arg;
    775         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(0), &Req, SUP_IOCTL_CALL_SERVICE_SIZE(0));
    776         if (RT_SUCCESS(rc))
    777             rc = Req.Hdr.rc;
    778     }
    779     else if (SUP_IOCTL_CALL_SERVICE_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */
    780     {
    781         AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);
    782         AssertReturn(pReqHdr->u32Magic == SUPR0SERVICEREQHDR_MAGIC, VERR_INVALID_MAGIC);
    783         const size_t cbReq = pReqHdr->cbReq;
    784 
    785         PSUPCALLSERVICE pReq = (PSUPCALLSERVICE)alloca(SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
    786         pReq->Hdr.u32Cookie = g_u32Cookie;
    787         pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    788         pReq->Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(cbReq);
    789         pReq->Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(cbReq);
    790         pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    791         pReq->Hdr.rc = VERR_INTERNAL_ERROR;
    792         memcpy(pReq->u.In.szName, pszService, cchService);
    793         pReq->u.In.szName[cchService] = '\0';
    794         pReq->u.In.uOperation = uOperation;
    795         pReq->u.In.u64Arg = u64Arg;
    796         memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);
    797         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
    798         if (RT_SUCCESS(rc))
    799             rc = pReq->Hdr.rc;
    800         memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);
    801     }
    802     else /** @todo may have to remove the size limits one this request... */
    803         AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);
    804     return rc;
    805 }
    806 
    807 
    808 /**
    809  * Worker for the SUPR3Logger* APIs.
    810  *
    811  * @returns VBox status code.
    812  * @param   enmWhich    Which logger.
    813  * @param   fWhat       What to do with the logger.
    814  * @param   pszFlags    The flags settings.
    815  * @param   pszGroups   The groups settings.
    816  * @param   pszDest     The destination specificier.
    817  */
    818 static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)
    819 {
    820     uint32_t const cchFlags  = pszFlags  ? (uint32_t)strlen(pszFlags)  : 0;
    821     uint32_t const cchGroups = pszGroups ? (uint32_t)strlen(pszGroups) : 0;
    822     uint32_t const cchDest   = pszDest   ? (uint32_t)strlen(pszDest)   : 0;
    823     uint32_t const cbStrTab  = cchFlags  + !!cchFlags
    824                              + cchGroups + !!cchGroups
    825                              + cchDest   + !!cchDest
    826                              + (!cchFlags && !cchGroups && !cchDest);
    827 
    828     PSUPLOGGERSETTINGS pReq  = (PSUPLOGGERSETTINGS)alloca(SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
    829     pReq->Hdr.u32Cookie = g_u32Cookie;
    830     pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    831     pReq->Hdr.cbIn  = SUP_IOCTL_LOGGER_SETTINGS_SIZE_IN(cbStrTab);
    832     pReq->Hdr.cbOut = SUP_IOCTL_LOGGER_SETTINGS_SIZE_OUT;
    833     pReq->Hdr.fFlags= SUPREQHDR_FLAGS_DEFAULT;
    834     pReq->Hdr.rc    = VERR_INTERNAL_ERROR;
    835     switch (enmWhich)
    836     {
    837         case SUPLOGGER_DEBUG:   pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_DEBUG; break;
    838         case SUPLOGGER_RELEASE: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_RELEASE; break;
    839         default:
    840             return VERR_INVALID_PARAMETER;
    841     }
    842     pReq->u.In.fWhat = fWhat;
    843 
    844     uint32_t off = 0;
    845     if (cchFlags)
    846     {
    847         pReq->u.In.offFlags = off;
    848         memcpy(&pReq->u.In.szStrings[off], pszFlags, cchFlags + 1);
    849         off += cchFlags + 1;
    850     }
    851     else
    852         pReq->u.In.offFlags = cbStrTab - 1;
    853 
    854     if (cchGroups)
    855     {
    856         pReq->u.In.offGroups = off;
    857         memcpy(&pReq->u.In.szStrings[off], pszGroups, cchGroups + 1);
    858         off += cchGroups + 1;
    859     }
    860     else
    861         pReq->u.In.offGroups = cbStrTab - 1;
    862 
    863     if (cchDest)
    864     {
    865         pReq->u.In.offDestination = off;
    866         memcpy(&pReq->u.In.szStrings[off], pszDest, cchDest + 1);
    867         off += cchDest + 1;
    868     }
    869     else
    870         pReq->u.In.offDestination = cbStrTab - 1;
    871 
    872     if (!off)
    873     {
    874         pReq->u.In.szStrings[0] = '\0';
    875         off++;
    876     }
    877     Assert(off == cbStrTab);
    878     Assert(pReq->u.In.szStrings[cbStrTab - 1] == '\0');
    879 
    880 
    881     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
    882     if (RT_SUCCESS(rc))
    883         rc = pReq->Hdr.rc;
    884     return rc;
    885 }
    886 
    887 
    888 SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
    889 {
    890     return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);
    891 }
    892 
    893 
    894 SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
    895 {
    896     return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_CREATE, pszFlags, pszGroups, pszDest);
    897 }
    898 
    899 
    900 SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich)
    901 {
    902     return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_DESTROY, NULL, NULL, NULL);
    903 }
    904 
    905 
    906 SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages)
    907 {
    908     /*
    909      * Validate.
    910      */
    911     AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
    912     *ppvPages = NULL;
    913     AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
    914 
    915     /*
    916      * Call OS specific worker.
    917      */
    918     return suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
    919 }
    920 
    921 
    922 SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages)
    923 {
    924     /*
    925      * Validate.
    926      */
    927     AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
    928     AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
    929 
    930     /*
    931      * Call OS specific worker.
    932      */
    933     return suplibOsPageFree(&g_supLibData, pvPages, cPages);
    934 }
    935 
    936 
    937 /**
    938  * Locks down the physical memory backing a virtual memory
    939  * range in the current process.
    940  *
    941  * @returns VBox status code.
    942  * @param   pvStart         Start of virtual memory range.
    943  *                          Must be page aligned.
    944  * @param   cPages          Number of pages.
    945  * @param   paPages         Where to store the physical page addresses returned.
    946  *                          On entry this will point to an array of with cbMemory >> PAGE_SHIFT entries.
    947  */
    948 SUPR3DECL(int) supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages)
    949 {
    950     /*
    951      * Validate.
    952      */
    953     AssertPtr(pvStart);
    954     AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
    955     AssertPtr(paPages);
    956 
    957     /* fake */
    958     if (RT_UNLIKELY(g_u32FakeMode))
    959     {
    960         RTHCPHYS    Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
    961         size_t      iPage = cPages;
    962         while (iPage-- > 0)
    963             paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
    964         return VINF_SUCCESS;
    965     }
    966 
    967     /*
    968      * Issue IOCtl to the SUPDRV kernel module.
    969      */
    970     int rc;
    971     PSUPPAGELOCK pReq = (PSUPPAGELOCK)RTMemTmpAllocZ(SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
    972     if (RT_LIKELY(pReq))
    973     {
    974         pReq->Hdr.u32Cookie = g_u32Cookie;
    975         pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    976         pReq->Hdr.cbIn = SUP_IOCTL_PAGE_LOCK_SIZE_IN;
    977         pReq->Hdr.cbOut = SUP_IOCTL_PAGE_LOCK_SIZE_OUT(cPages);
    978         pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
    979         pReq->Hdr.rc = VERR_INTERNAL_ERROR;
    980         pReq->u.In.pvR3 = pvStart;
    981         pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
    982         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_LOCK, pReq, SUP_IOCTL_PAGE_LOCK_SIZE(cPages));
    983         if (RT_SUCCESS(rc))
    984             rc = pReq->Hdr.rc;
    985         if (RT_SUCCESS(rc))
    986         {
    987             for (uint32_t iPage = 0; iPage < cPages; iPage++)
    988             {
    989                 paPages[iPage].uReserved = 0;
    990                 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
    991                 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
    992             }
    993         }
    994         RTMemTmpFree(pReq);
    995     }
    996     else
    997         rc = VERR_NO_TMP_MEMORY;
    998 
    999     return rc;
    1000 }
    1001 
    1002 
    1003 /**
    1004  * Releases locked down pages.
    1005  *
    1006  * @returns VBox status code.
    1007  * @param   pvStart         Start of virtual memory range previously locked
    1008  *                          down by SUPPageLock().
    1009  */
    1010 SUPR3DECL(int) supR3PageUnlock(void *pvStart)
    1011 {
    1012     /*
    1013      * Validate.
    1014      */
    1015     AssertPtr(pvStart);
    1016     AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
    1017 
    1018     /* fake */
    1019     if (RT_UNLIKELY(g_u32FakeMode))
    1020         return VINF_SUCCESS;
    1021 
    1022     /*
    1023      * Issue IOCtl to the SUPDRV kernel module.
    1024      */
    1025     SUPPAGEUNLOCK Req;
    1026     Req.Hdr.u32Cookie = g_u32Cookie;
    1027     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1028     Req.Hdr.cbIn = SUP_IOCTL_PAGE_UNLOCK_SIZE_IN;
    1029     Req.Hdr.cbOut = SUP_IOCTL_PAGE_UNLOCK_SIZE_OUT;
    1030     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1031     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1032     Req.u.In.pvR3 = pvStart;
    1033     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_UNLOCK, &Req, SUP_IOCTL_PAGE_UNLOCK_SIZE);
    1034     if (RT_SUCCESS(rc))
    1035         rc = Req.Hdr.rc;
    1036     return rc;
    1037 }
    1038 
    1039 
    1040 /**
    1041  * Fallback for SUPR3PageAllocEx on systems where RTR0MemObjPhysAllocNC isn't
    1042  * supported.
    1043  */
    1044 static int supPagePageAllocNoKernelFallback(size_t cPages, void **ppvPages, PSUPPAGE paPages)
    1045 {
    1046     int rc = suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);
    1047     if (RT_SUCCESS(rc))
    1048     {
    1049         if (!paPages)
    1050             paPages = (PSUPPAGE)alloca(sizeof(paPages[0]) * cPages);
    1051         rc = supR3PageLock(*ppvPages, cPages, paPages);
    1052         if (RT_FAILURE(rc))
    1053             suplibOsPageFree(&g_supLibData, *ppvPages, cPages);
    1054     }
    1055     return rc;
    1056 }
    1057 
    1058 
    1059 SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)
    1060 {
    1061     /*
    1062      * Validate.
    1063      */
    1064     AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
    1065     *ppvPages = NULL;
    1066     AssertPtrNullReturn(pR0Ptr, VERR_INVALID_POINTER);
    1067     if (pR0Ptr)
    1068         *pR0Ptr = NIL_RTR0PTR;
    1069     AssertPtrNullReturn(paPages, VERR_INVALID_POINTER);
    1070     AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
    1071     AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
    1072 
    1073     /* fake */
    1074     if (RT_UNLIKELY(g_u32FakeMode))
    1075     {
    1076         void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
    1077         if (!pv)
    1078             return VERR_NO_MEMORY;
    1079         *ppvPages = pv;
    1080         if (pR0Ptr)
    1081             *pR0Ptr = (RTR0PTR)pv;
    1082         if (paPages)
    1083             for (size_t iPage = 0; iPage < cPages; iPage++)
    1084             {
    1085                 paPages[iPage].uReserved = 0;
    1086                 paPages[iPage].Phys = (iPage + 4321) << PAGE_SHIFT;
    1087                 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
    1088             }
    1089         return VINF_SUCCESS;
    1090     }
    1091 
    1092     /*
    1093      * Use fallback for non-R0 mapping?
    1094      */
    1095     if (    !pR0Ptr
    1096         &&  !g_fSupportsPageAllocNoKernel)
    1097         return supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
    1098 
    1099     /*
    1100      * Issue IOCtl to the SUPDRV kernel module.
    1101      */
    1102     int rc;
    1103     PSUPPAGEALLOCEX pReq = (PSUPPAGEALLOCEX)RTMemTmpAllocZ(SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
    1104     if (pReq)
    1105     {
    1106         pReq->Hdr.u32Cookie = g_u32Cookie;
    1107         pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    1108         pReq->Hdr.cbIn = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_IN;
    1109         pReq->Hdr.cbOut = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_OUT(cPages);
    1110         pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
    1111         pReq->Hdr.rc = VERR_INTERNAL_ERROR;
    1112         pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
    1113         pReq->u.In.fKernelMapping = pR0Ptr != NULL;
    1114         pReq->u.In.fUserMapping = true;
    1115         pReq->u.In.fReserved0 = false;
    1116         pReq->u.In.fReserved1 = false;
    1117         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
    1118         if (RT_SUCCESS(rc))
    1119         {
    1120             rc = pReq->Hdr.rc;
    1121             if (RT_SUCCESS(rc))
    1122             {
    1123                 *ppvPages = pReq->u.Out.pvR3;
    1124                 if (pR0Ptr)
    1125                     *pR0Ptr   = pReq->u.Out.pvR0;
    1126                 if (paPages)
    1127                     for (size_t iPage = 0; iPage < cPages; iPage++)
    1128                     {
    1129                         paPages[iPage].uReserved = 0;
    1130                         paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
    1131                         Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
    1132                     }
    1133 #ifdef RT_OS_DARWIN /* HACK ALERT! */
    1134                 supR3TouchPages(pReq->u.Out.pvR3, cPages);
    1135 #endif
    1136             }
    1137             else if (   rc == VERR_NOT_SUPPORTED
    1138                      && !pR0Ptr)
    1139             {
    1140                 g_fSupportsPageAllocNoKernel = false;
    1141                 rc = supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);
    1142             }
    1143         }
    1144 
    1145         RTMemTmpFree(pReq);
    1146     }
    1147     else
    1148         rc = VERR_NO_TMP_MEMORY;
    1149     return rc;
    1150 
    1151 }
    1152 
    1153 
    1154 SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)
    1155 {
    1156     /*
    1157      * Validate.
    1158      */
    1159     AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
    1160     AssertPtrReturn(pR0Ptr, VERR_INVALID_POINTER);
    1161     Assert(!(off & PAGE_OFFSET_MASK));
    1162     Assert(!(cb & PAGE_OFFSET_MASK) && cb);
    1163     Assert(!fFlags);
    1164     *pR0Ptr = NIL_RTR0PTR;
    1165 
    1166     /* fake */
    1167     if (RT_UNLIKELY(g_u32FakeMode))
    1168         return VERR_NOT_SUPPORTED;
    1169 
    1170     /*
    1171      * Issue IOCtl to the SUPDRV kernel module.
    1172      */
    1173     SUPPAGEMAPKERNEL Req;
    1174     Req.Hdr.u32Cookie = g_u32Cookie;
    1175     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1176     Req.Hdr.cbIn = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_IN;
    1177     Req.Hdr.cbOut = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_OUT;
    1178     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1179     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1180     Req.u.In.pvR3 = pvR3;
    1181     Req.u.In.offSub = off;
    1182     Req.u.In.cbSub = cb;
    1183     Req.u.In.fFlags = fFlags;
    1184     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);
    1185     if (RT_SUCCESS(rc))
    1186         rc = Req.Hdr.rc;
    1187     if (RT_SUCCESS(rc))
    1188         *pR0Ptr = Req.u.Out.pvR0;
    1189     return rc;
    1190 }
    1191 
    1192 
    1193 SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt)
    1194 {
    1195     /*
    1196      * Validate.
    1197      */
    1198     AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
    1199     Assert(!(off & PAGE_OFFSET_MASK));
    1200     Assert(!(cb & PAGE_OFFSET_MASK) && cb);
    1201     AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
    1202 
    1203     /* fake */
    1204     if (RT_UNLIKELY(g_u32FakeMode))
    1205         return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
    1206 
    1207     /*
    1208      * Some OSes can do this from ring-3, so try that before we
    1209      * issue the IOCtl to the SUPDRV kernel module.
    1210      * (Yea, this isn't very nice, but just try get the job done for now.)
    1211      */
    1212 #if !defined(RT_OS_SOLARIS)
    1213     RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
    1214 #endif
    1215 
    1216     SUPPAGEPROTECT Req;
    1217     Req.Hdr.u32Cookie = g_u32Cookie;
    1218     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1219     Req.Hdr.cbIn = SUP_IOCTL_PAGE_PROTECT_SIZE_IN;
    1220     Req.Hdr.cbOut = SUP_IOCTL_PAGE_PROTECT_SIZE_OUT;
    1221     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1222     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1223     Req.u.In.pvR3 = pvR3;
    1224     Req.u.In.pvR0 = R0Ptr;
    1225     Req.u.In.offSub = off;
    1226     Req.u.In.cbSub = cb;
    1227     Req.u.In.fProt = fProt;
    1228     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_PROTECT, &Req, SUP_IOCTL_PAGE_PROTECT_SIZE);
    1229     if (RT_SUCCESS(rc))
    1230         rc = Req.Hdr.rc;
    1231     return rc;
    1232 }
    1233 
    1234 
    1235 SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)
    1236 {
    1237     /*
    1238      * Validate.
    1239      */
    1240     AssertPtrReturn(pvPages, VERR_INVALID_POINTER);
    1241     AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
    1242 
    1243     /* fake */
    1244     if (RT_UNLIKELY(g_u32FakeMode))
    1245     {
    1246         RTMemPageFree(pvPages, cPages * PAGE_SIZE);
    1247         return VINF_SUCCESS;
    1248     }
    1249 
    1250     /*
    1251      * Try normal free first, then if it fails check if we're using the fallback
    1252      * for the allocations without kernel mappings and attempt unlocking it.
    1253      */
    1254     NOREF(cPages);
    1255     SUPPAGEFREE Req;
    1256     Req.Hdr.u32Cookie = g_u32Cookie;
    1257     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1258     Req.Hdr.cbIn = SUP_IOCTL_PAGE_FREE_SIZE_IN;
    1259     Req.Hdr.cbOut = SUP_IOCTL_PAGE_FREE_SIZE_OUT;
    1260     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1261     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1262     Req.u.In.pvR3 = pvPages;
    1263     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_FREE, &Req, SUP_IOCTL_PAGE_FREE_SIZE);
    1264     if (RT_SUCCESS(rc))
    1265     {
    1266         rc = Req.Hdr.rc;
    1267         if (    rc == VERR_INVALID_PARAMETER
    1268             &&  !g_fSupportsPageAllocNoKernel)
    1269         {
    1270             int rc2 = supR3PageUnlock(pvPages);
    1271             if (RT_SUCCESS(rc2))
    1272                 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);
    1273         }
    1274     }
    1275     return rc;
    1276 }
    1277 
    1278 
    1279 SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)
    1280 {
    1281     /*
    1282      * Validate.
    1283      */
    1284     AssertPtrReturn(pHCPhys, NULL);
    1285     *pHCPhys = NIL_RTHCPHYS;
    1286     AssertPtrNullReturn(pR0Ptr, NULL);
    1287     if (pR0Ptr)
    1288         *pR0Ptr = NIL_RTR0PTR;
    1289     AssertPtrNullReturn(pHCPhys, NULL);
    1290     AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), NULL);
    1291 
    1292     /* fake */
    1293     if (RT_UNLIKELY(g_u32FakeMode))
    1294     {
    1295         void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
    1296         if (pR0Ptr)
    1297             *pR0Ptr = (RTR0PTR)pv;
    1298         if (pHCPhys)
    1299             *pHCPhys = (uintptr_t)pv + (PAGE_SHIFT * 1024);
    1300         return pv;
    1301     }
    1302 
    1303     /*
    1304      * Issue IOCtl to the SUPDRV kernel module.
    1305      */
    1306     SUPCONTALLOC Req;
    1307     Req.Hdr.u32Cookie = g_u32Cookie;
    1308     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1309     Req.Hdr.cbIn = SUP_IOCTL_CONT_ALLOC_SIZE_IN;
    1310     Req.Hdr.cbOut = SUP_IOCTL_CONT_ALLOC_SIZE_OUT;
    1311     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1312     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1313     Req.u.In.cPages = (uint32_t)cPages;
    1314     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_ALLOC, &Req, SUP_IOCTL_CONT_ALLOC_SIZE);
    1315     if (    RT_SUCCESS(rc)
    1316         &&  RT_SUCCESS(Req.Hdr.rc))
    1317     {
    1318         *pHCPhys = Req.u.Out.HCPhys;
    1319         if (pR0Ptr)
    1320             *pR0Ptr = Req.u.Out.pvR0;
    1321 #ifdef RT_OS_DARWIN /* HACK ALERT! */
    1322         supR3TouchPages(Req.u.Out.pvR3, cPages);
    1323 #endif
    1324         return Req.u.Out.pvR3;
    1325     }
    1326 
    1327     return NULL;
    1328 }
    1329 
    1330 
    1331 SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages)
    1332 {
    1333     /*
    1334      * Validate.
    1335      */
    1336     if (!pv)
    1337         return VINF_SUCCESS;
    1338     AssertPtrReturn(pv, VERR_INVALID_POINTER);
    1339     AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
    1340 
    1341     /* fake */
    1342     if (RT_UNLIKELY(g_u32FakeMode))
    1343     {
    1344         RTMemPageFree(pv, cPages * PAGE_SIZE);
    1345         return VINF_SUCCESS;
    1346     }
    1347 
    1348     /*
    1349      * Issue IOCtl to the SUPDRV kernel module.
    1350      */
    1351     SUPCONTFREE Req;
    1352     Req.Hdr.u32Cookie = g_u32Cookie;
    1353     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1354     Req.Hdr.cbIn = SUP_IOCTL_CONT_FREE_SIZE_IN;
    1355     Req.Hdr.cbOut = SUP_IOCTL_CONT_FREE_SIZE_OUT;
    1356     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1357     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1358     Req.u.In.pvR3 = pv;
    1359     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_FREE, &Req, SUP_IOCTL_CONT_FREE_SIZE);
    1360     if (RT_SUCCESS(rc))
    1361         rc = Req.Hdr.rc;
    1362     return rc;
    1363 }
    1364 
    1365 
    1366 SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages)
    1367 {
    1368     /*
    1369      * Validate.
    1370      */
    1371     AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);
    1372     *ppvPages = NULL;
    1373     AssertPtrReturn(paPages, VERR_INVALID_POINTER);
    1374     AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
    1375 
    1376     /* fake */
    1377     if (RT_UNLIKELY(g_u32FakeMode))
    1378     {
    1379         *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
    1380         if (!*ppvPages)
    1381             return VERR_NO_LOW_MEMORY;
    1382 
    1383         /* fake physical addresses. */
    1384         RTHCPHYS    Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;
    1385         size_t      iPage = cPages;
    1386         while (iPage-- > 0)
    1387             paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);
    1388         return VINF_SUCCESS;
    1389     }
    1390 
    1391     /*
    1392      * Issue IOCtl to the SUPDRV kernel module.
    1393      */
    1394     int rc;
    1395     PSUPLOWALLOC pReq = (PSUPLOWALLOC)RTMemTmpAllocZ(SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
    1396     if (pReq)
    1397     {
    1398         pReq->Hdr.u32Cookie = g_u32Cookie;
    1399         pReq->Hdr.u32SessionCookie = g_u32SessionCookie;
    1400         pReq->Hdr.cbIn = SUP_IOCTL_LOW_ALLOC_SIZE_IN;
    1401         pReq->Hdr.cbOut = SUP_IOCTL_LOW_ALLOC_SIZE_OUT(cPages);
    1402         pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;
    1403         pReq->Hdr.rc = VERR_INTERNAL_ERROR;
    1404         pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);
    1405         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_ALLOC, pReq, SUP_IOCTL_LOW_ALLOC_SIZE(cPages));
    1406         if (RT_SUCCESS(rc))
    1407             rc = pReq->Hdr.rc;
    1408         if (RT_SUCCESS(rc))
    1409         {
    1410             *ppvPages = pReq->u.Out.pvR3;
    1411             if (ppvPagesR0)
    1412                 *ppvPagesR0 = pReq->u.Out.pvR0;
    1413             if (paPages)
    1414                 for (size_t iPage = 0; iPage < cPages; iPage++)
    1415                 {
    1416                     paPages[iPage].uReserved = 0;
    1417                     paPages[iPage].Phys = pReq->u.Out.aPages[iPage];
    1418                     Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));
    1419                     Assert(paPages[iPage].Phys <= UINT32_C(0xfffff000));
    1420                 }
    1421 #ifdef RT_OS_DARWIN /* HACK ALERT! */
    1422             supR3TouchPages(pReq->u.Out.pvR3, cPages);
    1423 #endif
    1424         }
    1425         RTMemTmpFree(pReq);
    1426     }
    1427     else
    1428         rc = VERR_NO_TMP_MEMORY;
    1429 
    1430     return rc;
    1431 }
    1432 
    1433 
    1434 SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages)
    1435 {
    1436     /*
    1437      * Validate.
    1438      */
    1439     if (!pv)
    1440         return VINF_SUCCESS;
    1441     AssertPtrReturn(pv, VERR_INVALID_POINTER);
    1442     AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);
    1443 
    1444     /* fake */
    1445     if (RT_UNLIKELY(g_u32FakeMode))
    1446     {
    1447         RTMemPageFree(pv, cPages * PAGE_SIZE);
    1448         return VINF_SUCCESS;
    1449     }
    1450 
    1451     /*
    1452      * Issue IOCtl to the SUPDRV kernel module.
    1453      */
    1454     SUPCONTFREE Req;
    1455     Req.Hdr.u32Cookie = g_u32Cookie;
    1456     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    1457     Req.Hdr.cbIn = SUP_IOCTL_LOW_FREE_SIZE_IN;
    1458     Req.Hdr.cbOut = SUP_IOCTL_LOW_FREE_SIZE_OUT;
    1459     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    1460     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    1461     Req.u.In.pvR3 = pv;
    1462     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_FREE, &Req, SUP_IOCTL_LOW_FREE_SIZE);
    1463     if (RT_SUCCESS(rc))
    1464         rc = Req.Hdr.rc;
    1465     return rc;
    1466 }
    1467 
    1468 
    1469 SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszMsg, PRTFILE phFile)
    1470 {
    1471     /*
    1472      * Quick input validation.
    1473      */
    1474     AssertPtr(pszFilename);
    1475     AssertPtr(pszMsg);
    1476     AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the
    1477                                                      file is the same we verified after opening it. */
    1478 
    1479     /*
    1480      * Only do the actual check in hardened builds.
    1481      */
    1482 #ifdef VBOX_WITH_HARDENING
    1483     int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
    1484     if (RT_FAILURE(rc))
    1485         LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));
    1486     return rc;
    1487 #else
    1488     return VINF_SUCCESS;
    1489 #endif
    1490 }
    1491 
    1492 
    1493 SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo)
    1494 {
    1495     /*
    1496      * Quick input validation.
    1497      */
    1498     AssertPtr(pszArgv0);
    1499     RTErrInfoClear(pErrInfo);
    1500 
    1501     /*
    1502      * Get the executable image path as we need it for all the tests here.
    1503      */
    1504     char szExecPath[RTPATH_MAX];
    1505     if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
    1506         return RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_2, "RTProcGetExecutablePath failed");
    1507 
    1508     int rc;
    1509     if (fInternal)
    1510     {
    1511         /*
    1512          * Internal applications must be launched directly without any PATH
    1513          * searching involved.
    1514          */
    1515         if (RTPathCompare(pszArgv0, szExecPath) != 0)
    1516             return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,
    1517                                  "argv[0] does not match the executable image path: '%s' != '%s'", pszArgv0, szExecPath);
    1518 
    1519         /*
    1520          * Internal applications must reside in or under the
    1521          * RTPathAppPrivateArch directory.
    1522          */
    1523         char szAppPrivateArch[RTPATH_MAX];
    1524         rc = RTPathAppPrivateArch(szAppPrivateArch, sizeof(szAppPrivateArch));
    1525         if (RT_FAILURE(rc))
    1526             return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,
    1527                                  "RTPathAppPrivateArch failed with rc=%Rrc", rc);
    1528         size_t cchAppPrivateArch = strlen(szAppPrivateArch);
    1529         if (   cchAppPrivateArch >= strlen(szExecPath)
    1530             || !RTPATH_IS_SLASH(szExecPath[cchAppPrivateArch]))
    1531             return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,
    1532                                 "Internal executable does reside under RTPathAppPrivateArch");
    1533         szExecPath[cchAppPrivateArch] = '\0';
    1534         if (RTPathCompare(szExecPath, szAppPrivateArch) != 0)
    1535             return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,
    1536                                 "Internal executable does reside under RTPathAppPrivateArch");
    1537         szExecPath[cchAppPrivateArch] = RTPATH_SLASH;
    1538     }
    1539 
    1540 #ifdef VBOX_WITH_HARDENING
    1541     /*
    1542      * Verify that the image file and parent directories are sane.
    1543      */
    1544     rc = supR3HardenedVerifyFile(szExecPath, RTHCUINTPTR_MAX, pErrInfo);
    1545     if (RT_FAILURE(rc))
    1546         return rc;
    1547 #endif
    1548 
    1549     return VINF_SUCCESS;
    1550 }
    1551 
    1552 
    1553 SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
    1554 {
    1555     /*
    1556      * Quick input validation
    1557      */
    1558     AssertPtr(pszDirPath);
    1559     RTErrInfoClear(pErrInfo);
    1560 
    1561     /*
    1562      * Only do the actual check in hardened builds.
    1563      */
    1564 #ifdef VBOX_WITH_HARDENING
    1565     int rc = supR3HardenedVerifyDir(pszDirPath, fRecursive, fCheckFiles, pErrInfo);
    1566     if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
    1567         LogRel(("supR3HardenedVerifyDir: Verification of \"%s\" failed, rc=%Rrc\n", pszDirPath, rc));
    1568     return rc;
    1569 #else
    1570     NOREF(pszDirPath); NOREF(fRecursive); NOREF(fCheckFiles);
    1571     return VINF_SUCCESS;
    1572 #endif
    1573 }
    1574 
    1575 
    1576 SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo)
    1577 {
    1578     /*
    1579      * Quick input validation
    1580      */
    1581     AssertPtr(pszFilename);
    1582     RTErrInfoClear(pErrInfo);
    1583 
    1584     /*
    1585      * Only do the actual check in hardened builds.
    1586      */
    1587 #ifdef VBOX_WITH_HARDENING
    1588     int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
    1589     if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))
    1590         LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
    1591     return rc;
    1592 #else
    1593     return VINF_SUCCESS;
    1594 #endif
    1595 }
    1596100
    1597101
     
    1692196
    1693197    /* iterate the function table. */
    1694     int c = g_pFunctions->u.Out.cFunctions;
    1695     PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];
     198    int c = g_pSupFunctions->u.Out.cFunctions;
     199    PSUPFUNC pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
    1696200    while (c-- > 0)
    1697201    {
     
    1743247     * Despair.
    1744248     */
    1745     c = g_pFunctions->u.Out.cFunctions;
    1746     pFunc = &g_pFunctions->u.Out.aFunctions[0];
     249    c = g_pSupFunctions->u.Out.cFunctions;
     250    pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
    1747251    while (c-- > 0)
    1748252    {
    1749         RTAssertMsg2Weak("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);
     253        RTAssertMsg2Weak("%d: %s\n", g_pSupFunctions->u.Out.cFunctions - c, pFunc->szName);
    1750254        pFunc++;
    1751255    }
    1752256
    1753257    AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
    1754     if (g_u32FakeMode)
     258    if (g_uSupFakeMode)
    1755259    {
    1756260        *pValue = 0xdeadbeef;
     
    1884388        strcpy(OpenReq.u.In.szName, pszModule);
    1885389        strcpy(OpenReq.u.In.szFilename, pszFilename);
    1886         if (!g_u32FakeMode)
     390        if (!g_uSupFakeMode)
    1887391        {
    1888392            rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
     
    1997501                            pLoadReq->u.In.cbImageWithTabs            = cbImageWithTabs;
    1998502                            pLoadReq->u.In.pvImageBase                = OpenReq.u.Out.pvImageBase;
    1999                             if (!g_u32FakeMode)
     503                            if (!g_uSupFakeMode)
    2000504                            {
    2001505                                rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
     
    2066570{
    2067571    /* fake */
    2068     if (RT_UNLIKELY(g_u32FakeMode))
     572    if (RT_UNLIKELY(g_uSupFakeMode))
    2069573    {
    2070574        g_pvVMMR0 = NIL_RTR0PTR;
     
    2098602
    2099603    /* fake */
    2100     if (RT_UNLIKELY(g_u32FakeMode))
     604    if (RT_UNLIKELY(g_uSupFakeMode))
    2101605    {
    2102606        *ppvValue = (void *)(uintptr_t)0xdeadf00d;
     
    2141645
    2142646
    2143 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
    2144 {
    2145     if (g_pSUPGlobalInfoPage)
    2146     {
    2147         *pHCPhys = g_HCPhysSUPGlobalInfoPage;
    2148         return VINF_SUCCESS;
    2149     }
    2150     *pHCPhys = NIL_RTHCPHYS;
    2151     return VERR_WRONG_ORDER;
    2152 }
    2153 
    2154 
    2155647/**
    2156648 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
     
    2305797
    2306798
    2307 SUPR3DECL(int) SUPR3QueryVTxSupported(void)
    2308 {
    2309 #ifdef RT_OS_LINUX
    2310     return suplibOsQueryVTxSupported();
    2311 #else
    2312     return VINF_SUCCESS;
    2313 #endif
    2314 }
    2315 
    2316 
    2317 SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps)
    2318 {
    2319     AssertPtrReturn(pfCaps, VERR_INVALID_POINTER);
    2320 
    2321     *pfCaps = 0;
    2322 
    2323     /* fake */
    2324     if (RT_UNLIKELY(g_u32FakeMode))
    2325         return VINF_SUCCESS;
    2326 
    2327     /*
    2328      * Issue IOCtl to the SUPDRV kernel module.
    2329      */
    2330     SUPVTCAPS Req;
    2331     Req.Hdr.u32Cookie = g_u32Cookie;
    2332     Req.Hdr.u32SessionCookie = g_u32SessionCookie;
    2333     Req.Hdr.cbIn = SUP_IOCTL_VT_CAPS_SIZE_IN;
    2334     Req.Hdr.cbOut = SUP_IOCTL_VT_CAPS_SIZE_OUT;
    2335     Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
    2336     Req.Hdr.rc = VERR_INTERNAL_ERROR;
    2337     Req.u.Out.Caps = 0;
    2338     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_VT_CAPS, &Req, SUP_IOCTL_VT_CAPS_SIZE);
    2339     if (RT_SUCCESS(rc))
    2340     {
    2341         rc = Req.Hdr.rc;
    2342         if (RT_SUCCESS(rc))
    2343             *pfCaps = Req.u.Out.Caps;
    2344     }
    2345     return rc;
    2346 }
    2347 
    2348 
    2349 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg)
    2350 {
    2351     /* fake */
    2352     if (RT_UNLIKELY(g_u32FakeMode))
    2353         return VINF_SUCCESS;
    2354 
    2355     /*
    2356      * Issue IOCtl to the SUPDRV kernel module.
    2357      */
    2358     SUPTRACEROPEN Req;
    2359     Req.Hdr.u32Cookie       = g_u32Cookie;
    2360     Req.Hdr.u32SessionCookie= g_u32SessionCookie;
    2361     Req.Hdr.cbIn            = SUP_IOCTL_TRACER_OPEN_SIZE_IN;
    2362     Req.Hdr.cbOut           = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;
    2363     Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    2364     Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2365     Req.u.In.uCookie        = uCookie;
    2366     Req.u.In.uArg           = uArg;
    2367     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_OPEN, &Req, SUP_IOCTL_TRACER_OPEN_SIZE);
    2368     if (RT_SUCCESS(rc))
    2369         rc = Req.Hdr.rc;
    2370     return rc;
    2371 }
    2372 
    2373 
    2374 SUPR3DECL(int) SUPR3TracerClose(void)
    2375 {
    2376     /* fake */
    2377     if (RT_UNLIKELY(g_u32FakeMode))
    2378         return VINF_SUCCESS;
    2379 
    2380     /*
    2381      * Issue IOCtl to the SUPDRV kernel module.
    2382      */
    2383     SUPREQHDR Req;
    2384     Req.u32Cookie       = g_u32Cookie;
    2385     Req.u32SessionCookie= g_u32SessionCookie;
    2386     Req.cbIn            = SUP_IOCTL_TRACER_OPEN_SIZE_IN;
    2387     Req.cbOut           = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;
    2388     Req.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    2389     Req.rc              = VERR_INTERNAL_ERROR;
    2390     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_CLOSE, &Req, SUP_IOCTL_TRACER_CLOSE_SIZE);
    2391     if (RT_SUCCESS(rc))
    2392         rc = Req.rc;
    2393     return rc;
    2394 }
    2395 
    2396 
    2397 SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)
    2398 {
    2399     /* fake */
    2400     if (RT_UNLIKELY(g_u32FakeMode))
    2401     {
    2402         *piRetVal = -1;
    2403         return VERR_NOT_SUPPORTED;
    2404     }
    2405 
    2406     /*
    2407      * Issue IOCtl to the SUPDRV kernel module.
    2408      */
    2409     SUPTRACERIOCTL Req;
    2410     Req.Hdr.u32Cookie       = g_u32Cookie;
    2411     Req.Hdr.u32SessionCookie= g_u32SessionCookie;
    2412     Req.Hdr.cbIn            = SUP_IOCTL_TRACER_IOCTL_SIZE_IN;
    2413     Req.Hdr.cbOut           = SUP_IOCTL_TRACER_IOCTL_SIZE_OUT;
    2414     Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    2415     Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2416     Req.u.In.uCmd           = uCmd;
    2417     Req.u.In.uArg           = uArg;
    2418     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_IOCTL, &Req, SUP_IOCTL_TRACER_IOCTL_SIZE);
    2419     if (RT_SUCCESS(rc))
    2420     {
    2421         rc = Req.Hdr.rc;
    2422         *piRetVal = Req.u.Out.iRetVal;
    2423     }
    2424     return rc;
    2425 }
    2426 
    2427 
    2428 
    2429 typedef struct SUPDRVTRACERSTRTAB
    2430 {
    2431     /** Pointer to the string table. */
    2432     char       *pchStrTab;
    2433     /** The actual string table size. */
    2434     uint32_t    cbStrTab;
    2435     /** The original string pointers. */
    2436     RTUINTPTR   apszOrgFunctions[1];
    2437 } SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB;
    2438 
    2439 
    2440 /**
    2441  * Destroys a string table, restoring the original pszFunction member valus.
    2442  *
    2443  * @param   pThis               The string table structure.
    2444  * @param   paProbLocs          The probe location array.
    2445  * @param   cProbLocs           The number of probe locations.
    2446  */
    2447 static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,
    2448                                      uint32_t cProbeLocs, bool f32Bit)
    2449 {
    2450     /* Restore. */
    2451     size_t i = cProbeLocs;
    2452     if (f32Bit)
    2453         while (i--)
    2454             paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i];
    2455     else
    2456         while (i--)
    2457             paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i];
    2458 
    2459     /* Free. */
    2460     RTMemFree(pThis->pchStrTab);
    2461     RTMemFree(pThis);
    2462 }
    2463 
    2464 
    2465 /**
    2466  * Creates a string table for the pszFunction members in the probe location
    2467  * array.
    2468  *
    2469  * This will save and replace the pszFunction members with offsets.
    2470  *
    2471  * @returns Pointer to a string table structure.  NULL on failure.
    2472  * @param   paProbLocs          The probe location array.
    2473  * @param   cProbLocs           The number of elements in the array.
    2474  * @param   cBits
    2475  */
    2476 static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32,
    2477                                                    PVTGPROBELOC64 paProbeLocs64,
    2478                                                    uint32_t cProbeLocs,
    2479                                                    RTUINTPTR offDelta,
    2480                                                    bool f32Bit)
    2481 {
    2482     if (cProbeLocs > _128K)
    2483         return NULL;
    2484 
    2485     /*
    2486      * Allocate the string table structures.
    2487      */
    2488     size_t              cbThis    = RT_OFFSETOF(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]);
    2489     PSUPDRVTRACERSTRTAB pThis     = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis);
    2490     if (!pThis)
    2491         return NULL;
    2492 
    2493     uint32_t const      cHashBits = cProbeLocs * 2 - 1;
    2494     uint32_t           *pbmHash   = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 );
    2495     if (!pbmHash)
    2496     {
    2497         RTMemFree(pThis);
    2498         return NULL;
    2499     }
    2500 
    2501     /*
    2502      * Calc the max string table size and save the orignal pointers so we can
    2503      * replace them later.
    2504      */
    2505     size_t cbMax = 1;
    2506     for (uint32_t i = 0; i < cProbeLocs; i++)
    2507     {
    2508         pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction;
    2509         const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
    2510         size_t cch = strlen(pszFunction);
    2511         if (cch > _1K)
    2512         {
    2513             cbMax = 0;
    2514             break;
    2515         }
    2516         cbMax += cch + 1;
    2517     }
    2518 
    2519     /* Alloc space for it. */
    2520     if (cbMax > 0)
    2521         pThis->pchStrTab = (char *)RTMemAlloc(cbMax);
    2522     else
    2523         pThis->pchStrTab = NULL;
    2524     if (!pThis->pchStrTab)
    2525     {
    2526         RTMemFree(pbmHash);
    2527         RTMemFree(pThis);
    2528         return NULL;
    2529     }
    2530 
    2531     /*
    2532      * Create the string table.
    2533      */
    2534     uint32_t off = 0;
    2535     uint32_t offPrev = 0;
    2536 
    2537     for (uint32_t i = 0; i < cProbeLocs; i++)
    2538     {
    2539         const char * const psz      = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);
    2540         size_t       const cch      = strlen(psz);
    2541         uint32_t     const iHashBit = RTStrHash1(psz) % cHashBits;
    2542         if (ASMBitTestAndSet(pbmHash, iHashBit))
    2543         {
    2544             /* Often it's the most recent string. */
    2545             if (   off - offPrev < cch + 1
    2546                 || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
    2547             {
    2548                 /* It wasn't, search the entire string table. (lazy bird) */
    2549                 offPrev = 0;
    2550                 while (offPrev < off)
    2551                 {
    2552                     size_t cchCur = strlen(&pThis->pchStrTab[offPrev]);
    2553                     if (   cchCur == cch
    2554                         && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))
    2555                         break;
    2556                     offPrev += (uint32_t)cchCur + 1;
    2557                 }
    2558             }
    2559         }
    2560         else
    2561             offPrev = off;
    2562 
    2563         /* Add the string to the table. */
    2564         if (offPrev >= off)
    2565         {
    2566             memcpy(&pThis->pchStrTab[off], psz, cch + 1);
    2567             offPrev = off;
    2568             off += (uint32_t)cch + 1;
    2569         }
    2570 
    2571         /* Update the entry */
    2572         if (f32Bit)
    2573             paProbeLocs32[i].pszFunction = offPrev;
    2574         else
    2575             paProbeLocs64[i].pszFunction = offPrev;
    2576     }
    2577 
    2578     pThis->cbStrTab = off;
    2579     RTMemFree(pbmHash);
    2580     return pThis;
    2581 }
    2582 
    2583 
    2584 
    2585 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
    2586                                          RTUINTPTR uVtgHdrAddr, uint32_t fFlags)
    2587 {
    2588     /* Validate input. */
    2589     NOREF(hModNative);
    2590     AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
    2591     AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
    2592     AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
    2593     size_t cchModule = strlen(pszModule);
    2594     AssertReturn(cchModule < RT_SIZEOFMEMB(SUPTRACERUMODREG, u.In.szName), VERR_FILENAME_TOO_LONG);
    2595     AssertReturn(!RTPathHavePath(pszModule), VERR_INVALID_PARAMETER);
    2596     AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);
    2597 
    2598     /*
    2599      * Set the probe location array offset and size members. If the size is
    2600      * zero, don't bother ring-0 with it.
    2601      */
    2602     if (!pVtgHdr->offProbeLocs)
    2603     {
    2604         uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;
    2605         if (u64Tmp >= UINT32_MAX)
    2606             return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
    2607         pVtgHdr->cbProbeLocs  = (uint32_t)u64Tmp;
    2608 
    2609         u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;
    2610         if ((int64_t)u64Tmp != (int32_t)u64Tmp)
    2611         {
    2612             LogRel(("SUPR3TracerRegisterModule: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",
    2613                     u64Tmp, pVtgHdr->uProbeLocs.u64, uVtgHdrAddr));
    2614             return VERR_SUPDRV_VTG_BAD_HDR_PTR;
    2615         }
    2616         pVtgHdr->offProbeLocs = (int32_t)u64Tmp;
    2617     }
    2618 
    2619     if (   !pVtgHdr->cbProbeLocs
    2620         || !pVtgHdr->cbProbes)
    2621         return VINF_SUCCESS;
    2622 
    2623     /*
    2624      * Fake out.
    2625      */
    2626     if (RT_UNLIKELY(g_u32FakeMode))
    2627         return VINF_SUCCESS;
    2628 
    2629     /*
    2630      * Create a string table for the function names in the location array.
    2631      * It's somewhat easier to do that here than from ring-0.
    2632      */
    2633     size_t const        cProbeLocs  = pVtgHdr->cbProbeLocs
    2634                                     / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));
    2635     PVTGPROBELOC        paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);
    2636     PSUPDRVTRACERSTRTAB pStrTab     = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs,
    2637                                                               (PVTGPROBELOC64)paProbeLocs,
    2638                                                               cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr,
    2639                                                               pVtgHdr->cBits == 32);
    2640     if (!pStrTab)
    2641         return VERR_NO_MEMORY;
    2642 
    2643 
    2644     /*
    2645      * Issue IOCtl to the SUPDRV kernel module.
    2646      */
    2647     SUPTRACERUMODREG Req;
    2648     Req.Hdr.u32Cookie       = g_u32Cookie;
    2649     Req.Hdr.u32SessionCookie= g_u32SessionCookie;
    2650     Req.Hdr.cbIn            = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;
    2651     Req.Hdr.cbOut           = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;
    2652     Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    2653     Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2654     Req.u.In.uVtgHdrAddr    = uVtgHdrAddr;
    2655     Req.u.In.R3PtrVtgHdr    = pVtgHdr;
    2656     Req.u.In.R3PtrStrTab    = pStrTab->pchStrTab;
    2657     Req.u.In.cbStrTab       = pStrTab->cbStrTab;
    2658     Req.u.In.fFlags         = fFlags;
    2659 
    2660     memcpy(Req.u.In.szName, pszModule, cchModule + 1);
    2661     if (!RTPathHasSuffix(Req.u.In.szName))
    2662     {
    2663         /* Add the default suffix if none is given. */
    2664         switch (fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK)
    2665         {
    2666 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
    2667             case SUP_TRACER_UMOD_FLAGS_EXE:
    2668                 if (cchModule + sizeof(".exe") <= sizeof(Req.u.In.szName))
    2669                     strcpy(&Req.u.In.szName[cchModule], ".exe");
    2670                 break;
    2671 #endif
    2672 
    2673             case SUP_TRACER_UMOD_FLAGS_SHARED:
    2674             {
    2675                 const char *pszSuff = RTLdrGetSuff();
    2676                 size_t      cchSuff = strlen(pszSuff);
    2677                 if (cchModule + cchSuff < sizeof(Req.u.In.szName))
    2678                     memcpy(&Req.u.In.szName[cchModule], pszSuff, cchSuff + 1);
    2679                 break;
    2680             }
    2681         }
    2682     }
    2683 
    2684     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_REG, &Req, SUP_IOCTL_TRACER_UMOD_REG_SIZE);
    2685     if (RT_SUCCESS(rc))
    2686         rc = Req.Hdr.rc;
    2687 
    2688     supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs,
    2689                              cProbeLocs,  pVtgHdr->cBits == 32);
    2690     return rc;
    2691 }
    2692 
    2693 
    2694 SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr)
    2695 {
    2696     /* Validate input. */
    2697     AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);
    2698     AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
    2699 
    2700     /*
    2701      * Don't bother if the object is empty.
    2702      */
    2703     if (   !pVtgHdr->cbProbeLocs
    2704         || !pVtgHdr->cbProbes)
    2705         return VINF_SUCCESS;
    2706 
    2707     /*
    2708      * Fake out.
    2709      */
    2710     if (RT_UNLIKELY(g_u32FakeMode))
    2711         return VINF_SUCCESS;
    2712 
    2713     /*
    2714      * Issue IOCtl to the SUPDRV kernel module.
    2715      */
    2716     SUPTRACERUMODDEREG Req;
    2717     Req.Hdr.u32Cookie       = g_u32Cookie;
    2718     Req.Hdr.u32SessionCookie= g_u32SessionCookie;
    2719     Req.Hdr.cbIn            = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;
    2720     Req.Hdr.cbOut           = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;
    2721     Req.Hdr.fFlags          = SUPREQHDR_FLAGS_DEFAULT;
    2722     Req.Hdr.rc              = VERR_INTERNAL_ERROR;
    2723     Req.u.In.pVtgHdr        = pVtgHdr;
    2724 
    2725     int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_DEREG, &Req, SUP_IOCTL_TRACER_UMOD_DEREG_SIZE);
    2726     if (RT_SUCCESS(rc))
    2727         rc = Req.Hdr.rc;
    2728     return rc;
    2729 }
    2730 
    2731 
    2732 DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq)
    2733 {
    2734     pReq->Hdr.u32Cookie         = g_u32Cookie;
    2735     pReq->Hdr.u32SessionCookie  = g_u32SessionCookie;
    2736     Assert(pReq->Hdr.cbIn  == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN);
    2737     Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT);
    2738     pReq->Hdr.fFlags            = SUPREQHDR_FLAGS_DEFAULT;
    2739     pReq->Hdr.rc                = VINF_SUCCESS;
    2740 
    2741     suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE);
    2742 }
    2743 
  • trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp

    r47537 r49634  
    943943
    944944
     945#ifdef SUPDRV_WITH_MSR_PROBER
     946
     947int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     948{
     949    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
     950    return VERR_NOT_SUPPORTED;
     951}
     952
     953
     954int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     955{
     956    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
     957    return VERR_NOT_SUPPORTED;
     958}
     959
     960
     961int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     962{
     963    NOREF(idCpu); NOREF(pReq);
     964    return VERR_NOT_SUPPORTED;
     965}
     966
     967#endif /* SUPDRV_WITH_MSR_PROBER */
     968
     969
     970
    945971/**
    946972 * Converts an IPRT error code to a darwin error code.
  • trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c

    r47537 r49634  
    552552
    553553
     554#ifdef SUPDRV_WITH_MSR_PROBER
     555
     556int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     557{
     558    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
     559    return VERR_NOT_SUPPORTED;
     560}
     561
     562
     563int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     564{
     565    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
     566    return VERR_NOT_SUPPORTED;
     567}
     568
     569
     570int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     571{
     572    NOREF(idCpu); NOREF(pReq);
     573    return VERR_NOT_SUPPORTED;
     574}
     575
     576#endif /* SUPDRV_WITH_MSR_PROBER */
     577
     578
    554579SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
    555580{
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r47537 r49634  
    6060# include <linux/platform_device.h>
    6161#endif
     62#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) && defined(SUPDRV_WITH_MSR_PROBER)
     63# define SUPDRV_LINUX_HAS_SAFE_MSR_API
     64# include <asm/msr.h>
     65# include <iprt/asm-amd64-x86.h>
     66#endif
     67
    6268
    6369
     
    853859
    854860
     861#ifdef SUPDRV_WITH_MSR_PROBER
     862
     863int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     864{
     865# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
     866    uint32_t u32Low, u32High;
     867    int rc;
     868
     869    if (idCpu == NIL_RTCPUID)
     870        idCpu = RTMpCpuId();
     871    else if (!RTMpIsCpuOnline(idCpu))
     872        return VERR_CPU_OFFLINE;
     873    rc = rdmsr_safe_on_cpu(idCpu, uMsr, &u32Low, &u32High);
     874    if (rc >= 0)
     875    {
     876        *puValue = RT_MAKE_U64(u32Low, u32High);
     877        return VINF_SUCCESS;
     878    }
     879    return VERR_ACCESS_DENIED;
     880# else
     881    return VERR_NOT_SUPPORTED;
     882# endif
     883}
     884
     885
     886int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     887{
     888# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
     889    int rc;
     890
     891    if (idCpu == NIL_RTCPUID)
     892        idCpu = RTMpCpuId();
     893    else if (!RTMpIsCpuOnline(idCpu))
     894        return VERR_CPU_OFFLINE;
     895    rc = wrmsr_safe_on_cpu(idCpu, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue));
     896    if (rc >= 0)
     897        return VINF_SUCCESS;
     898    return VERR_ACCESS_DENIED;
     899# else
     900    return VERR_NOT_SUPPORTED;
     901# endif
     902}
     903
     904# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
     905/**
     906 * Worker for supdrvOSMsrProberModify.
     907 */
     908static DECLCALLBACK(void) supdrvOsMsrProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
     909{
     910    PSUPMSRPROBER               pReq    = (PSUPMSRPROBER)pvUser1;
     911    register uint32_t           uMsr    = pReq->u.In.uMsr;
     912    bool const                  fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER;
     913    uint64_t                    uBefore;
     914    uint64_t                    uWritten;
     915    uint64_t                    uAfter;
     916    int                         rcBefore, rcWrite, rcAfter, rcRestore;
     917    RTCCUINTREG                 fOldFlags;
     918
     919    /* Initialize result variables. */
     920    uBefore = uWritten = uAfter    = 0;
     921    rcWrite = rcAfter  = rcRestore = -EIO;
     922
     923    /*
     924     * Do the job.
     925     */
     926    fOldFlags = ASMIntDisableFlags();
     927    ASMCompilerBarrier(); /* paranoia */
     928    if (!fFaster)
     929        ASMWriteBackAndInvalidateCaches();
     930
     931    rcBefore = rdmsrl_safe(uMsr, &uBefore);
     932    if (rcBefore >= 0)
     933    {
     934        register uint64_t uRestore = uBefore;
     935        uWritten  = uRestore;
     936        uWritten &= pReq->u.In.uArgs.Modify.fAndMask;
     937        uWritten |= pReq->u.In.uArgs.Modify.fOrMask;
     938
     939        rcWrite   = wrmsr_safe(uMsr, RT_LODWORD(uWritten), RT_HIDWORD(uWritten));
     940        rcAfter   = rdmsrl_safe(uMsr, &uAfter);
     941        rcRestore = wrmsr_safe(uMsr, RT_LODWORD(uRestore), RT_HIDWORD(uRestore));
     942
     943        if (!fFaster)
     944        {
     945            ASMWriteBackAndInvalidateCaches();
     946            ASMReloadCR3();
     947            ASMNopPause();
     948        }
     949    }
     950
     951    ASMCompilerBarrier(); /* paranoia */
     952    ASMSetFlags(fOldFlags);
     953
     954    /*
     955     * Write out the results.
     956     */
     957    pReq->u.Out.uResults.Modify.uBefore    = uBefore;
     958    pReq->u.Out.uResults.Modify.uWritten   = uWritten;
     959    pReq->u.Out.uResults.Modify.uAfter     = uAfter;
     960    pReq->u.Out.uResults.Modify.fBeforeGp  = rcBefore  < 0;
     961    pReq->u.Out.uResults.Modify.fModifyGp  = rcWrite   < 0;
     962    pReq->u.Out.uResults.Modify.fAfterGp   = rcAfter   < 0;
     963    pReq->u.Out.uResults.Modify.fRestoreGp = rcRestore < 0;
     964    RT_ZERO(pReq->u.Out.uResults.Modify.afReserved);
     965}
     966
     967# endif
     968
     969
     970int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     971{
     972# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
     973    if (idCpu == NIL_RTCPUID)
     974        idCpu = RTMpCpuId();
     975    else if (!RTMpIsCpuOnline(idCpu))
     976        return VERR_CPU_OFFLINE;
     977    return RTMpOnSpecific(idCpu, supdrvOsMsrProberModifyOnCpu, pReq, NULL);
     978# else
     979    return VERR_NOT_SUPPORTED;
     980# endif
     981}
     982
     983#endif /* SUPDRV_WITH_MSR_PROBER */
     984
     985
    855986/**
    856987 * Converts a supdrv error code to an linux error code.
  • trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp

    r47537 r49634  
    421421
    422422
     423#ifdef SUPDRV_WITH_MSR_PROBER
     424
     425int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     426{
     427    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
     428    return VERR_NOT_SUPPORTED;
     429}
     430
     431
     432int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     433{
     434    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
     435    return VERR_NOT_SUPPORTED;
     436}
     437
     438
     439int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     440{
     441    NOREF(idCpu); NOREF(pReq);
     442    return VERR_NOT_SUPPORTED;
     443}
     444
     445#endif /* SUPDRV_WITH_MSR_PROBER */
     446
     447
    423448/**
    424449 * Callback for writing to the log buffer.
  • trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c

    r48952 r49634  
    11891189
    11901190
     1191#ifdef SUPDRV_WITH_MSR_PROBER
     1192
     1193int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     1194{
     1195    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
     1196    return VERR_NOT_SUPPORTED;
     1197}
     1198
     1199
     1200int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     1201{
     1202    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
     1203    return VERR_NOT_SUPPORTED;
     1204}
     1205
     1206
     1207int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     1208{
     1209    NOREF(idCpu); NOREF(pReq);
     1210    return VERR_NOT_SUPPORTED;
     1211}
     1212
     1213#endif /* SUPDRV_WITH_MSR_PROBER */
     1214
     1215
    11911216RTDECL(int) SUPR0Printf(const char *pszFormat, ...)
    11921217{
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r48132 r49634  
    10351035
    10361036
     1037#ifdef SUPDRV_WITH_MSR_PROBER
     1038
     1039int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
     1040{
     1041    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
     1042    return VERR_NOT_SUPPORTED;
     1043}
     1044
     1045
     1046int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
     1047{
     1048    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
     1049    return VERR_NOT_SUPPORTED;
     1050}
     1051
     1052
     1053int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
     1054{
     1055    NOREF(idCpu); NOREF(pReq);
     1056    return VERR_NOT_SUPPORTED;
     1057}
     1058
     1059#endif /* SUPDRV_WITH_MSR_PROBER */
     1060
     1061
    10371062/**
    10381063 * Converts an IPRT error code to an nt status code.
  • trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp

    r48935 r49634  
    5555    (PFNRT)SUPR3Init,
    5656    (PFNRT)SUPR3PageAllocEx,
     57    (PFNRT)SUPR3LoadVMM,
    5758    (PFNRT)SUPSemEventCreate,
    5859    (PFNRT)SUPTracerFireProbe,
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