VirtualBox

Changeset 91676 in vbox


Ignore:
Timestamp:
Oct 11, 2021 8:46:03 PM (3 years ago)
Author:
vboxsync
Message:

VMM/NEM-win: Quick and very dirty hack to make the code work on windows 11. This is _not_ something we want to be doing in the longish run... bugref:10118

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/nem.h

    r82968 r91676  
    8989/** @defgroup grp_nem_r0    The NEM ring-0 Context API
    9090 * @{  */
     91VMMR0_INT_DECL(int)  NEMR0Init(void);
     92VMMR0_INT_DECL(void) NEMR0Term(void);
    9193VMMR0_INT_DECL(int)  NEMR0InitVM(PGVM pGVM);
    9294VMMR0_INT_DECL(int)  NEMR0InitVMPart2(PGVM pGVM);
     
    101103VMMR0_INT_DECL(int)  NEMR0UpdateStatistics(PGVM pGVM, VMCPUID idCpu);
    102104VMMR0_INT_DECL(int)  NEMR0DoExperiment(PGVM pGVM, VMCPUID idCpu, uint64_t u64Arg);
     105#ifdef RT_OS_WINDOWS
     106VMMR0_INT_DECL(int)  NEMR0WinGetPartitionId(PGVM pGVM, uintptr_t uHandle);
     107#endif
    103108/** @} */
    104109
  • trunk/src/VBox/VMM/Makefile.kmk

    r91018 r91676  
    580580 endif
    581581 ifdef VBOX_WITH_NATIVE_NEM
    582 VMMR0_SOURCES.win.amd64 += VMMR0/NEMR0Native-win.cpp
     582VMMR0_SOURCES.win.amd64 += \
     583        VMMR0/NEMR0Native-win.cpp \
     584        VMMR0/NEMR0NativeA-win.asm
    583585VMMR0_DEFS.win.amd64    += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0
    584586VMMR0/NEMR0Native-win.cpp_SDKS.win = ReorderCompilerIncs $(VBOX_WINDDK) $(VBOX_WINPSDK)INCS
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r91580 r91676  
    3939#include <VBox/param.h>
    4040
     41#include <iprt/ctype.h>
     42#include <iprt/critsect.h>
    4143#include <iprt/dbg.h>
     44#include <iprt/mem.h>
    4245#include <iprt/memobj.h>
    4346#include <iprt/string.h>
    4447#include <iprt/time.h>
     48#define PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS32_PECOFF
     49#include <iprt/formats/pecoff.h>
    4550
    4651
     
    7580 */
    7681static NTSTATUS (*g_pfnWinHvDepositMemory)(uintptr_t idPartition, size_t cPages, uintptr_t IdealNode, size_t *pcActuallyAdded);
     82
     83RT_C_DECLS_BEGIN
     84/**
     85 * The WinHvGetPartitionProperty function we intercept in VID.SYS to get the
     86 * Hyper-V partition ID.
     87 *
     88 * This is used from assembly.
     89 */
     90NTSTATUS WinHvGetPartitionProperty(uintptr_t idPartition, HV_PARTITION_PROPERTY_CODE enmProperty, PHV_PARTITION_PROPERTY puValue);
     91decltype(WinHvGetPartitionProperty) *g_pfnWinHvGetPartitionProperty;
     92RT_C_DECLS_END
     93
     94/** @name VID.SYS image details.
     95 * @{ */
     96static uint8_t                                 *g_pbVidSys                            = NULL;
     97static uintptr_t                                g_cbVidSys                            = 0;
     98static PIMAGE_NT_HEADERS                        g_pVidSysHdrs                         = NULL;
     99/** Pointer to the import thunk entry in VID.SYS for WinHvGetPartitionProperty if we found it. */
     100static decltype(WinHvGetPartitionProperty)    **g_ppfnVidSysWinHvGetPartitionProperty = NULL;
     101
     102/** Critical section protecting the WinHvGetPartitionProperty hacking. */
     103static RTCRITSECT                               g_VidSysCritSect;
     104RT_C_DECLS_BEGIN
     105/** The partition ID passed to WinHvGetPartitionProperty by VID.SYS.   */
     106HV_PARTITION_ID                                 g_idVidSysFoundPartition = HV_PARTITION_ID_INVALID;
     107/** The thread which is currently looking for a partition ID. */
     108RTNATIVETHREAD                                  g_hVidSysMatchThread     = NIL_RTNATIVETHREAD;
     109/** The property code we expect in WinHvGetPartitionProperty. */
     110VID_PARTITION_PROPERTY_CODE                     g_enmVidSysMatchProperty = INT64_MAX;
     111/* NEMR0NativeA-win.asm: */
     112extern uint8_t                                  g_abNemR0WinHvrWinHvGetPartitionProperty_OriginalProlog[64];
     113RT_C_DECLS_END
     114/** @} */
     115
    77116
    78117
     
    92131                                             void *pvOutput, uint32_t cbOutput);
    93132
     133/* NEMR0NativeA-win.asm: */
     134DECLASM(NTSTATUS)    nemR0VidSysWinHvGetPartitionProperty(uintptr_t idPartition, HV_PARTITION_PROPERTY_CODE enmProperty,
     135                                                          PHV_PARTITION_PROPERTY puValue);
     136DECLASM(NTSTATUS)    nemR0WinHvrWinHvGetPartitionProperty(uintptr_t idPartition, HV_PARTITION_PROPERTY_CODE enmProperty,
     137                                                          PHV_PARTITION_PROPERTY puValue);
     138
    94139
    95140/*
     
    103148#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
    104149
     150
     151/**
     152 * Module initialization for NEM.
     153 */
     154VMMR0_INT_DECL(int)  NEMR0Init(void)
     155{
     156    return RTCritSectInit(&g_VidSysCritSect);
     157}
     158
     159
     160/**
     161 * Module termination for NEM.
     162 */
     163VMMR0_INT_DECL(void) NEMR0Term(void)
     164{
     165    RTCritSectDelete(&g_VidSysCritSect);
     166}
    105167
    106168
     
    132194}
    133195
     196
    134197/**
    135198 * Worker for NEMR0CleanupVM and NEMR0InitVM that cleans up a hypercall page.
     
    148211    pHypercallData->hMemObj    = NIL_RTR0MEMOBJ;
    149212    pHypercallData->HCPhysPage = NIL_RTHCPHYS;
     213}
     214
     215
     216static int nemR0StrICmp(const char *psz1, const char *psz2)
     217{
     218    for (;;)
     219    {
     220        char ch1 = *psz1++;
     221        char ch2 = *psz2++;
     222        if (   ch1 != ch2
     223            && RT_C_TO_LOWER(ch1) != RT_C_TO_LOWER(ch2))
     224            return ch1 - ch2;
     225        if (!ch1)
     226            return 0;
     227    }
     228}
     229
     230
     231/**
     232 * Worker for nemR0PrepareForVidSysIntercept().
     233 */
     234static void nemR0PrepareForVidSysInterceptInner(void)
     235{
     236    uint32_t const             cbImage       = g_cbVidSys;
     237    uint8_t * const            pbImage       = g_pbVidSys;
     238    PIMAGE_NT_HEADERS const    pNtHdrs       = g_pVidSysHdrs;
     239    uintptr_t const            offEndNtHdrs  = (uintptr_t)(pNtHdrs + 1) - (uintptr_t)pbImage;
     240
     241#define CHECK_LOG_RET(a_Expr, a_LogRel) do { \
     242            if (RT_LIKELY(a_Expr)) { /* likely */ } \
     243            else \
     244            { \
     245                LogRel(a_LogRel); \
     246                return; \
     247            } \
     248        } while (0)
     249
     250    //__try
     251    {
     252        /*
     253         * Get and validate the import directory entry.
     254         */
     255        CHECK_LOG_RET(   pNtHdrs->OptionalHeader.NumberOfRvaAndSizes >  IMAGE_DIRECTORY_ENTRY_IMPORT
     256                      || pNtHdrs->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_NUMBEROF_DIRECTORY_ENTRIES * 4,
     257                      ("NEMR0: vid.sys: NumberOfRvaAndSizes is out of range: %#x\n", pNtHdrs->OptionalHeader.NumberOfRvaAndSizes));
     258
     259        IMAGE_DATA_DIRECTORY const ImportDir = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
     260        CHECK_LOG_RET(   ImportDir.Size >= sizeof(IMAGE_IMPORT_DESCRIPTOR)
     261                      && ImportDir.VirtualAddress >= offEndNtHdrs /* ASSUMES NT headers before imports */
     262                      && (uint64_t)ImportDir.VirtualAddress + ImportDir.Size <= cbImage,
     263                      ("NEMR0: vid.sys: Bad import directory entry: %#x LB %#x (cbImage=%#x, offEndNtHdrs=%#zx)\n",
     264                       ImportDir.VirtualAddress, ImportDir.Size, cbImage, offEndNtHdrs));
     265
     266        /*
     267         * Walk the import descriptor table looking for NTDLL.DLL.
     268         */
     269        for (PIMAGE_IMPORT_DESCRIPTOR pImps = (PIMAGE_IMPORT_DESCRIPTOR)&pbImage[ImportDir.VirtualAddress];
     270             pImps->Name != 0 && pImps->FirstThunk != 0;
     271             pImps++)
     272        {
     273            CHECK_LOG_RET(pImps->Name < cbImage, ("NEMR0: vid.sys: Bad import directory entry name: %#x", pImps->Name));
     274            const char *pszModName = (const char *)&pbImage[pImps->Name];
     275            if (nemR0StrICmp(pszModName, "winhvr.sys"))
     276                continue;
     277            CHECK_LOG_RET(pImps->FirstThunk < cbImage && pImps->FirstThunk >= offEndNtHdrs,
     278                          ("NEMR0: vid.sys: Bad FirstThunk: %#x", pImps->FirstThunk));
     279            CHECK_LOG_RET(   pImps->u.OriginalFirstThunk == 0
     280                          || (pImps->u.OriginalFirstThunk >= offEndNtHdrs && pImps->u.OriginalFirstThunk < cbImage),
     281                          ("NEMR0: vid.sys: Bad OriginalFirstThunk: %#x", pImps->u.OriginalFirstThunk));
     282
     283            /*
     284             * Walk the thunks table(s) looking for WinHvGetPartitionProperty.
     285             */
     286            uintptr_t *puFirstThunk = (uintptr_t *)&pbImage[pImps->FirstThunk]; /* update this. */
     287            if (   pImps->u.OriginalFirstThunk != 0
     288                && pImps->u.OriginalFirstThunk != pImps->FirstThunk)
     289            {
     290                uintptr_t const *puOrgThunk = (uintptr_t const *)&pbImage[pImps->u.OriginalFirstThunk]; /* read from this. */
     291                uintptr_t        cLeft      = (cbImage - (RT_MAX(pImps->FirstThunk, pImps->u.OriginalFirstThunk)))
     292                                            / sizeof(*puFirstThunk);
     293                while (cLeft-- > 0 && *puOrgThunk != 0)
     294                {
     295                    if (!(*puOrgThunk & IMAGE_ORDINAL_FLAG64))
     296                    {
     297                        CHECK_LOG_RET(*puOrgThunk >= offEndNtHdrs && *puOrgThunk < cbImage,
     298                                      ("NEMR0: vid.sys: Bad thunk entry: %#x", *puOrgThunk));
     299
     300                        const char *pszSymbol = (const char *)&pbImage[*puOrgThunk + 2];
     301                        if (strcmp(pszSymbol, "WinHvGetPartitionProperty") == 0)
     302                            g_ppfnVidSysWinHvGetPartitionProperty = (decltype(WinHvGetPartitionProperty) **)puFirstThunk;
     303                    }
     304
     305                    puOrgThunk++;
     306                    puFirstThunk++;
     307                }
     308            }
     309            else
     310            {
     311                /* No original thunk table, so scan the resolved symbols for a match
     312                   with the WinHvGetPartitionProperty address. */
     313                uintptr_t const uNeedle = (uintptr_t)g_pfnWinHvGetPartitionProperty;
     314                uintptr_t       cLeft   = (cbImage - pImps->FirstThunk) / sizeof(*puFirstThunk);
     315                while (cLeft-- > 0 && *puFirstThunk != 0)
     316                {
     317                    if (*puFirstThunk == uNeedle)
     318                        g_ppfnVidSysWinHvGetPartitionProperty = (decltype(WinHvGetPartitionProperty) **)puFirstThunk;
     319                    puFirstThunk++;
     320                }
     321            }
     322        }
     323
     324        /* Report the findings: */
     325        if (g_ppfnVidSysWinHvGetPartitionProperty)
     326            LogRel(("NEMR0: vid.sys: Found WinHvGetPartitionProperty import thunk at %p (value %p vs %p)\n",
     327                    g_ppfnVidSysWinHvGetPartitionProperty,*g_ppfnVidSysWinHvGetPartitionProperty, g_pfnWinHvGetPartitionProperty));
     328        else
     329            LogRel(("NEMR0: vid.sys: Did not find WinHvGetPartitionProperty!\n"));
     330    }
     331    //__except(EXCEPTION_EXECUTE_HANDLER)
     332    //{
     333    //    return;
     334    //}
     335#undef CHECK_LOG_RET
     336}
     337
     338
     339/**
     340 * Worker for NEMR0InitVM that prepares for intercepting stuff in VID.SYS.
     341 */
     342static void nemR0PrepareForVidSysIntercept(RTDBGKRNLINFO hKrnlInfo)
     343{
     344    /*
     345     * Resolve the symbols we need first.
     346     */
     347    int rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, "vid.sys", "__ImageBase", (void **)&g_pbVidSys);
     348    if (RT_SUCCESS(rc))
     349    {
     350        rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, "vid.sys", "__ImageSize", (void **)&g_cbVidSys);
     351        if (RT_SUCCESS(rc))
     352        {
     353            rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, "vid.sys", "__ImageNtHdrs", (void **)&g_pVidSysHdrs);
     354            if (RT_SUCCESS(rc))
     355            {
     356                rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, "winhvr.sys", "WinHvGetPartitionProperty",
     357                                                (void **)&g_pfnWinHvGetPartitionProperty);
     358                if (RT_SUCCESS(rc))
     359                {
     360                    /*
     361                     * Now locate the import thunk entry for WinHvGetPartitionProperty in vid.sys.
     362                     */
     363                    nemR0PrepareForVidSysInterceptInner();
     364                }
     365                else
     366                    LogRel(("NEMR0: Failed to find winhvr.sys!WinHvGetPartitionProperty (%Rrc)\n", rc));
     367            }
     368            else
     369                LogRel(("NEMR0: Failed to find vid.sys!__ImageNtHdrs (%Rrc)\n", rc));
     370        }
     371        else
     372            LogRel(("NEMR0: Failed to find vid.sys!__ImageSize (%Rrc)\n", rc));
     373    }
     374    else
     375        LogRel(("NEMR0: Failed to find vid.sys!__ImageBase (%Rrc)\n", rc));
    150376}
    151377
     
    187413                rc = rc == VERR_MODULE_NOT_FOUND ? VERR_NEM_MISSING_KERNEL_API_2 : VERR_NEM_MISSING_KERNEL_API_3;
    188414        }
     415
     416        /*
     417         * Since late 2021 we may also need to do some nasty trickery with vid.sys to get
     418         * the partition ID. So, ge the necessary info while we have a hKrnlInfo instance.
     419         */
     420        if (RT_SUCCESS(rc))
     421            nemR0PrepareForVidSysIntercept(hKrnlInfo);
     422
    189423        RTR0DbgKrnlInfoRelease(hKrnlInfo);
    190424        if (RT_SUCCESS(rc))
     
    283517
    284518/**
     519 * Here is something that we really do not wish to do, but find us force do to
     520 * right now as we cannot rewrite the memory management of VBox 6.1 in time for
     521 * windows 11.
     522 *
     523 * @returns VBox status code.
     524 * @param   pGVM        The ring-0 VM structure.
     525 * @param   pahMemObjs  Array of 6 memory objects that the caller will release.
     526 *                      ASSUMES that they are initialized to NIL.
     527 */
     528static int nemR0InitVMPart2DontWannaDoTheseUglyPartitionIdFallbacks(PGVM pGVM, PRTR0MEMOBJ pahMemObjs)
     529{
     530    /*
     531     * Check preconditions:
     532     */
     533    if (   !g_ppfnVidSysWinHvGetPartitionProperty
     534        || (uintptr_t)g_ppfnVidSysWinHvGetPartitionProperty & (sizeof(uintptr_t) - 1))
     535    {
     536        LogRel(("NEMR0: g_ppfnVidSysWinHvGetPartitionProperty is NULL or misaligned (%p), partition ID fallback not possible.\n",
     537                g_ppfnVidSysWinHvGetPartitionProperty));
     538        return VERR_NEM_INIT_FAILED;
     539    }
     540    if (!g_pfnWinHvGetPartitionProperty)
     541    {
     542        LogRel(("NEMR0: g_pfnWinHvGetPartitionProperty is NULL, partition ID fallback not possible.\n"));
     543        return VERR_NEM_INIT_FAILED;
     544    }
     545    if (!pGVM->nem.s.IoCtlGetPartitionProperty.uFunction)
     546    {
     547        LogRel(("NEMR0: IoCtlGetPartitionProperty.uFunction is 0, partition ID fallback not possible.\n"));
     548        return VERR_NEM_INIT_FAILED;
     549    }
     550
     551    /*
     552     * Create an alias for the thunk table entry because its very likely to be read-only.
     553     */
     554    int rc = RTR0MemObjLockKernel(&pahMemObjs[0], g_ppfnVidSysWinHvGetPartitionProperty, sizeof(uintptr_t), RTMEM_PROT_READ);
     555    if (RT_FAILURE(rc))
     556    {
     557        LogRel(("NEMR0: RTR0MemObjLockKernel failed on VID.SYS thunk table entry: %Rrc\n", rc));
     558        return rc;
     559    }
     560
     561    rc = RTR0MemObjEnterPhys(&pahMemObjs[1], RTR0MemObjGetPagePhysAddr(pahMemObjs[0], 0), PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
     562    if (RT_FAILURE(rc))
     563    {
     564        LogRel(("NEMR0: RTR0MemObjEnterPhys failed on VID.SYS thunk table entry: %Rrc\n", rc));
     565        return rc;
     566    }
     567
     568    rc = RTR0MemObjMapKernel(&pahMemObjs[2], pahMemObjs[1], (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     569    if (RT_FAILURE(rc))
     570    {
     571        LogRel(("NEMR0: RTR0MemObjMapKernel failed on VID.SYS thunk table entry: %Rrc\n", rc));
     572        return rc;
     573    }
     574
     575    decltype(WinHvGetPartitionProperty) **ppfnThunkAlias
     576        = (decltype(WinHvGetPartitionProperty) **)(  (uintptr_t)RTR0MemObjAddress(pahMemObjs[2])
     577                                                   | ((uintptr_t)g_ppfnVidSysWinHvGetPartitionProperty & PAGE_OFFSET_MASK));
     578    LogRel(("NEMR0: ppfnThunkAlias=%p *ppfnThunkAlias=%p; original: %p & %p, phys %RHp\n", ppfnThunkAlias, *ppfnThunkAlias,
     579            g_ppfnVidSysWinHvGetPartitionProperty, *g_ppfnVidSysWinHvGetPartitionProperty,
     580            RTR0MemObjGetPagePhysAddr(pahMemObjs[0], 0) ));
     581
     582    /*
     583     * Create an alias for the target code in WinHvr.sys as there is a very decent
     584     * chance we have to patch it.
     585     */
     586    rc = RTR0MemObjLockKernel(&pahMemObjs[3], g_pfnWinHvGetPartitionProperty, sizeof(uintptr_t), RTMEM_PROT_READ);
     587    if (RT_FAILURE(rc))
     588    {
     589        LogRel(("NEMR0: RTR0MemObjLockKernel failed on WinHvGetPartitionProperty (%p): %Rrc\n", g_pfnWinHvGetPartitionProperty, rc));
     590        return rc;
     591    }
     592
     593    rc = RTR0MemObjEnterPhys(&pahMemObjs[4], RTR0MemObjGetPagePhysAddr(pahMemObjs[3], 0), PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE);
     594    if (RT_FAILURE(rc))
     595    {
     596        LogRel(("NEMR0: RTR0MemObjEnterPhys failed on WinHvGetPartitionProperty: %Rrc\n", rc));
     597        return rc;
     598    }
     599
     600    rc = RTR0MemObjMapKernel(&pahMemObjs[5], pahMemObjs[4], (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     601    if (RT_FAILURE(rc))
     602    {
     603        LogRel(("NEMR0: RTR0MemObjMapKernel failed on WinHvGetPartitionProperty: %Rrc\n", rc));
     604        return rc;
     605    }
     606
     607    uint8_t *pbTargetAlias = (uint8_t *)(  (uintptr_t)RTR0MemObjAddress(pahMemObjs[5])
     608                                         | ((uintptr_t)g_pfnWinHvGetPartitionProperty & PAGE_OFFSET_MASK));
     609    LogRel(("NEMR0: pbTargetAlias=%p %.16Rhxs; original: %p %.16Rhxs, phys %RHp\n", pbTargetAlias, pbTargetAlias,
     610            g_pfnWinHvGetPartitionProperty, g_pfnWinHvGetPartitionProperty, RTR0MemObjGetPagePhysAddr(pahMemObjs[3], 0) ));
     611
     612    /*
     613     * Analyse the target functions prologue to figure out how much we should copy
     614     * when patching it.  We repeat this every time because we don't want to get
     615     * tripped up by someone else doing the same stuff as we're doing here.
     616     * We need at least 12 bytes for the patch sequence (MOV RAX, QWORD; JMP RAX)
     617     */
     618    union
     619    {
     620        uint8_t  ab[48];    /**< Must be equal or smallar than g_abNemR0WinHvrWinHvGetPartitionProperty_OriginalProlog */
     621        int64_t  ai64[6];
     622    } Org;
     623    memcpy(Org.ab, g_pfnWinHvGetPartitionProperty, sizeof(Org)); /** @todo ASSUMES 48 valid bytes start at function... */
     624
     625    uint32_t       offJmpBack = 0;
     626    uint32_t const cbMinJmpPatch = 12;
     627    DISSTATE       Dis;
     628    while (offJmpBack < cbMinJmpPatch && offJmpBack < sizeof(Org) - 16)
     629    {
     630        uint32_t cbInstr = 1;
     631        rc = DISInstr(&Org.ab[offJmpBack], DISCPUMODE_64BIT, &Dis, &cbInstr);
     632        if (RT_FAILURE(rc))
     633        {
     634            LogRel(("NEMR0: DISInstr failed %#x bytes into WinHvGetPartitionProperty: %Rrc (%.48Rhxs)\n",
     635                    offJmpBack, rc, Org.ab));
     636            break;
     637        }
     638        if (Dis.pCurInstr->fOpType & DISOPTYPE_CONTROLFLOW)
     639        {
     640            LogRel(("NEMR0: Control flow instruction %#x bytes into WinHvGetPartitionProperty prologue: %.48Rhxs\n",
     641                    offJmpBack, Org.ab));
     642            break;
     643        }
     644        if (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */)
     645        {
     646            LogRel(("NEMR0: RIP relative addressing %#x bytes into WinHvGetPartitionProperty prologue: %.48Rhxs\n",
     647                    offJmpBack, Org.ab));
     648            break;
     649        }
     650        offJmpBack += cbInstr;
     651    }
     652
     653    uintptr_t const cbLeftInPage = PAGE_SIZE - ((uintptr_t)g_pfnWinHvGetPartitionProperty & PAGE_OFFSET_MASK);
     654    if (cbLeftInPage < 16 && offJmpBack >= cbMinJmpPatch)
     655    {
     656        LogRel(("NEMR0: WinHvGetPartitionProperty patching not possible do the page crossing: %p (%#zx)\n",
     657                g_pfnWinHvGetPartitionProperty, cbLeftInPage));
     658        offJmpBack = 0;
     659    }
     660    if (offJmpBack >= cbMinJmpPatch)
     661        LogRel(("NEMR0: offJmpBack=%#x for WinHvGetPartitionProperty (%p: %.48Rhxs)\n",
     662                offJmpBack, g_pfnWinHvGetPartitionProperty, Org.ab));
     663    else
     664        offJmpBack = 0;
     665    rc = VINF_SUCCESS;
     666
     667    /*
     668     * Now enter serialization lock and get on with it...
     669     */
     670    PVMCPUCC const pVCpu0 = &pGVM->aCpus[0];
     671    NTSTATUS       rcNt;
     672    RTCritSectEnter(&g_VidSysCritSect);
     673
     674    /*
     675     * First attempt, patching the import table entry.
     676     */
     677    g_idVidSysFoundPartition = HV_PARTITION_ID_INVALID;
     678    g_hVidSysMatchThread     = RTThreadNativeSelf();
     679    g_enmVidSysMatchProperty = pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty = HvPartitionPropertyProcessorVendor;
     680    pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue = 0;
     681
     682    void *pvOld = NULL;
     683    if (ASMAtomicCmpXchgExPtr(ppfnThunkAlias, (void *)(uintptr_t)nemR0VidSysWinHvGetPartitionProperty,
     684                              (void *)(uintptr_t)g_pfnWinHvGetPartitionProperty, &pvOld))
     685    {
     686        LogRel(("NEMR0: after switch to %p: ppfnThunkAlias=%p *ppfnThunkAlias=%p; original: %p & %p\n",
     687                nemR0VidSysWinHvGetPartitionProperty, ppfnThunkAlias, *ppfnThunkAlias,
     688                g_ppfnVidSysWinHvGetPartitionProperty, *g_ppfnVidSysWinHvGetPartitionProperty));
     689
     690        rcNt = nemR0NtPerformIoControl(pGVM, pVCpu0, pGVM->nemr0.s.IoCtlGetPartitionProperty.uFunction,
     691                                       &pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty,
     692                                       sizeof(pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty),
     693                                       &pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue,
     694                                       sizeof(pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue));
     695        ASMAtomicWritePtr(ppfnThunkAlias, (void *)(uintptr_t)g_pfnWinHvGetPartitionProperty);
     696        HV_PARTITION_ID idHvPartition = g_idVidSysFoundPartition;
     697
     698        LogRel(("NEMR0: WinHvGetPartitionProperty trick #1 yielded: rcNt=%#x idHvPartition=%#RX64 uValue=%#RX64\n",
     699                rcNt, idHvPartition, pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue));
     700        pGVM->nemr0.s.idHvPartition = idHvPartition;
     701    }
     702    else
     703    {
     704        LogRel(("NEMR0: Unexpected WinHvGetPartitionProperty pointer in VID.SYS: %p, expected %p\n",
     705                pvOld, g_pfnWinHvGetPartitionProperty));
     706        rc = VERR_NEM_INIT_FAILED;
     707    }
     708
     709    /*
     710     * If that didn't succeed, try patching the winhvr.sys code.
     711     */
     712    if (   pGVM->nemr0.s.idHvPartition == HV_PARTITION_ID_INVALID
     713        && offJmpBack >= cbMinJmpPatch)
     714    {
     715        g_idVidSysFoundPartition = HV_PARTITION_ID_INVALID;
     716        g_hVidSysMatchThread     = RTThreadNativeSelf();
     717        g_enmVidSysMatchProperty = pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty = HvPartitionPropertyProcessorVendor;
     718        pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue = 0;
     719
     720        /*
     721         * Prepare the hook area.
     722         */
     723        uint8_t *pbDst = g_abNemR0WinHvrWinHvGetPartitionProperty_OriginalProlog;
     724        memcpy(pbDst, (uint8_t const *)(uintptr_t)g_pfnWinHvGetPartitionProperty, offJmpBack);
     725        pbDst += offJmpBack;
     726
     727        *pbDst++ = 0x48; /* mov rax, imm64 */
     728        *pbDst++ = 0xb8;
     729        *(uint64_t *)pbDst = (uintptr_t)g_pfnWinHvGetPartitionProperty + offJmpBack;
     730        pbDst += sizeof(uint64_t);
     731        *pbDst++ = 0xff; /* jmp rax */
     732        *pbDst++ = 0xe0;
     733        *pbDst++ = 0xcc; /* int3 */
     734
     735        /*
     736         * Patch the original. We use cmpxchg16b here to avoid concurrency problems
     737         * (this also makes sure we don't trample over someone else doing similar
     738         * patching at the same time).
     739         */
     740        union
     741        {
     742            uint8_t  ab[16];
     743            uint64_t au64[2];
     744        } Patch;
     745        memcpy(Patch.ab, Org.ab, sizeof(Patch));
     746        pbDst = Patch.ab;
     747        *pbDst++ = 0x48; /* mov rax, imm64 */
     748        *pbDst++ = 0xb8;
     749        *(uint64_t *)pbDst = (uintptr_t)nemR0WinHvrWinHvGetPartitionProperty;
     750        pbDst += sizeof(uint64_t);
     751        *pbDst++ = 0xff; /* jmp rax */
     752        *pbDst++ = 0xe0;
     753
     754        int64_t ai64CmpCopy[2] = { Org.ai64[0], Org.ai64[1] }; /* paranoia  */
     755        if (_InterlockedCompareExchange128((__int64 volatile *)pbTargetAlias, Patch.au64[1], Patch.au64[0], ai64CmpCopy) != 0)
     756        {
     757            rcNt = nemR0NtPerformIoControl(pGVM, pVCpu0, pGVM->nemr0.s.IoCtlGetPartitionProperty.uFunction,
     758                                           &pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty,
     759                                           sizeof(pVCpu0->nem.s.uIoCtlBuf.GetProp.enmProperty),
     760                                           &pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue,
     761                                           sizeof(pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue));
     762
     763            for (uint32_t cFailures = 0; cFailures < 10; cFailures++)
     764            {
     765                ai64CmpCopy[0] = Patch.au64[0]; /* paranoia */
     766                ai64CmpCopy[1] = Patch.au64[1];
     767                if (_InterlockedCompareExchange128((__int64 volatile *)pbTargetAlias, Org.ai64[1], Org.ai64[0], ai64CmpCopy) != 0)
     768                {
     769                    if (cFailures > 0)
     770                        LogRel(("NEMR0: Succeeded on try #%u.\n", cFailures));
     771                    break;
     772                }
     773                LogRel(("NEMR0: Patch restore failure #%u: %.16Rhxs, expected %.16Rhxs\n",
     774                        cFailures + 1, &ai64CmpCopy[0], &Patch.au64[0]));
     775                RTThreadSleep(1000);
     776            }
     777
     778            HV_PARTITION_ID idHvPartition = g_idVidSysFoundPartition;
     779            LogRel(("NEMR0: WinHvGetPartitionProperty trick #2 yielded: rcNt=%#x idHvPartition=%#RX64 uValue=%#RX64\n",
     780                    rcNt, idHvPartition, pVCpu0->nem.s.uIoCtlBuf.GetProp.uValue));
     781            pGVM->nemr0.s.idHvPartition = idHvPartition;
     782
     783        }
     784        else
     785        {
     786            LogRel(("NEMR0: Failed to install WinHvGetPartitionProperty patch: %.16Rhxs, expected %.16Rhxs\n",
     787                    &ai64CmpCopy[0], &Org.ai64[0]));
     788            rc = VERR_NEM_INIT_FAILED;
     789        }
     790    }
     791
     792    RTCritSectLeave(&g_VidSysCritSect);
     793
     794    return rc;
     795}
     796
     797
     798/**
    285799 * 2nd part of the initialization, after we've got a partition handle.
    286800 *
     
    305819    pGVM->nemr0.s.IoCtlGetHvPartitionId = Copy;
    306820
     821    Copy = pGVM->nem.s.IoCtlGetPartitionProperty;
     822    AssertLogRelReturn(Copy.uFunction != 0, VERR_NEM_INIT_FAILED);
     823    AssertLogRelReturn(Copy.cbInput == sizeof(VID_PARTITION_PROPERTY_CODE), VERR_NEM_INIT_FAILED);
     824    AssertLogRelReturn(Copy.cbOutput == sizeof(HV_PARTITION_PROPERTY), VERR_NEM_INIT_FAILED);
     825    pGVM->nemr0.s.IoCtlGetPartitionProperty = Copy;
     826
    307827    pGVM->nemr0.s.fMayUseRing0Runloop = pGVM->nem.s.fUseRing0Runloop;
    308828
     
    356876        NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pVCpu0, pGVM->nemr0.s.IoCtlGetHvPartitionId.uFunction, NULL, 0,
    357877                                                &pVCpu0->nem.s.uIoCtlBuf.idPartition, sizeof(pVCpu0->nem.s.uIoCtlBuf.idPartition));
     878#if 0
    358879        AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("IoCtlGetHvPartitionId failed: %#x\n", rcNt), VERR_NEM_INIT_FAILED);
    359880        pGVM->nemr0.s.idHvPartition = pVCpu0->nem.s.uIoCtlBuf.idPartition;
     881#else
     882        /*
     883         * Since 2021 (Win11) the above I/O control doesn't work on exo-partitions
     884         * so we have to go to extremes to get at it.  Sigh.
     885         */
     886        if (   !NT_SUCCESS(rcNt)
     887            || pVCpu0->nem.s.uIoCtlBuf.idPartition == HV_PARTITION_ID_INVALID)
     888        {
     889            LogRel(("IoCtlGetHvPartitionId failed: r0=%#RX64, r3=%#RX64, rcNt=%#x\n",
     890                    pGVM->nemr0.s.idHvPartition, pGVM->nem.s.idHvPartition, rcNt));
     891
     892            RTR0MEMOBJ ahMemObjs[6]
     893                = { NIL_RTR0MEMOBJ, NIL_RTR0MEMOBJ, NIL_RTR0MEMOBJ, NIL_RTR0MEMOBJ, NIL_RTR0MEMOBJ, NIL_RTR0MEMOBJ };
     894            rc = nemR0InitVMPart2DontWannaDoTheseUglyPartitionIdFallbacks(pGVM, ahMemObjs);
     895            size_t i = RT_ELEMENTS(ahMemObjs);
     896            while (i-- > 0)
     897                RTR0MemObjFree(ahMemObjs[i], false /*fFreeMappings*/);
     898        }
     899        if (pGVM->nem.s.idHvPartition == HV_PARTITION_ID_INVALID)
     900            pGVM->nem.s.idHvPartition = pGVM->nemr0.s.idHvPartition;
     901#endif
    360902        AssertLogRelMsgReturn(pGVM->nemr0.s.idHvPartition == pGVM->nem.s.idHvPartition,
    361903                              ("idHvPartition mismatch: r0=%#RX64, r3=%#RX64\n", pGVM->nemr0.s.idHvPartition, pGVM->nem.s.idHvPartition),
    362904                              VERR_NEM_INIT_FAILED);
     905        if (RT_SUCCESS(rc) && pGVM->nemr0.s.idHvPartition == HV_PARTITION_ID_INVALID)
     906            rc = VERR_NEM_INIT_FAILED;
    363907    }
    364908
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r91271 r91676  
    184184#endif
    185185                                    {
     186#ifdef VBOX_WITH_NEM_R0
     187                                        rc = NEMR0Init();
    186188                                        if (RT_SUCCESS(rc))
     189#endif
    187190                                        {
    188191                                            LogFlow(("ModuleInit: returns success\n"));
     
    267270#ifdef VBOX_WITH_TRIPLE_FAULT_HACK
    268271    vmmR0TripleFaultHackTerm();
     272#endif
     273#ifdef VBOX_WITH_NEM_R0
     274    NEMR0Term();
    269275#endif
    270276
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r91580 r91676  
    6969
    7070/** VID I/O control detection: Fake partition handle input. */
    71 #define NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE          ((HANDLE)(uintptr_t)38479125)
     71#define NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE                      ((HANDLE)(uintptr_t)38479125)
    7272/** VID I/O control detection: Fake partition ID return. */
    73 #define NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_ID    UINT64_C(0xfa1e000042424242)
     73#define NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_ID                UINT64_C(0xfa1e000042424242)
     74/** VID I/O control detection: The property we get via VidGetPartitionProperty. */
     75#define NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_CODE     HvPartitionPropertyProcessorVendor
     76/** VID I/O control detection: Fake property value return. */
     77#define NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_VALUE    UINT64_C(0xf00dface01020304)
    7478/** VID I/O control detection: Fake CPU index input. */
    75 #define NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX        UINT32_C(42)
     79#define NEM_WIN_IOCTL_DETECTOR_FAKE_VP_INDEX                    UINT32_C(42)
    7680/** VID I/O control detection: Fake timeout input. */
    77 #define NEM_WIN_IOCTL_DETECTOR_FAKE_TIMEOUT         UINT32_C(0x00080286)
     81#define NEM_WIN_IOCTL_DETECTOR_FAKE_TIMEOUT                     UINT32_C(0x00080286)
    7882
    7983
     
    105109 * @{ */
    106110static decltype(VidGetHvPartitionId)               *g_pfnVidGetHvPartitionId;
     111static decltype(VidGetPartitionProperty)           *g_pfnVidGetPartitionProperty;
    107112static decltype(VidStartVirtualProcessor)          *g_pfnVidStartVirtualProcessor;
    108113static decltype(VidStopVirtualProcessor)           *g_pfnVidStopVirtualProcessor;
     
    151156#endif
    152157    NEM_WIN_IMPORT(1, false, VidGetHvPartitionId),
     158    NEM_WIN_IMPORT(1, false, VidGetPartitionProperty),
    153159    NEM_WIN_IMPORT(1, false, VidMessageSlotMap),
    154160    NEM_WIN_IMPORT(1, false, VidMessageSlotHandleAndGetNext),
     
    170176/** Info about the VidGetHvPartitionId I/O control interface. */
    171177static NEMWINIOCTL g_IoCtlGetHvPartitionId;
     178/** Info about the VidGetPartitionProperty I/O control interface. */
     179static NEMWINIOCTL g_IoCtlGetPartitionProperty;
    172180/** Info about the VidStartVirtualProcessor I/O control interface. */
    173181static NEMWINIOCTL g_IoCtlStartVirtualProcessor;
     
    374382         * Walk the thunks table(s) looking for NtDeviceIoControlFile.
    375383         */
    376         PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)&pbImage[pImps->FirstThunk]; /* update this. */
    377         PIMAGE_THUNK_DATA pThunk      = pImps->OriginalFirstThunk == 0                  /* read from this. */
    378                                       ? (PIMAGE_THUNK_DATA)&pbImage[pImps->FirstThunk]
    379                                       : (PIMAGE_THUNK_DATA)&pbImage[pImps->OriginalFirstThunk];
    380         while (pThunk->u1.Ordinal != 0)
     384        uintptr_t *puFirstThunk = (uintptr_t *)&pbImage[pImps->FirstThunk]; /* update this. */
     385        if (   pImps->OriginalFirstThunk != 0
     386            && pImps->OriginalFirstThunk != pImps->FirstThunk)
    381387        {
    382             if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32))
     388            uintptr_t const *puOrgThunk = (uintptr_t const *)&pbImage[pImps->OriginalFirstThunk]; /* read from this. */
     389            uintptr_t        cLeft      = (cbImage - (RT_MAX(pImps->FirstThunk, pImps->OriginalFirstThunk)))
     390                                        / sizeof(*puFirstThunk);
     391            while (cLeft-- > 0 && *puOrgThunk != 0)
    383392            {
    384                 AssertReturn(pThunk->u1.Ordinal > 0 && pThunk->u1.Ordinal < cbImage,
    385                              RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad FirstThunk: %#x", pImps->FirstThunk));
    386 
    387                 const char *pszSymbol = (const char *)&pbImage[(uintptr_t)pThunk->u1.AddressOfData + 2];
    388                 if (strcmp(pszSymbol, "NtDeviceIoControlFile") == 0)
     393                if (!(*puOrgThunk & IMAGE_ORDINAL_FLAG64)) /* ASSUMES 64-bit */
    389394                {
    390                     DWORD fOldProt = PAGE_READONLY;
    391                     VirtualProtect(&pFirstThunk->u1.Function, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &fOldProt);
    392                     g_ppfnVidNtDeviceIoControlFile = (decltype(NtDeviceIoControlFile) **)&pFirstThunk->u1.Function;
    393                     /* Don't restore the protection here, so we modify the NtDeviceIoControlFile pointer later. */
     395                    AssertReturn(*puOrgThunk > 0 && *puOrgThunk < cbImage,
     396                                 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "VID.DLL bad thunk entry: %#x", *puOrgThunk));
     397
     398                    const char *pszSymbol = (const char *)&pbImage[*puOrgThunk + 2];
     399                    if (strcmp(pszSymbol, "NtDeviceIoControlFile") == 0)
     400                        g_ppfnVidNtDeviceIoControlFile = (decltype(NtDeviceIoControlFile) **)puFirstThunk;
    394401                }
     402
     403                puOrgThunk++;
     404                puFirstThunk++;
    395405            }
    396 
    397             pThunk++;
    398             pFirstThunk++;
     406        }
     407        else
     408        {
     409            /* No original thunk table, so scan the resolved symbols for a match
     410               with the NtDeviceIoControlFile address. */
     411            uintptr_t const uNeedle = (uintptr_t)g_pfnNtDeviceIoControlFile;
     412            uintptr_t       cLeft   = (cbImage - pImps->FirstThunk) / sizeof(*puFirstThunk);
     413            while (cLeft-- > 0 && *puFirstThunk != 0)
     414            {
     415                if (*puFirstThunk == uNeedle)
     416                    g_ppfnVidNtDeviceIoControlFile = (decltype(NtDeviceIoControlFile) **)puFirstThunk;
     417                puFirstThunk++;
     418            }
    399419        }
    400420    }
    401421
    402     if (*g_ppfnVidNtDeviceIoControlFile)
    403     {
     422    if (g_ppfnVidNtDeviceIoControlFile != NULL)
     423    {
     424        /* Make the thunk writable we can freely modify it. */
     425        DWORD fOldProt = PAGE_READONLY;
     426        VirtualProtect((void *)(uintptr_t)g_ppfnVidNtDeviceIoControlFile, sizeof(uintptr_t), PAGE_EXECUTE_READWRITE, &fOldProt);
     427
    404428#ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    405429        *g_ppfnVidNtDeviceIoControlFile = nemR3WinLogWrapper_NtDeviceIoControlFile;
     
    793817
    794818/**
     819 * Used to fill in g_IoCtlGetHvPartitionId.
     820 */
     821static NTSTATUS WINAPI
     822nemR3WinIoctlDetector_GetPartitionProperty(HANDLE hFile, HANDLE hEvt, PIO_APC_ROUTINE pfnApcCallback, PVOID pvApcCtx,
     823                                           PIO_STATUS_BLOCK pIos, ULONG uFunction, PVOID pvInput, ULONG cbInput,
     824                                           PVOID pvOutput, ULONG cbOutput)
     825{
     826    AssertLogRelMsgReturn(hFile == NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, ("hFile=%p\n", hFile), STATUS_INVALID_PARAMETER_1);
     827    RT_NOREF(hEvt); RT_NOREF(pfnApcCallback); RT_NOREF(pvApcCtx);
     828    AssertLogRelMsgReturn(RT_VALID_PTR(pIos), ("pIos=%p\n", pIos), STATUS_INVALID_PARAMETER_5);
     829    AssertLogRelMsgReturn(cbInput == sizeof(VID_PARTITION_PROPERTY_CODE), ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_8);
     830    AssertLogRelMsgReturn(RT_VALID_PTR(pvInput), ("pvInput=%p\n", pvInput), STATUS_INVALID_PARAMETER_9);
     831    AssertLogRelMsgReturn(*(VID_PARTITION_PROPERTY_CODE *)pvInput == NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_CODE,
     832                          ("*pvInput=%#x, expected %#x\n", *(HV_PARTITION_PROPERTY_CODE *)pvInput,
     833                           NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_CODE), STATUS_INVALID_PARAMETER_9);
     834    AssertLogRelMsgReturn(RT_VALID_PTR(pvOutput), ("pvOutput=%p\n", pvOutput), STATUS_INVALID_PARAMETER_9);
     835    AssertLogRelMsgReturn(cbOutput == sizeof(HV_PARTITION_PROPERTY), ("cbInput=%#x\n", cbInput), STATUS_INVALID_PARAMETER_10);
     836    *(HV_PARTITION_PROPERTY *)pvOutput = NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_VALUE;
     837
     838    g_IoCtlGetPartitionProperty.cbInput   = cbInput;
     839    g_IoCtlGetPartitionProperty.cbOutput  = cbOutput;
     840    g_IoCtlGetPartitionProperty.uFunction = uFunction;
     841
     842    return STATUS_SUCCESS;
     843}
     844
     845
     846/**
    795847 * Used to fill in g_IoCtlStartVirtualProcessor.
    796848 */
     
    936988    decltype(NtDeviceIoControlFile) * const pfnOrg = *g_ppfnVidNtDeviceIoControlFile;
    937989
    938     /* VidGetHvPartitionId - must work due to memory. */
     990    /* VidGetHvPartitionId - must work due to our memory management. */
     991    HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID;
    939992    *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_GetHvPartitionId;
    940     HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID;
    941993    BOOL fRet = g_pfnVidGetHvPartitionId(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, &idHvPartition);
    942994    *g_ppfnVidNtDeviceIoControlFile = pfnOrg;
     
    947999    LogRel(("NEM: VidGetHvPartitionId            -> fun:%#x in:%#x out:%#x\n",
    9481000            g_IoCtlGetHvPartitionId.uFunction, g_IoCtlGetHvPartitionId.cbInput, g_IoCtlGetHvPartitionId.cbOutput));
     1001
     1002    /* VidGetPartitionProperty - must work as it's fallback for VidGetHvPartitionId. */
     1003    HV_PARTITION_PROPERTY uPropValue = ~NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_VALUE;
     1004    *g_ppfnVidNtDeviceIoControlFile = nemR3WinIoctlDetector_GetPartitionProperty;
     1005    fRet = g_pfnVidGetPartitionProperty(NEM_WIN_IOCTL_DETECTOR_FAKE_HANDLE, NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_CODE,
     1006                                        &uPropValue);
     1007    *g_ppfnVidNtDeviceIoControlFile = pfnOrg;
     1008    AssertReturn(   fRet
     1009                 && uPropValue == NEM_WIN_IOCTL_DETECTOR_FAKE_PARTITION_PROPERTY_VALUE
     1010                 && g_IoCtlGetHvPartitionId.uFunction != 0,
     1011                 RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
     1012                               "Problem figuring out VidGetPartitionProperty: fRet=%u uPropValue=%#x dwErr=%u",
     1013                               fRet, uPropValue, GetLastError()) );
     1014    LogRel(("NEM: VidGetPartitionProperty        -> fun:%#x in:%#x out:%#x\n",
     1015            g_IoCtlGetPartitionProperty.uFunction, g_IoCtlGetPartitionProperty.cbInput, g_IoCtlGetPartitionProperty.cbOutput));
    9491016
    9501017    int rcRet = VINF_SUCCESS;
     
    10301097    /* Done. */
    10311098    pVM->nem.s.IoCtlGetHvPartitionId            = g_IoCtlGetHvPartitionId;
     1099    pVM->nem.s.IoCtlGetPartitionProperty        = g_IoCtlGetPartitionProperty;
    10321100    pVM->nem.s.IoCtlStartVirtualProcessor       = g_IoCtlStartVirtualProcessor;
    10331101    pVM->nem.s.IoCtlStopVirtualProcessor        = g_IoCtlStopVirtualProcessor;
     
    13871455
    13881456    /*
    1389      * Set up the partition and create EMTs.
     1457     * Set up the partition.
    13901458     *
    13911459     * Seems like this is where the partition is actually instantiated and we get
     
    13981466                          hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    13991467
    1400     /* Get the handle. */
     1468    /* Get the handle (could also fish this out via VID.DLL NtDeviceIoControlFile intercepting). */
    14011469    HANDLE hPartitionDevice;
    14021470    __try
     
    14141482                          "Failed to get device handle for partition %p: %Rhrc", hPartition, hrc);
    14151483
    1416     HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID;
    1417     if (!g_pfnVidGetHvPartitionId(hPartitionDevice, &idHvPartition))
     1484    /* Test the handle. */
     1485    HV_PARTITION_PROPERTY uValue;
     1486    if (!g_pfnVidGetPartitionProperty(hPartitionDevice, HvPartitionPropertyProcessorVendor, &uValue))
    14181487        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    14191488                          "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)",
    14201489                          hPartition, hPartitionDevice, RTNtLastStatusValue(), RTNtLastErrorValue());
     1490    LogRel(("NEM: HvPartitionPropertyProcessorVendor=%#llx (%lld)\n", uValue, uValue));
     1491
     1492    /*
     1493     * Get the partition ID so we can keep managing our memory the way we've
     1494     * been doing for the last 12+ years.
     1495     *
     1496     * The WHvMapGpaRange/WHvUnmapGpaRange interface is very ill-fitting and
     1497     * very inflexible compared to what we need.  Fortunately, the hypervisor
     1498     * have a much better interface which we are able to use from ring-0.
     1499     * Not pretty, but necessary for the time being.
     1500     */
     1501    HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID;
     1502    if (!g_pfnVidGetHvPartitionId(hPartitionDevice, &idHvPartition))
     1503    {
     1504        if (RTNtLastErrorValue() != ERROR_INVALID_FUNCTION) /* Will try get it later in VMMR0_DO_NEM_INIT_VM_PART_2. */
     1505            return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     1506                              "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)",
     1507                              hPartition, hPartitionDevice, RTNtLastStatusValue(), RTNtLastErrorValue());
     1508        LogRel(("NEM: VidGetHvPartitionId failed with ERROR_NOT_SUPPORTED, will try again later from ring-0...\n"));
     1509        idHvPartition = HV_PARTITION_ID_INVALID;
     1510    }
    14211511    pVM->nem.s.hPartitionDevice = hPartitionDevice;
    14221512    pVM->nem.s.idHvPartition    = idHvPartition;
     
    14841574    if (RT_SUCCESS(rc))
    14851575    {
    1486         LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition));
     1576        LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n",
     1577                hPartitionDevice, pVM->nem.s.idHvPartition));
    14871578
    14881579#if 1
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r86117 r91676  
    195195    /** Info about the VidGetHvPartitionId I/O control interface. */
    196196    NEMWINIOCTL                 IoCtlGetHvPartitionId;
     197    /** Info about the VidGetPartitionProperty I/O control interface. */
     198    NEMWINIOCTL                 IoCtlGetPartitionProperty;
    197199    /** Info about the VidStartVirtualProcessor I/O control interface. */
    198200    NEMWINIOCTL                 IoCtlStartVirtualProcessor;
     
    290292        HV_PARTITION_ID         idPartition;
    291293        HV_VP_INDEX             idCpu;
     294        struct
     295        {
     296            uint64_t            enmProperty;
     297            uint64_t            uValue;
     298        } GetProp;
    292299# ifdef VID_MSHAGN_F_GET_NEXT_MESSAGE
    293300        VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT MsgSlotHandleAndGetNext;
     
    384391    /** Info about the VidGetHvPartitionId I/O control interface. */
    385392    NEMWINIOCTL                 IoCtlGetHvPartitionId;
     393    /** Info about the VidGetPartitionProperty I/O control interface. */
     394    NEMWINIOCTL                 IoCtlGetPartitionProperty;
    386395    /** Info about the VidStartVirtualProcessor I/O control interface. */
    387396    NEMWINIOCTL                 IoCtlStartVirtualProcessor;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette