VirtualBox

Changeset 71075 in vbox


Ignore:
Timestamp:
Feb 20, 2018 9:10:45 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120939
Message:

VMM,SUPDrv: More NEM/win experimentation. bugref:9044

Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/err.h

    r70979 r71075  
    28152815/** NEM init failed. */
    28162816#define VERR_NEM_INIT_FAILED                        (-6802)
     2817/** NEM init failed because of missing kernel API. */
     2818#define VERR_NEM_MISSING_KERNEL_API                 (-6803)
    28172819/** NEM failed to create a native VM instance. */
    2818 #define VERR_NEM_VM_CREATE_FAILED                   (-6803)
     2820#define VERR_NEM_VM_CREATE_FAILED                   (-6804)
     2821/** NEM failed to map page(s) into the VM. */
     2822#define VERR_NEM_MAP_PAGES_FAILED                   (-6805)
     2823/** NEM failed to unmap page(s) into the VM. */
     2824#define VERR_NEM_UNMAP_PAGES_FAILED                 (-6806)
    28192825/** @} */
    28202826
  • trunk/include/VBox/vmm/gvm.h

    r69475 r71075  
    5454        uint8_t             padding[64];
    5555    } gvmm;
     56
     57#ifdef VBOX_WITH_NEM_R0
     58    /** The NEM per vcpu data. */
     59    union
     60    {
     61# ifdef ___NEMInternal_h
     62        struct NEMR0PERVCPU s;
     63# endif
     64        uint8_t             padding[64];
     65    } nem;
     66#endif
    5667} GVMCPU;
    5768/** Pointer to the GVMCPU data. */
     
    107118    } gmm;
    108119
     120#ifdef VBOX_WITH_NEM_R0
     121    /** The NEM per vcpu data. */
     122    union
     123    {
     124# ifdef ___NEMInternal_h
     125        struct NEMR0PERVM   s;
     126# endif
     127        uint8_t             padding[64];
     128    } nem;
     129#endif
     130
    109131    /** The RAWPCIVM per vm data. */
    110132    union
     
    113135        struct RAWPCIPERVM s;
    114136#endif
    115         uint8_t     padding[64];
     137        uint8_t             padding[64];
    116138    } rawpci;
    117 
    118139
    119140    /** GVMCPU array for the configured number of virtual CPUs. */
  • trunk/include/VBox/vmm/nem.h

    r71041 r71075  
    8080/** @} */
    8181
    82 /** @defgroup grp_nem_hc    The NEM host context API
     82
     83/** @defgroup grp_nem_r0    The NEM ring-0 Context API
     84 * @{  */
     85VMMR0_INT_DECL(int)  NEMR0InitVM(PGVM pGVM, PVM pVM);
     86VMMR0_INT_DECL(void) NEMR0CleanupVM(PGVM pGVM);
     87VMMR0_INT_DECL(int)  NEMR0MapPages(PGVM pGVM, PVM pVM, VMCPUID idCpu);
     88VMMR0_INT_DECL(int)  NEMR0UnmapPages(PGVM pGVM, PVM pVM, VMCPUID idCpu);
     89/** @} */
     90
     91
     92/** @defgroup grp_nem_hc    The NEM Host Context API
    8393 * @{
    8494 */
  • trunk/include/VBox/vmm/vm.h

    r71041 r71075  
    176176        struct NEMCPU       s;
    177177#endif
    178         uint8_t             padding[128];       /* multiple of 64 */
     178        uint8_t             padding[256];       /* multiple of 64 */
    179179    } nem;
    180180
     
    265265
    266266    /** Align the following members on page boundary. */
    267     uint8_t                 abAlignment2[1976];
     267    uint8_t                 abAlignment2[1848];
    268268
    269269    /** PGM part. */
  • trunk/include/VBox/vmm/vm.mac

    r70948 r71075  
    6464    .hm                     resb 5824
    6565    .em                     resb 1408
    66     .nem                    resb 128
     66    .nem                    resb 256
    6767    .trpm                   resb 128
    6868    .tm                     resb 384
  • trunk/include/VBox/vmm/vmm.h

    r69107 r71075  
    501501    VMMR0_DO_SRV_END,
    502502
     503    /** Call NEMR0InitVM() (host specific). */
     504    VMMR0_DO_NEM_INIT_VM = 576,
     505    /** Call NEMR0MapPages() (host specific). */
     506    VMMR0_DO_NEM_MAP_PAGES,
     507    /** Call NEMR0UnmapPages() (host specific). */
     508    VMMR0_DO_NEM_UNMAP_PAGES,
     509
    503510    /** Official call we use for testing Ring-0 APIs. */
    504     VMMR0_DO_TESTS,
     511    VMMR0_DO_TESTS = 640,
    505512    /** Test the 32->64 bits switcher. */
    506513    VMMR0_DO_TEST_SWITCHER3264,
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r70917 r71075  
    3939#include <iprt/asm-math.h>
    4040#include <iprt/cpuset.h>
    41 #if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
     41#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
    4242# include <iprt/dbg.h>
    4343#endif
     
    331331    { "RTProcSelf",                             (void *)(uintptr_t)RTProcSelf },
    332332    { "RTR0AssertPanicSystem",                  (void *)(uintptr_t)RTR0AssertPanicSystem },
    333 #if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
    334     { "RTR0DbgKrnlInfoOpen",                    (void *)(uintptr_t)RTR0DbgKrnlInfoOpen },          /* only-darwin, only-solaris */
    335     { "RTR0DbgKrnlInfoQueryMember",             (void *)(uintptr_t)RTR0DbgKrnlInfoQueryMember },   /* only-darwin, only-solaris */
     333#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)
     334    { "RTR0DbgKrnlInfoOpen",                    (void *)(uintptr_t)RTR0DbgKrnlInfoOpen },          /* only-darwin, only-solaris, only-windows */
     335    { "RTR0DbgKrnlInfoQueryMember",             (void *)(uintptr_t)RTR0DbgKrnlInfoQueryMember },   /* only-darwin, only-solaris, only-windows */
    336336# if defined(RT_OS_SOLARIS)
    337337    { "RTR0DbgKrnlInfoQuerySize",               (void *)(uintptr_t)RTR0DbgKrnlInfoQuerySize },     /* only-solaris */
    338338# endif
    339     { "RTR0DbgKrnlInfoQuerySymbol",             (void *)(uintptr_t)RTR0DbgKrnlInfoQuerySymbol },   /* only-darwin, only-solaris */
    340     { "RTR0DbgKrnlInfoRelease",                 (void *)(uintptr_t)RTR0DbgKrnlInfoRelease },       /* only-darwin, only-solaris */
    341     { "RTR0DbgKrnlInfoRetain",                  (void *)(uintptr_t)RTR0DbgKrnlInfoRetain },        /* only-darwin, only-solaris */
     339    { "RTR0DbgKrnlInfoQuerySymbol",             (void *)(uintptr_t)RTR0DbgKrnlInfoQuerySymbol },   /* only-darwin, only-solaris, only-windows */
     340    { "RTR0DbgKrnlInfoRelease",                 (void *)(uintptr_t)RTR0DbgKrnlInfoRelease },       /* only-darwin, only-solaris, only-windows */
     341    { "RTR0DbgKrnlInfoRetain",                  (void *)(uintptr_t)RTR0DbgKrnlInfoRetain },        /* only-darwin, only-solaris, only-windows */
    342342#endif
    343343    { "RTR0MemAreKrnlAndUsrDifferent",          (void *)(uintptr_t)RTR0MemAreKrnlAndUsrDifferent },
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r70917 r71075  
    214214 * @remarks 0x002a0000 is used by 5.1. The next version number must be 0x002b0000.
    215215 */
    216 #define SUPDRV_IOC_VERSION                              0x00290001
     216#define SUPDRV_IOC_VERSION                              0x00290002
    217217
    218218/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r70918 r71075  
    277277        CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    278278        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00290000
    279                                    ? 0x00290001
     279                                   ? 0x00290002
    280280                                   : SUPDRV_IOC_VERSION & 0xffff0000;
    281281        CookieReq.u.In.u32MinVersion = uMinVersion;
  • trunk/src/VBox/VMM/Makefile.kmk

    r70979 r71075  
    829829        VMMR0/VMMR0JmpA-x86.asm
    830830
     831 if1of ($(USERNAME),bird) # experimental.
     832  VMMR0_SOURCES.win.amd64 += VMMR0/NEMR0Native-win.cpp
     833  VMMR0_DEFS.win.amd64    += VBOX_WITH_NATIVE_NEM VBOX_WITH_NEM_R0
     834 endif
     835
    831836 VMMR0_LIBS = \
    832837        $(PATH_STAGE_LIB)/ServicesR0$(VBOX_SUFF_LIB) \
  • trunk/src/VBox/VMM/VMMAll/AllPdbTypeHack.cpp

    r69111 r71075  
    5151#include "../include/EMInternal.h"
    5252#include "../include/IEMInternal.h"
     53#include "../include/NEMInternal.h"
    5354#include "../include/REMInternal.h"
    5455#include "../VMMR0/GMMR0Internal.h"
  • trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp

    r69111 r71075  
    5858#include <VBox/vmm/vmcpuset.h>
    5959#include <VBox/vmm/vmm.h>
     60#ifdef VBOX_WITH_NEM_R0
     61# include <VBox/vmm/nem.h>
     62#endif
    6063#include <VBox/param.h>
    6164#include <VBox/err.h>
     
    12431246
    12441247    GMMR0CleanupVM(pGVM);
     1248#ifdef VBOX_WITH_NEM_R0
     1249    NEMR0CleanupVM(pGVM);
     1250#endif
    12451251
    12461252    AssertCompile((uintptr_t)NIL_RTTHREADCTXHOOK == 0); /* Depends on zero initialized memory working for NIL at the moment. */
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r70917 r71075  
    2727#include <VBox/vmm/pdmapi.h>
    2828#include <VBox/vmm/pgm.h>
     29#ifdef VBOX_WITH_NEM_R0
     30# include <VBox/vmm/nem.h>
     31#endif
    2932#include <VBox/vmm/stam.h>
    3033#include <VBox/vmm/tm.h>
     
    19591962            break;
    19601963#endif
     1964
     1965        /*
     1966         * NEM requests.
     1967         */
     1968#ifdef VBOX_WITH_NEM_R0
     1969# if defined(RT_ARCH_AMD64) && defined(RT_OS_WINDOWS)
     1970        case VMMR0_DO_NEM_INIT_VM:
     1971            if (u64Arg || pReqHdr || idCpu != 0)
     1972                return VERR_INVALID_PARAMETER;
     1973            rc = NEMR0InitVM(pGVM, pVM);
     1974            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     1975            break;
     1976
     1977        case VMMR0_DO_NEM_MAP_PAGES:
     1978            if (u64Arg || pReqHdr || idCpu == NIL_VMCPUID)
     1979                return VERR_INVALID_PARAMETER;
     1980            rc = NEMR0MapPages(pGVM, pVM, idCpu);
     1981            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     1982            break;
     1983
     1984        case VMMR0_DO_NEM_UNMAP_PAGES:
     1985            if (u64Arg || pReqHdr || idCpu == NIL_VMCPUID)
     1986                return VERR_INVALID_PARAMETER;
     1987            rc = NEMR0UnmapPages(pGVM, pVM, idCpu);
     1988            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     1989            break;
     1990# endif
     1991#endif
     1992
    19611993        /*
    19621994         * For profiling.
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71044 r71075  
    55 * Log group 2: Exit logging.
    66 * Log group 3: Log context on exit.
     7 * Log group 5: Ring-3 memory management
     8 * Log group 6: Ring-0 memory management
    79 * Log group 12: API intercepts.
    810 */
     
    2628#define LOG_GROUP LOG_GROUP_NEM
    2729#include <iprt/nt/nt-and-windows.h>
     30#include <iprt/nt/hyperv.h>
    2831#include <WinHvPlatform.h>
    2932
     
    7376#define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys)    \
    7477    ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
     78
     79
     80#define NEM_WIN_USE_HYPERCALLS
    7581
    7682
     
    147153/** @} */
    148154
     155/** @name APIs imported from Vid.dll
     156 * @{ */
     157static BOOL (WINAPI *g_pfnVidGetHvPartitionId)(HANDLE hPartition, HV_PARTITION_ID *pidPartition);
     158/** @} */
     159
    149160
    150161/**
     
    176187    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),
    177188    NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),
     189    NEM_WIN_IMPORT(1, false, VidGetHvPartitionId),
    178190#undef NEM_WIN_IMPORT
    179191};
     
    752764        {
    753765            /*
    754              * Create and initialize a partition.
     766             * Check out our ring-0 capabilities.
    755767             */
    756             rc = nemR3WinInitCreatePartition(pVM, pErrInfo);
     768            rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0 /*idCpu*/, VMMR0_DO_NEM_INIT_VM, 0, NULL);
    757769            if (RT_SUCCESS(rc))
    758770            {
    759                 VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API);
    760                 Log(("NEM: Marked active!\n"));
     771                /*
     772                 * Create and initialize a partition.
     773                 */
     774                rc = nemR3WinInitCreatePartition(pVM, pErrInfo);
     775                if (RT_SUCCESS(rc))
     776                {
     777                    VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API);
     778                    Log(("NEM: Marked active!\n"));
     779                }
    761780            }
    762781        }
     
    862881        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    863882                          "Failed to get device handle for partition %p: %Rhrc", hPartition, hrc);
    864     /** @todo Do a Vid query that uses the handle to check that we've got a
    865      *  working value.  */
     883
     884    HV_PARTITION_ID idHvPartition = HV_PARTITION_ID_INVALID;
     885    if (!g_pfnVidGetHvPartitionId(hPartitionDevice, &idHvPartition))
     886        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     887                          "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)",
     888                          hPartition, hPartitionDevice, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
    866889    pVM->nem.s.hPartitionDevice = hPartitionDevice;
     890    pVM->nem.s.idHvPartition    = idHvPartition;
    867891
    868892    /*
     
    890914    pVM->nem.s.fCreatedEmts = true;
    891915
    892     LogRel(("NEM: Successfully set up partition (device handle %p)\n", hPartitionDevice));
     916    LogRel(("NEM: Successfully set up partition (device handle %p, partition ID %#llx)\n", hPartitionDevice, idHvPartition));
    893917    return VINF_SUCCESS;
    894918}
     
    15881612        if (pPendingInt->fInterruptionPending)
    15891613        {
    1590             Log6(("PendingInterruption: type=%u vector=%#x errcd=%RTbool/%#x unk0=%u unk1=%u\n",
     1614            Log7(("PendingInterruption: type=%u vector=%#x errcd=%RTbool/%#x unk0=%u unk1=%u\n",
    15911615                  pPendingInt->enmInterruptionType, pPendingInt->InterruptionVector, pPendingInt->fDeliverErrCd,
    15921616                  pPendingInt->uErrCd, pPendingInt->fUnknown0, pPendingInt->fUnknown1));
     
    18161840}
    18171841
     1842
    18181843static DECLCALLBACK(int) nemR3WinUnmapOnePageCallback(PVM pVM, RTGCPHYS GCPhys, uint8_t *pu2NemState, void *pvUser)
    18191844{
    18201845    RT_NOREF_PV(pvUser);
     1846#ifdef NEM_WIN_USE_HYPERCALLS
     1847    PVMCPU pVCpu = VMMGetCpu(pVM);
     1848    pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys;
     1849    pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;
     1850    int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
     1851    AssertRC(rc);
     1852    if (RT_SUCCESS(rc))
     1853#else
    18211854    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    18221855    if (SUCCEEDED(hrc))
     1856#endif
     1857    {
     1858        Log5(("NEM GPA unmap all: %RGp (cMappedPages=%u)\n", GCPhys, pVM->nem.s.cMappedPages - 1));
    18231859        *pu2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
     1860    }
    18241861    else
    18251862    {
     1863#ifdef NEM_WIN_USE_HYPERCALLS
     1864        LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));
     1865#else
    18261866        LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    18271867                GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtCurrentTeb()->LastStatusValue,
    18281868                RTNtCurrentTeb()->LastErrorValue, pVM->nem.s.cMappedPages));
     1869#endif
    18291870        *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET;
    18301871    }
     
    19471988     * If this fails, which it does every so often, just unmap everything for now.
    19481989     */
     1990#ifdef NEM_WIN_USE_HYPERCALLS
     1991    pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys;
     1992    pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;
     1993    int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
     1994    AssertRC(rc);
     1995    if (RT_SUCCESS(rc))
     1996#else
    19491997    /** @todo figure out whether we mess up the state or if it's WHv.   */
    19501998    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    19511999    if (SUCCEEDED(hrc))
     2000#endif
    19522001    {
    19532002        pState->fDidSomething = true;
    19542003        pState->fCanResume    = true;
    19552004        pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
    1956         Log5(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp => unmapped[%s]\n", GCPhys, g_apszPageStates[u2State]));
     2005        uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2006        Log5(("NEM GPA unmapped/exit: %RGp (was %s, cMappedPages=%u)\n", GCPhys, g_apszPageStates[u2State], cMappedPages));
    19572007        return VINF_SUCCESS;
    19582008    }
     2009#ifdef NEM_WIN_USE_HYPERCALLS
     2010    LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhys, rc));
     2011    return rc;
     2012#else
    19592013    LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    19602014            GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue,
     
    19682022    pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
    19692023    return VINF_SUCCESS;
     2024#endif
    19702025}
    19712026
     
    21832238    const bool   fSingleStepping = false; /** @todo get this from somewhere. */
    21842239    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    2185     for (;;)
     2240    for (unsigned iLoop = 0;;iLoop++)
    21862241    {
    21872242        /*
     
    23272382        }
    23282383
     2384#ifdef NEM_WIN_USE_HYPERCALLS
    23292385        /* Hack alert! */
    23302386        uint32_t const cMappedPages = pVM->nem.s.cMappedPages;
     
    23362392            Log(("nemR3NativeRunGC: Unmapped all; cMappedPages=%u -> %u\n", cMappedPages, pVM->nem.s.cMappedPages));
    23372393        }
     2394#endif
    23382395
    23392396        /* If any FF is pending, return to the EM loops.  That's okay for the
     
    25042561                                                            PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)
    25052562{
    2506     Assert(pVCpu == NULL);
    2507 
    25082563    /* We'll just unmap the memory. */
    25092564    if (pInfo->u2NemState > NEM_WIN_PAGE_STATE_UNMAPPED)
    25102565    {
     2566#ifdef NEM_WIN_USE_HYPERCALLS
     2567        pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhys;
     2568        pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;
     2569        int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
     2570        AssertRC(rc);
     2571        if (RT_SUCCESS(rc))
     2572#else
    25112573        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
    25122574        if (SUCCEEDED(hrc))
     2575#endif
     2576        {
     2577            uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2578            Log5(("NEM GPA unmapped/A20: %RGp (was %s, cMappedPages=%u)\n", GCPhys, g_apszPageStates[pInfo->u2NemState], cMappedPages));
    25132579            pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
     2580        }
    25142581        else
    25152582        {
     2583#ifdef NEM_WIN_USE_HYPERCALLS
     2584            LogRel(("nemR3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));
     2585            return rc;
     2586#else
    25162587            LogRel(("nemR3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    25172588                    GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
    25182589            return VERR_INTERNAL_ERROR_2;
     2590#endif
    25192591        }
    25202592    }
     
    25292601 * @returns The PGMPhysNemQueryPageInfo result.
    25302602 * @param   pVM             The cross context VM structure.
    2531  * @param   pVCpu           The cross context virtual CPU structure.  Optional.
     2603 * @param   pVCpu           The cross context virtual CPU structure.
    25322604 * @param   GCPhys          The page to unmap.
    25332605 */
    2534 static int nemR3WinUnmapPageForA20Gate(PVM pVM, RTGCPHYS GCPhys)
     2606static int nemR3WinUnmapPageForA20Gate(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
    25352607{
    25362608    PGMPHYSNEMPAGEINFO Info;
    2537     return PGMPhysNemPageInfoChecker(pVM, NULL /*pVCpu*/, GCPhys, false /*fMakeWritable*/, &Info,
     2609    return PGMPhysNemPageInfoChecker(pVM, pVCpu, GCPhys, false /*fMakeWritable*/, &Info,
    25382610                                     nemR3WinUnsetForA20CheckerCallback, NULL);
    25392611}
     
    25582630        pVM->nem.s.fA20Enabled = fEnabled;
    25592631        for (RTGCPHYS GCPhys = _1M; GCPhys < _1M + _64K; GCPhys += X86_PAGE_SIZE)
    2560             nemR3WinUnmapPageForA20Gate(pVM, GCPhys);
     2632            nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys);
    25612633    }
    25622634}
     
    26192691        if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)
    26202692        {
     2693#ifdef NEM_WIN_USE_HYPERCALLS
     2694            PVMCPU pVCpu = VMMGetCpu(pVM);
     2695            pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhysDst;
     2696            pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;
     2697            int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
     2698            AssertRC(rc);
     2699            if (RT_SUCCESS(rc))
     2700            {
     2701                *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
     2702                uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2703                if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)
     2704                {
     2705                    Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n",
     2706                          GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
     2707                    return VINF_SUCCESS;
     2708                }
     2709            }
     2710            else
     2711            {
     2712                LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
     2713                return rc;
     2714            }
     2715#else
    26212716            HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE);
    26222717            if (SUCCEEDED(hrc))
     
    26262721                if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)
    26272722                {
    2628                     Log5(("nemR3NativeSetPhysPage: %RGp => unmapped (total %u)\n", GCPhysDst, cMappedPages));
     2723                    Log5(("NEM GPA unmapped/set: %RGp (was %s, cMappedPages=%u)\n",
     2724                          GCPhysDst, g_apszPageStates[u2OldState], cMappedPages));
    26292725                    return VINF_SUCCESS;
    26302726                }
     
    26362732                return VERR_NEM_INIT_FAILED;
    26372733            }
     2734#endif
    26382735        }
    26392736    }
     
    26442741    if (fPageProt & NEM_PAGE_PROT_WRITE)
    26452742    {
     2743#ifdef NEM_WIN_USE_HYPERCALLS
     2744        RT_NOREF_PV(GCPhysSrc);
     2745        PVMCPU pVCpu = VMMGetCpu(pVM);
     2746        pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc = GCPhysSrc;
     2747        pVCpu->nem.s.Hypercall.MapPages.GCPhysDst = GCPhysDst;
     2748        pVCpu->nem.s.Hypercall.MapPages.cPages    = 1;
     2749        pVCpu->nem.s.Hypercall.MapPages.fFlags    = HV_MAP_GPA_READABLE   | HV_MAP_GPA_WRITABLE
     2750                                                  | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN;
     2751        int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_MAP_PAGES, 0, NULL);
     2752        AssertRC(rc);
     2753        if (RT_SUCCESS(rc))
     2754        {
     2755            *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
     2756            uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2757            Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
     2758                  GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
     2759            return VINF_SUCCESS;
     2760        }
     2761        LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
     2762        return rc;
     2763#else
    26462764        void *pvPage;
    26472765        int rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhysSrc, &pvPage);
     
    26542772                *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    26552773                uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    2656                 Log5(("nemR3NativeSetPhysPage: %RGp => writable (total %u)\n", GCPhysDst, cMappedPages));
     2774                Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
     2775                      GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    26572776                return VINF_SUCCESS;
    26582777            }
     
    26632782        LogRel(("nemR3NativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    26642783        return rc;
     2784#endif
    26652785    }
    26662786
    26672787    if (fPageProt & NEM_PAGE_PROT_READ)
    26682788    {
     2789#ifdef NEM_WIN_USE_HYPERCALLS
     2790        PVMCPU pVCpu = VMMGetCpu(pVM);
     2791        pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc = GCPhysSrc;
     2792        pVCpu->nem.s.Hypercall.MapPages.GCPhysDst = GCPhysDst;
     2793        pVCpu->nem.s.Hypercall.MapPages.cPages    = 1;
     2794        pVCpu->nem.s.Hypercall.MapPages.fFlags    = HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_EXECUTABLE_AGAIN;
     2795        int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_MAP_PAGES, 0, NULL);
     2796        AssertRC(rc);
     2797        if (RT_SUCCESS(rc))
     2798        {
     2799            *pu2State = NEM_WIN_PAGE_STATE_READABLE;
     2800            uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2801            Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
     2802                  GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
     2803            return VINF_SUCCESS;
     2804        }
     2805        LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
     2806        return rc;
     2807#else
    26692808        const void *pvPage;
    26702809        int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhysSrc, &pvPage);
     
    26772816                *pu2State = NEM_WIN_PAGE_STATE_READABLE;
    26782817                uint32_t cMappedPages = ASMAtomicIncU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
    2679                 Log5(("nemR3NativeSetPhysPage: %RGp => read+exec (total %u)\n", GCPhysDst, cMappedPages));
     2818                Log5(("NEM GPA mapped/set: %RGp %s (was %s, cMappedPages=%u)\n",
     2819                      GCPhysDst, g_apszPageStates[u2NewState], g_apszPageStates[u2OldState], cMappedPages));
    26802820                return VINF_SUCCESS;
    26812821            }
     
    26862826        LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    26872827        return rc;
     2828#endif
    26882829    }
    26892830
     
    27032844    }
    27042845
    2705     HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE);
     2846#ifdef NEM_WIN_USE_HYPERCALLS
     2847    PVMCPU pVCpu = VMMGetCpu(pVM);
     2848    pVCpu->nem.s.Hypercall.UnmapPages.GCPhys = GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
     2849    pVCpu->nem.s.Hypercall.UnmapPages.cPages = 1;
     2850    int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, pVCpu->idCpu, VMMR0_DO_NEM_UNMAP_PAGES, 0, NULL);
     2851    AssertRC(rc);
     2852    if (RT_SUCCESS(rc))
     2853    {
     2854        uint32_t cMappedPages = ASMAtomicDecU32(&pVM->nem.s.cMappedPages); NOREF(cMappedPages);
     2855        Log5(("NEM GPA unmapped/just: %RGp (was %s, cMappedPages=%u)\n", GCPhysDst, g_apszPageStates[*pu2State], cMappedPages));
     2856        *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
     2857        return VINF_SUCCESS;
     2858    }
     2859    LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp rc=%Rrc\n", GCPhysDst, rc));
     2860    return rc;
     2861#else
     2862    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE);
    27062863    if (SUCCEEDED(hrc))
    27072864    {
     
    27142871            GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
    27152872    return VERR_INTERNAL_ERROR_3;
     2873#endif
    27162874}
    27172875
     
    27322890    {
    27332891        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    2734         rc = nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2892        rc = nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    27352893        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys) && RT_SUCCESS(rc))
    27362894            rc = nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     
    27652923    {
    27662924        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    2767         nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2925        nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    27682926        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    27692927            nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
     
    27952953    {
    27962954        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
    2797         nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2955        nemR3WinUnmapPageForA20Gate(pVM, pVCpu, GCPhys | RT_BIT_32(20));
    27982956        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
    27992957            nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r71043 r71075  
    2525#include <VBox/vmm/stam.h>
    2626#include <VBox/vmm/vmapi.h>
     27#ifdef RT_OS_WINDOWS
     28#include <iprt/nt/hyperv.h>
     29#endif
    2730
    2831RT_C_DECLS_BEGIN
     
    8386     * controls. */
    8487    RTR3PTR                     hPartitionDevice;
     88    /** The Hyper-V partition ID.   */
     89    uint64_t                    idHvPartition;
    8590
    8691    /** Number of currently mapped pages. */
     
    105110    /** NEMCPU_MAGIC. */
    106111    uint32_t                    u32Magic;
    107 
     112#ifdef RT_OS_WINDOWS
     113    /** Parameters for making Hyper-V hypercalls. */
     114    union
     115    {
     116        uint8_t                 ab[64];
     117        /** Arguments for NEMR0MapPages (HvCallMapGpaPages). */
     118        struct
     119        {
     120            RTGCPHYS            GCPhysSrc;
     121            RTGCPHYS            GCPhysDst; /**< Same as GCPhysSrc except maybe when the A20 gate is disabled. */
     122            uint32_t            cPages;
     123            HV_MAP_GPA_FLAGS    fFlags;
     124        }                       MapPages;
     125        /** Arguments for NEMR0UnmapPages (HvCallUnmapGpaPages). */
     126        struct
     127        {
     128            RTGCPHYS            GCPhys;
     129            uint32_t            cPages;
     130        }                       UnmapPages;
     131    } Hypercall;
     132#endif
    108133} NEMCPU;
    109134/** Pointer to NEM VMCPU instance data. */
     
    114139/** NEMCPU::u32Magic value after termination. */
    115140#define NEMCPU_MAGIC_DEAD       UINT32_C(0xdead2222)
     141
     142
     143#ifdef IN_RING0
     144
     145/**
     146 * NEM GVMCPU instance data.
     147 */
     148typedef struct NEMR0PERVCPU
     149{
     150# ifdef RT_OS_WINDOWS
     151    /** @name Hypercall input/ouput page.
     152     * @{ */
     153    /** Host physical address of the hypercall input/output page. */
     154    RTHCPHYS                    HCPhysHypercallData;
     155    /** Pointer to the hypercall input/output page. */
     156    uint8_t                    *pbHypercallData;
     157    /** Handle to the memory object of the hypercall input/output page. */
     158    RTR0MEMOBJ                  hHypercallDataMemObj;
     159    /** @} */
     160# endif
     161} NEMR0PERVCPU;
     162
     163/**
     164 * NEM GVM instance data.
     165 */
     166typedef struct NEMR0PERVM
     167{
     168# ifdef RT_OS_WINDOWS
     169    /** The partition ID. */
     170    uint64_t                    idHvPartition;
     171# endif
     172} NEMR0PERVM;
     173
     174#endif /* IN_RING*/
     175
    116176
    117177#ifdef IN_RING3
     
    148208
    149209
     210#ifdef RT_OS_WINDOWS
     211/** Maximum number of pages we can map in a single NEMR0MapPages call. */
     212# define NEM_MAX_MAP_PAGES      ((PAGE_SIZE - RT_UOFFSETOF(HV_INPUT_MAP_GPA_PAGES, PageList)) / sizeof(HV_SPA_PAGE_NUMBER))
     213/** Maximum number of pages we can unmap in a single NEMR0UnmapPages call. */
     214# define NEM_MAX_UNMAP_PAGES    4095
     215
     216#endif
    150217/** @} */
    151218
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