VirtualBox

Changeset 71129 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Feb 26, 2018 3:58:50 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121015
Message:

VMM/NEM/win: Reimplemented virtual process API, optimizing the cancel case and prepping for doing this from ring-0. bugref:9044

Location:
trunk/src/VBox/VMM/VMMR3
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r71087 r71129  
    2929#include <iprt/nt/nt-and-windows.h>
    3030#include <iprt/nt/hyperv.h>
     31#include <iprt/nt/vid.h>
    3132#include <WinHvPlatform.h>
    3233
     
    7879
    7980
    80 #define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    81 #define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    82 
    8381
    8482/*********************************************************************************************************************************
    8583*   Structures and Typedefs                                                                                                      *
    8684*********************************************************************************************************************************/
    87 /** WHvRegisterInterruptState layout, reconstructed from the v7.1 DDK. */
    88 typedef union MISSINGINTERUPTSTATEREG
    89 {
    90     /** 64-bit view. */
    91     uint64_t au64[2];
    92     struct /* unamed */
    93     {
    94         uint64_t fInterruptShadow : 1;
    95         uint64_t fNmiMasked : 2;
    96         uint64_t uReserved0 : 61;
    97         uint64_t uReserved1;
    98     };
    99 } MISSINGINTERUPTSTATEREG;
    100 AssertCompileSize(MISSINGINTERUPTSTATEREG, 16);
    101 
    10285
    10386
     
    11699static decltype(WHvUnmapGpaRange) *                 g_pfnWHvUnmapGpaRange;
    117100static decltype(WHvTranslateGva) *                  g_pfnWHvTranslateGva;
     101#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    118102static decltype(WHvCreateVirtualProcessor) *        g_pfnWHvCreateVirtualProcessor;
    119103static decltype(WHvDeleteVirtualProcessor) *        g_pfnWHvDeleteVirtualProcessor;
     
    123107static decltype(WHvGetVirtualProcessorRegisters) *  g_pfnWHvGetVirtualProcessorRegisters;
    124108static decltype(WHvSetVirtualProcessorRegisters) *  g_pfnWHvSetVirtualProcessorRegisters;
     109#endif
    125110/** @} */
    126111
    127112/** @name APIs imported from Vid.dll
    128113 * @{ */
    129 static BOOL (WINAPI *g_pfnVidGetHvPartitionId)(HANDLE hPartition, HV_PARTITION_ID *pidPartition);
     114static decltype(VidGetHvPartitionId)               *g_pfnVidGetHvPartitionId;
     115static decltype(VidStartVirtualProcessor)          *g_pfnVidStartVirtualProcessor;
     116static decltype(VidStopVirtualProcessor)           *g_pfnVidStopVirtualProcessor;
     117static decltype(VidMessageSlotMap)                 *g_pfnVidMessageSlotMap;
     118static decltype(VidMessageSlotHandleAndGetNext)    *g_pfnVidMessageSlotHandleAndGetNext;
     119#ifdef LOG_ENABLED
     120static decltype(VidGetVirtualProcessorRunningStatus) *g_pfnVidGetVirtualProcessorRunningStatus;
     121#endif
    130122/** @} */
    131123
     
    152144    NEM_WIN_IMPORT(0, false, WHvUnmapGpaRange),
    153145    NEM_WIN_IMPORT(0, false, WHvTranslateGva),
     146#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    154147    NEM_WIN_IMPORT(0, false, WHvCreateVirtualProcessor),
    155148    NEM_WIN_IMPORT(0, false, WHvDeleteVirtualProcessor),
    156149    NEM_WIN_IMPORT(0, false, WHvRunVirtualProcessor),
     150    NEM_WIN_IMPORT(0, false, WHvCancelRunVirtualProcessor),
    157151    NEM_WIN_IMPORT(0, false, WHvGetRunExitContextSize),
    158     NEM_WIN_IMPORT(0, false, WHvCancelRunVirtualProcessor),
    159152    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),
    160153    NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),
     154#endif
    161155    NEM_WIN_IMPORT(1, false, VidGetHvPartitionId),
     156    NEM_WIN_IMPORT(1, false, VidMessageSlotMap),
     157    NEM_WIN_IMPORT(1, false, VidMessageSlotHandleAndGetNext),
     158    NEM_WIN_IMPORT(1, false, VidStartVirtualProcessor),
     159    NEM_WIN_IMPORT(1, false, VidStopVirtualProcessor),
     160#ifdef LOG_ENABLED
     161    NEM_WIN_IMPORT(1, false, VidGetVirtualProcessorRunningStatus),
     162#endif
    162163#undef NEM_WIN_IMPORT
    163164};
     
    202203
    203204/** The real NtDeviceIoControlFile API in NTDLL.   */
    204 static decltype(NtDeviceIoControlFile) *g_pfnNtDeviceIoControlFile;
     205static decltype(NtDeviceIoControlFile)       *g_pfnNtDeviceIoControlFile;
     206/** Mapping slot for CPU #0.
     207 * @{  */
     208static VID_MESSAGE_MAPPING_HEADER            *g_pMsgSlotMapping = NULL;
     209static const HV_MESSAGE_HEADER               *g_pHvMsgHdr;
     210static const HV_X64_INTERCEPT_MESSAGE_HEADER *g_pX64MsgHdr;
     211/** @} */
     212
    205213
    206214/**
     
    214222                                         PVOID pvOutput, ULONG cbOutput)
    215223{
     224    char szFunction[32];
     225    const char *pszFunction;
     226    switch (uFunction)
     227    {
     228        case 0x2210cb: pszFunction = "VidMessageSlotHandleAndGetNext"; break;
     229        case 0x2210cc: pszFunction = "VidMessageSlotMap"; break;
     230        case 0x221164: pszFunction = "VidStopVirtualProcessor"; break;
     231        case 0x221158: pszFunction = "VidStartVirtualProcessor"; break;
     232        case 0x2210a7: pszFunction = "VidGetVirtualProcessorState"; break;
     233        case 0x221153: pszFunction = "VidSetVirtualProcessorState"; break;
     234        default:
     235            RTStrPrintf(szFunction, sizeof(szFunction), "%#x", uFunction);
     236            pszFunction = szFunction;
     237            break;
     238    }
     239
     240    if (cbInput > 0 && pvInput)
     241        Log12(("VID!NtDeviceIoControlFile: %s/input: %.*Rhxs\n", pszFunction, RT_MIN(cbInput, 32), pvInput));
    216242    NTSTATUS rcNt = g_pfnNtDeviceIoControlFile(hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, uFunction,
    217243                                               pvInput, cbInput, pvOutput, cbOutput);
    218244    if (!hEvt && !pfnApcCallback && !pvApcCtx)
    219         Log12(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%#x Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
    220                hFile, pIos, pIos->Status, pIos->Information, uFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     245        Log12(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
     246               hFile, pIos, pIos->Status, pIos->Information, pszFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
    221247    else
    222         Log12(("VID!NtDeviceIoControlFile: hFile=%#zx hEvt=%#zx Apc=%p/%p pIos=%p->{s:%#x, i:%#zx} uFunction=%#x Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
    223                hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, uFunction,
     248        Log12(("VID!NtDeviceIoControlFile: hFile=%#zx hEvt=%#zx Apc=%p/%p pIos=%p->{s:%#x, i:%#zx} uFunction=%s Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
     249               hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, pszFunction,
    224250               pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     251    if (cbOutput > 0 && pvOutput)
     252    {
     253        Log12(("VID!NtDeviceIoControlFile: %s/output: %.*Rhxs\n", pszFunction, RT_MIN(cbOutput, 32), pvOutput));
     254        if (uFunction == 0x2210cc && g_pMsgSlotMapping == NULL && cbOutput >= sizeof(void *))
     255        {
     256            g_pMsgSlotMapping = *(VID_MESSAGE_MAPPING_HEADER **)pvOutput;
     257            g_pHvMsgHdr       = (const HV_MESSAGE_HEADER               *)(g_pMsgSlotMapping + 1);
     258            g_pX64MsgHdr      = (const HV_X64_INTERCEPT_MESSAGE_HEADER *)(g_pHvMsgHdr + 1);
     259            Log12(("VID!NtDeviceIoControlFile: Message slot mapping: %p\n", g_pMsgSlotMapping));
     260        }
     261    }
     262    if (g_pMsgSlotMapping && (uFunction == 0x2210cb || uFunction == 0x2210cc || uFunction == 0x221164))
     263        Log12(("VID!NtDeviceIoControlFile: enmVidMsgType=%#x cb=%#x msg=%#x payload=%u cs:rip=%04x:%08RX64 (%s)\n",
     264               g_pMsgSlotMapping->enmVidMsgType, g_pMsgSlotMapping->cbMessage,
     265               g_pHvMsgHdr->MessageType, g_pHvMsgHdr->PayloadSize,
     266               g_pX64MsgHdr->CsSegment.Selector, g_pX64MsgHdr->Rip, pszFunction));
     267
    225268    return rcNt;
    226269}
     
    304347    Assert(fSuccess);
    305348}
    306 #endif
    307 
     349
     350#endif /* NEM_WIN_INTERCEPT_NT_IO_CTLS */
    308351
    309352
     
    456499        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    457500                             "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc (Last=%#x/%u)",
    458                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     501                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    459502    if (!Caps.HypervisorPresent)
    460503    {
     
    475518        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    476519                             "WHvGetCapability/WHvCapabilityCodeExtendedVmExits failed: %Rhrc (Last=%#x/%u)",
    477                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     520                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    478521    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeExtendedVmExits", "%'#018RX64", Caps.ExtendedVmExits.AsUINT64);
    479522    pVM->nem.s.fExtendedMsrExit   = RT_BOOL(Caps.ExtendedVmExits.X64MsrExit);
     
    495538        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    496539                             "WHvGetCapability/WHvCapabilityCodeFeatures failed: %Rhrc (Last=%#x/%u)",
    497                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     540                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    498541    if (Caps.Features.AsUINT64 & ~(uint64_t)0)
    499542        LogRel(("NEM: Warning! Unknown feature definitions: %#RX64\n", Caps.Features.AsUINT64));
     
    508551        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    509552                             "WHvGetCapability/WHvCapabilityCodeProcessorVendor failed: %Rhrc (Last=%#x/%u)",
    510                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     553                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    511554    switch (Caps.ProcessorVendor)
    512555    {
     
    533576        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    534577                             "WHvGetCapability/WHvCapabilityCodeProcessorFeatures failed: %Rhrc (Last=%#x/%u)",
    535                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     578                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    536579    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorFeatures", "%'#018RX64", Caps.ProcessorFeatures.AsUINT64);
    537580#define NEM_LOG_REL_CPU_FEATURE(a_Field)    NEM_LOG_REL_CAP_SUB(#a_Field, Caps.ProcessorFeatures.a_Field)
     
    592635        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    593636                             "WHvGetCapability/WHvCapabilityCodeProcessorClFlushSize failed: %Rhrc (Last=%#x/%u)",
    594                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     637                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    595638    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorClFlushSize", "2^%u", Caps.ProcessorClFlushSize);
    596639    if (Caps.ProcessorClFlushSize < 8 && Caps.ProcessorClFlushSize > 9)
     
    650693    if (FAILED(hrc))
    651694        return RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED, "WHvCreatePartition failed with %Rhrc (Last=%#x/%u)",
    652                              hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     695                             hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    653696
    654697    int rc;
     
    696739        rc = RTErrInfoSetF(pErrInfo, VERR_NEM_VM_CREATE_FAILED,
    697740                           "Failed setting WHvPartitionPropertyCodeProcessorCount to %u: %Rhrc (Last=%#x/%u)",
    698                            pVM->cCpus, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     741                           pVM->cCpus, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    699742    WHvDeletePartition(hPartition);
    700743
     
    799842        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    800843                          "Failed to set WHvPartitionPropertyCodeProcessorVendor to %u: %Rhrc (Last=%#x/%u)",
    801                           Property.ProcessorVendor, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     844                          Property.ProcessorVendor, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    802845
    803846    /* Not sure if we really need to set the cache line flush size. */
     
    809852        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    810853                          "Failed to set WHvPartitionPropertyCodeProcessorClFlushSize to %u: %Rhrc (Last=%#x/%u)",
    811                           pVM->nem.s.cCacheLineFlushShift, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     854                          pVM->nem.s.cCacheLineFlushShift, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    812855
    813856    /*
     
    824867        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    825868                          "Failed to set WHvPartitionPropertyCodeProcessorFeatures to %'#RX64: %Rhrc (Last=%#x/%u)",
    826                           pVM->nem.s.uCpuFeatures.u64, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     869                          pVM->nem.s.uCpuFeatures.u64, hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    827870
    828871    /*
     
    836879        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    837880                          "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)",
    838                           hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     881                          hrc, RTNtLastStatusValue(), RTNtLastErrorValue());
    839882
    840883    /* Get the handle. */
     
    858901        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    859902                          "Failed to get device handle and/or partition ID for %p (hPartitionDevice=%p, Last=%#x/%u)",
    860                           hPartition, hPartitionDevice, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue);
     903                          hPartition, hPartitionDevice, RTNtLastStatusValue(), RTNtLastErrorValue());
    861904    pVM->nem.s.hPartitionDevice = hPartitionDevice;
    862905    pVM->nem.s.idHvPartition    = idHvPartition;
    863906
    864907    /*
    865      * Create EMTs.
     908     * Setup the EMTs.
    866909     */
    867910    VMCPUID iCpu;
    868911    for (iCpu = 0; iCpu < pVM->cCpus; iCpu++)
    869912    {
     913        PVMCPU pVCpu = &pVM->aCpus[iCpu];
     914
     915        pVCpu->nem.s.hNativeThreadHandle = (RTR3PTR)RTThreadGetNativeHandle(VMR3GetThreadHandle(pVCpu->pUVCpu));
     916        Assert((HANDLE)pVCpu->nem.s.hNativeThreadHandle != INVALID_HANDLE_VALUE);
     917
     918#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     919        VID_MAPPED_MESSAGE_SLOT MappedMsgSlot = { NULL, UINT32_MAX, UINT32_MAX };
     920        if (g_pfnVidMessageSlotMap(hPartitionDevice, &MappedMsgSlot, iCpu))
     921        {
     922            AssertLogRelMsg(MappedMsgSlot.iCpu == iCpu && MappedMsgSlot.uParentAdvisory == UINT32_MAX,
     923                            ("%#x %#x (iCpu=%#x)\n", MappedMsgSlot.iCpu, MappedMsgSlot.uParentAdvisory, iCpu));
     924            pVCpu->nem.s.pvMsgSlotMapping = MappedMsgSlot.pMsgBlock;
     925        }
     926        else
     927        {
     928            NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     929            DWORD const    dwErrLast = RTNtLastErrorValue();
     930            return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     931                              "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
     932        }
     933#else
    870934        hrc = WHvCreateVirtualProcessor(hPartition, iCpu, 0 /*fFlags*/);
    871935        if (FAILED(hrc))
    872936        {
    873             NTSTATUS const rcNtLast  = RTNtCurrentTeb()->LastStatusValue;
    874             DWORD const    dwErrLast = RTNtCurrentTeb()->LastErrorValue;
     937            NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     938            DWORD const    dwErrLast = RTNtLastErrorValue();
    875939            while (iCpu-- > 0)
    876940            {
    877941                HRESULT hrc2 = WHvDeleteVirtualProcessor(hPartition, iCpu);
    878942                AssertLogRelMsg(SUCCEEDED(hrc2), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    879                                                   hPartition, iCpu, hrc2, RTNtCurrentTeb()->LastStatusValue,
    880                                                   RTNtCurrentTeb()->LastErrorValue));
     943                                                  hPartition, iCpu, hrc2, RTNtLastStatusValue(),
     944                                                  RTNtLastErrorValue()));
    881945            }
    882946            return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    883947                              "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
    884948        }
     949#endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */
    885950    }
    886951    pVM->nem.s.fCreatedEmts = true;
     
    912977        while (iCpu-- > 0)
    913978        {
     979#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     980            pVM->aCpus[iCpu].nem.s.pvMsgSlotMapping = NULL;
     981#else
    914982            HRESULT hrc = WHvDeleteVirtualProcessor(hPartition, iCpu);
    915983            AssertLogRelMsg(SUCCEEDED(hrc), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    916                                              hPartition, iCpu, hrc, RTNtCurrentTeb()->LastStatusValue,
    917                                              RTNtCurrentTeb()->LastErrorValue));
     984                                             hPartition, iCpu, hrc, RTNtLastStatusValue(),
     985                                             RTNtLastErrorValue()));
     986#endif
    918987        }
    919988        WHvDeletePartition(hPartition);
     
    12931362    AssertLogRelMsgFailed(("WHvSetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    12941363                           pVM->nem.s.hPartition, pVCpu->idCpu, iReg,
    1295                            hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1364                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    12961365    return VERR_INTERNAL_ERROR;
    12971366#endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     
    16661735    AssertLogRelMsgFailed(("WHvGetVirtualProcessorRegisters(%p, %u,,%u,) -> %Rhrc (Last=%#x/%u)\n",
    16671736                           pVM->nem.s.hPartition, pVCpu->idCpu, cRegs,
    1668                            hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1737                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    16691738    return VERR_INTERNAL_ERROR;
    16701739#endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     
    16731742
    16741743#ifdef LOG_ENABLED
     1744/**
     1745 * Get the virtual processor running status.
     1746 */
     1747DECLINLINE(VID_PROCESSOR_STATUS) nemR3WinCpuGetRunningStatus(PVMCPU pVCpu)
     1748{
     1749    RTERRVARS Saved;
     1750    RTErrVarsSave(&Saved);
     1751
     1752    /*
     1753     * This API is disabled in release builds, it seems.  On build 17101 it requires
     1754     * the following patch to be enabled (windbg): eb vid+12180 0f 84 98 00 00 00
     1755     */
     1756    VID_PROCESSOR_STATUS enmCpuStatus = VidProcessorStatusUndefined;
     1757    NTSTATUS rcNt = g_pfnVidGetVirtualProcessorRunningStatus(pVCpu->pVMR3->nem.s.hPartitionDevice, pVCpu->idCpu, &enmCpuStatus);
     1758    AssertRC(rcNt);
     1759
     1760    RTErrVarsRestore(&Saved);
     1761    return enmCpuStatus;
     1762}
     1763#endif
     1764
     1765
     1766#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1767
     1768/**
     1769 * Our own WHvCancelRunVirtualProcessor that can later be moved to ring-0.
     1770 *
     1771 * This is an experiment only.
     1772 *
     1773 * @returns VBox status code.
     1774 * @param   pVM             The cross context VM structure.
     1775 * @param   pVCpu           The cross context virtual CPU structure of the
     1776 *                          calling EMT.
     1777 */
     1778static int nemR3WinCancelRunVirtualProcessor(PVM pVM, PVMCPU pVCpu)
     1779{
     1780    /*
     1781     * Work the state.
     1782     *
     1783     * From the looks of things, we should let the EMT call VidStopVirtualProcessor.
     1784     * So, we just need to modify the state and kick the EMT if it's waiting on
     1785     * messages.  For the latter we use QueueUserAPC / KeAlterThread.
     1786     */
     1787    for (;;)
     1788    {
     1789        VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu);
     1790        switch (enmState)
     1791        {
     1792            case VMCPUSTATE_STARTED_EXEC_NEM:
     1793                if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM))
     1794                {
     1795                    Log8(("nemR3WinCancelRunVirtualProcessor: Switched %u to canceled state\n", pVCpu->idCpu));
     1796                    return VINF_SUCCESS;
     1797                }
     1798                break;
     1799
     1800            case VMCPUSTATE_STARTED_EXEC_NEM_WAIT:
     1801            {
     1802                if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
     1803                {
     1804                    NTSTATUS rcNt = NtAlertThread(pVCpu->nem.s.hNativeThreadHandle);
     1805                    Log8(("nemR3WinCancelRunVirtualProcessor: Alerted %u: %#x\n", pVCpu->idCpu, rcNt));
     1806                    Assert(rcNt == STATUS_SUCCESS);
     1807                    if (NT_SUCCESS(rcNt))
     1808                        return VINF_SUCCESS;
     1809                    AssertLogRelMsgFailedReturn(("NtAlertThread failed: %#x\n", rcNt), RTErrConvertFromNtStatus(rcNt));
     1810                }
     1811                break;
     1812            }
     1813
     1814            default:
     1815                return VINF_SUCCESS;
     1816        }
     1817
     1818        ASMNopPause();
     1819        RT_NOREF(pVM);
     1820    }
     1821}
     1822
     1823
     1824/**
     1825 * Fills in WHV_VP_EXIT_CONTEXT from HV_X64_INTERCEPT_MESSAGE_HEADER.
     1826 */
     1827DECLINLINE(void) nemR3WinConvertX64MsgHdrToVpExitCtx(HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr, WHV_VP_EXIT_CONTEXT *pCtx)
     1828{
     1829    pCtx->ExecutionState.AsUINT16   = pHdr->ExecutionState.AsUINT16;
     1830    pCtx->InstructionLength         = pHdr->InstructionLength;
     1831    pCtx->Cs.Base                   = pHdr->CsSegment.Base;
     1832    pCtx->Cs.Limit                  = pHdr->CsSegment.Limit;
     1833    pCtx->Cs.Selector               = pHdr->CsSegment.Selector;
     1834    pCtx->Cs.Attributes             = pHdr->CsSegment.Attributes;
     1835    pCtx->Rip                       = pHdr->Rip;
     1836    pCtx->Rflags                    = pHdr->Rflags;
     1837}
     1838
     1839
     1840/**
     1841 * Convert hyper-V exit message to the WinHvPlatform structures.
     1842 *
     1843 * @returns VBox status code
     1844 * @param   pMsgHdr         The message to convert.
     1845 * @param   pExitCtx        The output structure. Assumes zeroed.
     1846 */
     1847static int nemR3WinRunVirtualProcessorConvertPending(HV_MESSAGE_HEADER const *pMsgHdr, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx)
     1848{
     1849    switch (pMsgHdr->MessageType)
     1850    {
     1851        case HvMessageTypeUnmappedGpa:
     1852        case HvMessageTypeGpaIntercept:
     1853        {
     1854            PCHV_X64_MEMORY_INTERCEPT_MESSAGE pMemMsg = (PCHV_X64_MEMORY_INTERCEPT_MESSAGE)(pMsgHdr + 1);
     1855            Assert(pMsgHdr->PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment));
     1856
     1857            pExitCtx->ExitReason                            = WHvRunVpExitReasonMemoryAccess;
     1858            nemR3WinConvertX64MsgHdrToVpExitCtx(&pMemMsg->Header, &pExitCtx->MemoryAccess.VpContext);
     1859            pExitCtx->MemoryAccess.InstructionByteCount     = pMemMsg->InstructionByteCount;
     1860            ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[0] = ((uint64_t const *)pMemMsg->InstructionBytes)[0];
     1861            ((uint64_t *)pExitCtx->MemoryAccess.InstructionBytes)[1] = ((uint64_t const *)pMemMsg->InstructionBytes)[1];
     1862
     1863            pExitCtx->MemoryAccess.AccessInfo.AccessType    = pMemMsg->Header.InterceptAccessType;
     1864            pExitCtx->MemoryAccess.AccessInfo.GpaUnmapped   = pMsgHdr->MessageType == HvMessageTypeUnmappedGpa;
     1865            pExitCtx->MemoryAccess.AccessInfo.GvaValid      = pMemMsg->MemoryAccessInfo.GvaValid;
     1866            pExitCtx->MemoryAccess.AccessInfo.Reserved      = pMemMsg->MemoryAccessInfo.Reserved;
     1867            pExitCtx->MemoryAccess.Gpa                      = pMemMsg->GuestPhysicalAddress;
     1868            pExitCtx->MemoryAccess.Gva                      = pMemMsg->GuestVirtualAddress;
     1869            return VINF_SUCCESS;
     1870        }
     1871
     1872        case HvMessageTypeX64IoPortIntercept:
     1873        {
     1874            PCHV_X64_IO_PORT_INTERCEPT_MESSAGE pPioMsg= (PCHV_X64_IO_PORT_INTERCEPT_MESSAGE)(pMsgHdr + 1);
     1875            Assert(pMsgHdr->PayloadSize == sizeof(*pPioMsg));
     1876
     1877            pExitCtx->ExitReason                            = WHvRunVpExitReasonX64IoPortAccess;
     1878            nemR3WinConvertX64MsgHdrToVpExitCtx(&pPioMsg->Header, &pExitCtx->IoPortAccess.VpContext);
     1879            pExitCtx->IoPortAccess.InstructionByteCount     = pPioMsg->InstructionByteCount;
     1880            ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[0] = ((uint64_t const *)pPioMsg->InstructionBytes)[0];
     1881            ((uint64_t *)pExitCtx->IoPortAccess.InstructionBytes)[1] = ((uint64_t const *)pPioMsg->InstructionBytes)[1];
     1882
     1883            pExitCtx->IoPortAccess.AccessInfo.IsWrite       = pPioMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE;
     1884            pExitCtx->IoPortAccess.AccessInfo.AccessSize    = pPioMsg->AccessInfo.AccessSize;
     1885            pExitCtx->IoPortAccess.AccessInfo.StringOp      = pPioMsg->AccessInfo.StringOp;
     1886            pExitCtx->IoPortAccess.AccessInfo.RepPrefix     = pPioMsg->AccessInfo.RepPrefix;
     1887            pExitCtx->IoPortAccess.AccessInfo.Reserved      = pPioMsg->AccessInfo.Reserved;
     1888            pExitCtx->IoPortAccess.PortNumber               = pPioMsg->PortNumber;
     1889            pExitCtx->IoPortAccess.Rax                      = pPioMsg->Rax;
     1890            pExitCtx->IoPortAccess.Rcx                      = pPioMsg->Rcx;
     1891            pExitCtx->IoPortAccess.Rsi                      = pPioMsg->Rsi;
     1892            pExitCtx->IoPortAccess.Rdi                      = pPioMsg->Rdi;
     1893            pExitCtx->IoPortAccess.Ds.Base                  = pPioMsg->DsSegment.Base;
     1894            pExitCtx->IoPortAccess.Ds.Limit                 = pPioMsg->DsSegment.Limit;
     1895            pExitCtx->IoPortAccess.Ds.Selector              = pPioMsg->DsSegment.Selector;
     1896            pExitCtx->IoPortAccess.Ds.Attributes            = pPioMsg->DsSegment.Attributes;
     1897            pExitCtx->IoPortAccess.Es.Base                  = pPioMsg->EsSegment.Base;
     1898            pExitCtx->IoPortAccess.Es.Limit                 = pPioMsg->EsSegment.Limit;
     1899            pExitCtx->IoPortAccess.Es.Selector              = pPioMsg->EsSegment.Selector;
     1900            pExitCtx->IoPortAccess.Es.Attributes            = pPioMsg->EsSegment.Attributes;
     1901            return VINF_SUCCESS;
     1902        }
     1903
     1904        case HvMessageTypeX64Halt:
     1905        {
     1906            PCHV_X64_HALT_MESSAGE pHaltMsg = (PCHV_X64_HALT_MESSAGE)(pMsgHdr + 1);
     1907            AssertMsg(pHaltMsg->u64Reserved == 0, ("HALT reserved: %#RX64\n", pHaltMsg->u64Reserved));
     1908            pExitCtx->ExitReason = WHvRunVpExitReasonX64Halt;
     1909            return VINF_SUCCESS;
     1910        }
     1911
     1912        case HvMessageTypeX64InterruptWindow:
     1913            AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1914
     1915        case HvMessageTypeInvalidVpRegisterValue:
     1916        case HvMessageTypeUnrecoverableException:
     1917        case HvMessageTypeUnsupportedFeature:
     1918        case HvMessageTypeTlbPageSizeMismatch:
     1919            AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1920
     1921        case HvMessageTypeX64MsrIntercept:
     1922        case HvMessageTypeX64CpuidIntercept:
     1923        case HvMessageTypeX64ExceptionIntercept:
     1924        case HvMessageTypeX64ApicEoi:
     1925        case HvMessageTypeX64LegacyFpError:
     1926        case HvMessageTypeX64RegisterIntercept:
     1927        case HvMessageTypeApicEoi:
     1928        case HvMessageTypeFerrAsserted:
     1929        case HvMessageTypeEventLogBufferComplete:
     1930        case HvMessageTimerExpired:
     1931            AssertLogRelMsgFailedReturn(("Unexpected message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1932
     1933        default:
     1934            AssertLogRelMsgFailedReturn(("Unknown message type #x!\n", pMsgHdr->MessageType), VERR_INTERNAL_ERROR_2);
     1935    }
     1936}
     1937
     1938
     1939/**
     1940 * Our own WHvRunVirtualProcessor that can later be moved to ring-0.
     1941 *
     1942 * This is an experiment only.
     1943 *
     1944 * @returns VBox status code.
     1945 * @param   pVM             The cross context VM structure.
     1946 * @param   pVCpu           The cross context virtual CPU structure of the
     1947 *                          calling EMT.
     1948 * @param   pExitCtx        Where to return exit information.
     1949 * @param   cbExitCtx       Size of the exit information area.
     1950 */
     1951static int nemR3WinRunVirtualProcessor(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT *pExitCtx, size_t cbExitCtx)
     1952{
     1953    RT_BZERO(pExitCtx, cbExitCtx);
     1954
     1955    /*
     1956     * Tell the CPU to execute stuff if we haven't got a pending message.
     1957     */
     1958    VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader = (VID_MESSAGE_MAPPING_HEADER volatile *)pVCpu->nem.s.pvMsgSlotMapping;
     1959    uint32_t                             fHandleAndGetFlags;
     1960    if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED))
     1961    {
     1962        uint8_t const bMsgState = pVCpu->nem.s.bMsgState;
     1963        if (bMsgState == NEM_WIN_MSG_STATE_PENDING_MSG)
     1964        {
     1965            Assert(pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage);
     1966            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE | VID_MSHAGN_F_HANDLE_MESSAGE;
     1967            Log8(("nemR3WinRunVirtualProcessor: #1: msg pending, no need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1968        }
     1969        else if (bMsgState != NEM_WIN_MSG_STATE_STARTED)
     1970        {
     1971            if (bMsgState == NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG)
     1972            {
     1973                Log8(("nemR3WinRunVirtualProcessor: #0: pending stop+message (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1974                /* ACK the pending message and get the stop message. */
     1975                BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     1976                                                                 VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
     1977                AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
     1978
     1979                /* ACK the stop message. */
     1980                fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     1981                                                                 VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
     1982                AssertLogRelMsg(fWait, ("dwErr=%u (%#x) rcNt=%#x\n", RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()));
     1983
     1984                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     1985            }
     1986
     1987            Log8(("nemR3WinRunVirtualProcessor: #1: starting CPU (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     1988            if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu))
     1989                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     1990            else
     1991            {
     1992                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
     1993                AssertLogRelMsgFailedReturn(("VidStartVirtualProcessor failed for CPU #%u: rcNt=%#x dwErr=%u\n",
     1994                                             pVCpu->idCpu, RTNtLastStatusValue(), RTNtLastErrorValue()),
     1995                                            VERR_INTERNAL_ERROR_3);
     1996            }
     1997            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
     1998        }
     1999        else
     2000        {
     2001            /* This shouldn't happen. */
     2002            fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
     2003            Log8(("nemR3WinRunVirtualProcessor: #1: NO MSG PENDING! No need to start CPU (cpu state %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2004        }
     2005    }
     2006    else
     2007    {
     2008        Log8(("nemR3WinRunVirtualProcessor: #1: state=%u -> canceled (cpu status %u)\n",
     2009              VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu)));
     2010        pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2011        return VINF_SUCCESS;
     2012    }
     2013
     2014    /*
     2015     * Wait for it to stop and give us a reason to work with.
     2016     */
     2017    uint32_t cMillies = 5000; // Starting low so we can experiment without getting stuck.
     2018    for (;;)
     2019    {
     2020        if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM))
     2021        {
     2022            Log8(("nemR3WinRunVirtualProcessor: #2: Waiting %#x (cpu status %u)...\n",
     2023                  fHandleAndGetFlags, nemR3WinCpuGetRunningStatus(pVCpu)));
     2024            BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2025                                                             fHandleAndGetFlags, cMillies);
     2026            if (fWait)
     2027            {
     2028                /* Not sure yet, but we have to check whether there is anything pending
     2029                   and retry if there isn't. */
     2030                VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
     2031                if (enmVidMsgType == VidMessageHypervisorMessage)
     2032                {
     2033                    if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT))
     2034                        VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
     2035                    Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded: %#x / %#x (cpu status %u)\n",
     2036                          enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType,
     2037                          nemR3WinCpuGetRunningStatus(pVCpu) ));
     2038                    pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
     2039                    return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
     2040                }
     2041
     2042                /* This shouldn't happen, and I think its wrong. */
     2043                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     2044#ifdef DEBUG_bird
     2045                __debugbreak();
     2046#endif
     2047                Log8(("nemR3WinRunVirtualProcessor: #3: wait succeeded, but nothing pending: %#x / %#x (cpu status %u)\n",
     2048                      enmVidMsgType, ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2049                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     2050                AssertLogRelMsgReturnStmt(enmVidMsgType == VidMessageStopRequestComplete,
     2051                                          ("enmVidMsgType=%#x\n", enmVidMsgType),
     2052                                          g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
     2053                                          VERR_INTERNAL_ERROR_3);
     2054                fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
     2055            }
     2056            else
     2057            {
     2058                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     2059
     2060                /* Note! VID.SYS merges STATUS_ALERTED and STATUS_USER_APC into STATUS_TIMEOUT. */
     2061                DWORD const dwErr = RTNtLastErrorValue();
     2062                AssertLogRelMsgReturnStmt(   dwErr == STATUS_TIMEOUT
     2063                                          || dwErr == STATUS_ALERTED || dwErr == STATUS_USER_APC, /* just in case */
     2064                                          ("dwErr=%u (%#x) (cpu status %u)\n", dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu)),
     2065                                          g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
     2066                                          VERR_INTERNAL_ERROR_3);
     2067                Log8(("nemR3WinRunVirtualProcessor: #3: wait timed out (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2068                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STARTED;
     2069                fHandleAndGetFlags &= ~VID_MSHAGN_F_HANDLE_MESSAGE;
     2070            }
     2071        }
     2072        else
     2073        {
     2074            /*
     2075             * State changed and we need to return.
     2076             *
     2077             * We must ensure that the processor is not running while we
     2078             * return, and that can be a bit complicated.
     2079             */
     2080            Log8(("nemR3WinRunVirtualProcessor: #4: state changed to %u (cpu status %u)\n",
     2081                  VMCPU_GET_STATE(pVCpu), nemR3WinCpuGetRunningStatus(pVCpu) ));
     2082            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_CANCELED);
     2083
     2084            /* If we haven't marked the pervious message as handled, simply return
     2085               without doing anything special. */
     2086            if (fHandleAndGetFlags & VID_MSHAGN_F_HANDLE_MESSAGE)
     2087            {
     2088                Log8(("nemR3WinRunVirtualProcessor: #5: Didn't resume previous message.\n"));
     2089                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_MSG;
     2090                pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2091                return VINF_SUCCESS;
     2092            }
     2093
     2094            /* The processor is running, so try stop it. */
     2095            BOOL fStop = g_pfnVidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu);
     2096            if (fStop)
     2097            {
     2098                Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU succeeded (cpu status %u)\n", nemR3WinCpuGetRunningStatus(pVCpu) ));
     2099                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     2100                pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2101                return VINF_SUCCESS;
     2102            }
     2103
     2104            /* Dang, the CPU stopped by itself with a message pending. */
     2105            DWORD dwErr = RTNtLastErrorValue();
     2106            Log8(("nemR3WinRunVirtualProcessor: #5: Stopping CPU failed (%u/%#x) - cpu status %u\n",
     2107                  dwErr, dwErr, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2108            pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2109            AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u\n", dwErr), VERR_INTERNAL_ERROR_3);
     2110
     2111            /* Get the pending message. */
     2112            BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2113                                                             VID_MSHAGN_F_GET_NEXT_MESSAGE, 5000);
     2114            AssertLogRelMsgReturn(fWait, ("error=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
     2115
     2116            VID_MESSAGE_TYPE const enmVidMsgType = pMappingHeader->enmVidMsgType;
     2117            if (enmVidMsgType == VidMessageHypervisorMessage)
     2118            {
     2119                Log8(("nemR3WinRunVirtualProcessor: #6: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
     2120                      ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2121                pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_PENDING_STOP_AND_MSG;
     2122                return nemR3WinRunVirtualProcessorConvertPending((HV_MESSAGE_HEADER const *)(pMappingHeader + 1), pExitCtx);
     2123            }
     2124
     2125            /* ACK the stop message, if that's what it is.  Don't think we'll ever get here. */
     2126            Log8(("nemR3WinRunVirtualProcessor: #6b: wait succeeded: %#x / %#x (cpu status %u)\n", enmVidMsgType,
     2127                  ((HV_MESSAGE_HEADER const *)(pMappingHeader + 1))->MessageType, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2128            AssertLogRelMsgReturn(enmVidMsgType == VidMessageStopRequestComplete, ("enmVidMsgType=%#x\n", enmVidMsgType),
     2129                                  VERR_INTERNAL_ERROR_3);
     2130            fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
     2131                                                        VID_MSHAGN_F_HANDLE_MESSAGE, 5000);
     2132            AssertLogRelMsgReturn(fWait, ("dwErr=%#u\n", RTNtLastErrorValue()), VERR_INTERNAL_ERROR_3);
     2133
     2134            pVCpu->nem.s.bMsgState = NEM_WIN_MSG_STATE_STOPPED;
     2135            pExitCtx->ExitReason = WHvRunVpExitReasonCanceled;
     2136            return VINF_SUCCESS;
     2137        }
     2138
     2139        /** @todo check flags and stuff? */
     2140    }
     2141}
     2142
     2143#endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
     2144
     2145#ifdef LOG_ENABLED
     2146
    16752147/**
    16762148 * Log the full details of an exit reason.
     
    18902362#else
    18912363        LogRel(("nemR3WinUnmapOnePageCallback: GCPhys=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    1892                 GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtCurrentTeb()->LastStatusValue,
    1893                 RTNtCurrentTeb()->LastErrorValue, pVM->nem.s.cMappedPages));
     2364                GCPhys, g_apszPageStates[*pu2NemState], hrc, hrc, RTNtLastStatusValue(),
     2365                RTNtLastErrorValue(), pVM->nem.s.cMappedPages));
    18942366#endif
    18952367        *pu2NemState = NEM_WIN_PAGE_STATE_NOT_SET;
     
    20722544#else
    20732545    LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp %s hrc=%Rhrc (%#x) Last=%#x/%u (cMappedPages=%u)\n",
    2074             GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue,
     2546            GCPhys, g_apszPageStates[u2State], hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue(),
    20752547            pVM->nem.s.cMappedPages));
    20762548
     
    23152787            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    23162788        {
     2789#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2790            int rc2 = nemR3WinRunVirtualProcessor(pVM, pVCpu, &ExitReason, sizeof(ExitReason));
     2791            AssertRCBreakStmt(rc2, rcStrict = rc2);
     2792#else
     2793            Log8(("Calling WHvRunVirtualProcessor\n"));
    23172794            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED);
    23182795            HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
     
    23202797            AssertLogRelMsgBreakStmt(SUCCEEDED(hrc),
    23212798                                     ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu,
    2322                                       hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue),
     2799                                      hrc, RTNtLastStatusValue(), RTNtLastErrorValue()),
    23232800                                     rcStrict = VERR_INTERNAL_ERROR);
    2324             Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d)\n", hrc, ExitReason.ExitReason, ExitReason.ExitReason));
     2801            Log2(("WHvRunVirtualProcessor -> %#x; exit code %#x (%d) (cpu status %u)\n",
     2802                  hrc, ExitReason.ExitReason, ExitReason.ExitReason, nemR3WinCpuGetRunningStatus(pVCpu) ));
     2803#endif
    23252804        }
    23262805        else
     
    24942973void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags)
    24952974{
     2975#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2976    nemR3WinCancelRunVirtualProcessor(pVM, pVCpu);
     2977#else
     2978    Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu));
    24962979    HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0);
    24972980    AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc));
    2498 
    24992981    RT_NOREF_PV(hrc);
     2982#endif
    25002983    RT_NOREF_PV(fFlags);
    25012984}
     
    25773060            {
    25783061                LogRel(("nemR3NativeNotifyPhysRomRegisterEarly: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2579                         GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3062                        GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    25803063                return VERR_NEM_INIT_FAILED;
    25813064            }
     
    26443127#else
    26453128            LogRel(("nemR3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2646                     GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3129                    GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    26473130            return VERR_INTERNAL_ERROR_2;
    26483131#endif
     
    28583341            {
    28593342                LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2860                         GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3343                        GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    28613344                return VERR_NEM_INIT_FAILED;
    28623345            }
     
    29013384            }
    29023385            LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2903                     GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3386                    GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29043387            return VERR_NEM_INIT_FAILED;
    29053388        }
     
    29413424            }
    29423425            LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2943                     GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3426                    GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29443427            return VERR_NEM_INIT_FAILED;
    29453428        }
     
    29883471    }
    29893472    LogRel(("nemR3JustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2990             GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     3473            GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    29913474    return VERR_INTERNAL_ERROR_3;
    29923475#endif
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r71040 r71129  
    45334533
    45344534/**
    4535  * Returns the native handle of the current EMT VMCPU thread.
     4535 * Returns the native ID of the current EMT VMCPU thread.
    45364536 *
    45374537 * @returns Handle if this is an EMT thread; NIL_RTNATIVETHREAD otherwise
     
    45514551
    45524552/**
    4553  * Returns the native handle of the current EMT VMCPU thread.
     4553 * Returns the native ID of the current EMT VMCPU thread.
    45544554 *
    45554555 * @returns Handle if this is an EMT thread; NIL_RTNATIVETHREAD otherwise
     
    45824582        return NIL_RTTHREAD;
    45834583
     4584    return pUVCpu->vm.s.ThreadEMT;
     4585}
     4586
     4587
     4588/**
     4589 * Returns the handle of the current EMT VMCPU thread.
     4590 *
     4591 * @returns The IPRT thread handle.
     4592 * @param   pUVCpu          The user mode CPU handle.
     4593 * @thread  EMT
     4594 */
     4595VMMR3_INT_DECL(RTTHREAD) VMR3GetThreadHandle(PUVMCPU pUVCpu)
     4596{
    45844597    return pUVCpu->vm.s.ThreadEMT;
    45854598}
  • trunk/src/VBox/VMM/VMMR3/VMEmt.cpp

    r71040 r71129  
    859859                }
    860860            }
    861             else if (enmState == VMCPUSTATE_STARTED_EXEC_NEM)
     861            else if (   enmState == VMCPUSTATE_STARTED_EXEC_NEM
     862                     || enmState == VMCPUSTATE_STARTED_EXEC_NEM_WAIT)
    862863                NEMR3NotifyFF(pUVCpu->pVM, pVCpu, fFlags);
    863864#ifdef VBOX_WITH_REM
     
    10011002        {
    10021003            VMCPUSTATE enmState = pVCpu->enmState;
    1003             if (enmState == VMCPUSTATE_STARTED_EXEC_NEM)
     1004            if (   enmState == VMCPUSTATE_STARTED_EXEC_NEM
     1005                || enmState == VMCPUSTATE_STARTED_EXEC_NEM_WAIT)
    10041006                NEMR3NotifyFF(pUVCpu->pVM, pVCpu, fFlags);
    10051007#ifdef VBOX_WITH_REM
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