VirtualBox

Changeset 72412 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jun 1, 2018 2:02:49 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
122883
Message:

NEM/win: More code merging. bugref:9044

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r72403 r72412  
    737737    if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
    738738    {
    739         GET_SEG(pCtx->es, WHvX64RegisterEs);
    740         GET_SEG(pCtx->cs, WHvX64RegisterCs);
    741         GET_SEG(pCtx->ss, WHvX64RegisterSs);
    742         GET_SEG(pCtx->ds, WHvX64RegisterDs);
    743         GET_SEG(pCtx->fs, WHvX64RegisterFs);
    744         GET_SEG(pCtx->gs, WHvX64RegisterGs);
     739        if (fWhat & CPUMCTX_EXTRN_ES)
     740            GET_SEG(pCtx->es, WHvX64RegisterEs);
     741        if (fWhat & CPUMCTX_EXTRN_CS)
     742            GET_SEG(pCtx->cs, WHvX64RegisterCs);
     743        if (fWhat & CPUMCTX_EXTRN_SS)
     744            GET_SEG(pCtx->ss, WHvX64RegisterSs);
     745        if (fWhat & CPUMCTX_EXTRN_DS)
     746            GET_SEG(pCtx->ds, WHvX64RegisterDs);
     747        if (fWhat & CPUMCTX_EXTRN_FS)
     748            GET_SEG(pCtx->fs, WHvX64RegisterFs);
     749        if (fWhat & CPUMCTX_EXTRN_GS)
     750            GET_SEG(pCtx->gs, WHvX64RegisterGs);
    745751    }
    746752
     
    11521158#endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
    11531159
     1160
    11541161#ifdef LOG_ENABLED
    1155 
    11561162/**
    11571163 * Logs the current CPU state.
     
    12011207    }
    12021208}
    1203 
    1204 
     1209#endif /* LOG_ENABLED */
     1210
     1211
     1212#ifdef LOG_ENABLED
     1213/** Macro used by nemHCWinExecStateToLogStr and nemR3WinExecStateToLogStr. */
     1214# define SWITCH_IT(a_szPrefix) \
     1215    do \
     1216        switch (u)\
     1217        { \
     1218            case 0x00: return a_szPrefix ""; \
     1219            case 0x01: return a_szPrefix ",Pnd"; \
     1220            case 0x02: return a_szPrefix ",Dbg"; \
     1221            case 0x03: return a_szPrefix ",Pnd,Dbg"; \
     1222            case 0x04: return a_szPrefix ",Shw"; \
     1223            case 0x05: return a_szPrefix ",Pnd,Shw"; \
     1224            case 0x06: return a_szPrefix ",Shw,Dbg"; \
     1225            case 0x07: return a_szPrefix ",Pnd,Shw,Dbg"; \
     1226            default: AssertFailedReturn("WTF?"); \
     1227        } \
     1228    while (0)
     1229
     1230# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    12051231/**
    1206  * Translates the execution stat bitfield into a short log string.
     1232 * Translates the execution stat bitfield into a short log string, VID version.
    12071233 *
    12081234 * @returns Read-only log string.
     
    12141240               | ((unsigned)pMsgHdr->ExecutionState.DebugActive << 1)
    12151241               | ((unsigned)pMsgHdr->ExecutionState.InterruptShadow << 2);
    1216 # define SWITCH_IT(a_szPrefix) \
    1217         do \
    1218             switch (u)\
    1219             { \
    1220                 case 0x00: return a_szPrefix ""; \
    1221                 case 0x01: return a_szPrefix ",Pnd"; \
    1222                 case 0x02: return a_szPrefix ",Dbg"; \
    1223                 case 0x03: return a_szPrefix ",Pnd,Dbg"; \
    1224                 case 0x04: return a_szPrefix ",Shw"; \
    1225                 case 0x05: return a_szPrefix ",Pnd,Shw"; \
    1226                 case 0x06: return a_szPrefix ",Shw,Dbg"; \
    1227                 case 0x07: return a_szPrefix ",Pnd,Shw,Dbg"; \
    1228                 default: AssertFailedReturn("WTF?"); \
    1229             } \
    1230         while (0)
    1231 
    12321242    if (pMsgHdr->ExecutionState.EferLma)
    12331243        SWITCH_IT("LM");
     
    12361246    else
    12371247        SWITCH_IT("RM");
     1248}
     1249# elif defined(IN_RING3)
     1250/**
     1251 * Translates the execution stat bitfield into a short log string, WinHv version.
     1252 *
     1253 * @returns Read-only log string.
     1254 * @param   pExitCtx        The exit context which state to summarize.
     1255 */
     1256static const char *nemR3WinExecStateToLogStr(WHV_VP_EXIT_CONTEXT const *pExitCtx)
     1257{
     1258    unsigned u = (unsigned)pExitCtx->ExecutionState.InterruptionPending
     1259               | ((unsigned)pExitCtx->ExecutionState.DebugActive << 1)
     1260               | ((unsigned)pExitCtx->ExecutionState.InterruptShadow << 2);
     1261    if (pExitCtx->ExecutionState.EferLma)
     1262        SWITCH_IT("LM");
     1263    else if (pExitCtx->ExecutionState.Cr0Pe)
     1264        SWITCH_IT("PM");
     1265    else
     1266        SWITCH_IT("RM");
     1267}
     1268# endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    12381269# undef SWITCH_IT
    1239 }
    1240 
    12411270#endif /* LOG_ENABLED */
    12421271
     1272
     1273#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    12431274/**
    1244  * Advances the guest RIP and clear EFLAGS.RF.
     1275 * Advances the guest RIP and clear EFLAGS.RF, VID version.
    12451276 *
    12461277 * This may clear VMCPU_FF_INHIBIT_INTERRUPTS.
     
    12651296        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    12661297}
    1267 
    1268 
    1269 NEM_TMPL_STATIC VBOXSTRICTRC
    1270 nemHCWinHandleHalt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    1271 {
    1272     NOREF(pVM); NOREF(pVCpu); NOREF(pCtx);
    1273     LogFlow(("nemHCWinHandleHalt\n"));
    1274     return VINF_EM_HALT;
    1275 }
     1298#elif defined(IN_RING3)
     1299/**
     1300 * Advances the guest RIP and clear EFLAGS.RF, WinHv version.
     1301 *
     1302 * This may clear VMCPU_FF_INHIBIT_INTERRUPTS.
     1303 *
     1304 * @param   pVCpu           The cross context virtual CPU structure.
     1305 * @param   pCtx            The CPU context to update.
     1306 * @param   pExitCtx        The exit context.
     1307 */
     1308DECLINLINE(void) nemR3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)
     1309{
     1310    Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)));
     1311
     1312    /* Advance the RIP. */
     1313    Assert(pExitCtx->InstructionLength > 0 && pExitCtx->InstructionLength < 16);
     1314    pCtx->rip += pExitCtx->InstructionLength;
     1315    pCtx->rflags.Bits.u1RF = 0;
     1316
     1317    /* Update interrupt inhibition. */
     1318    if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     1319    { /* likely */ }
     1320    else if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
     1321        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     1322}
     1323#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     1324
    12761325
    12771326
     
    14521501
    14531502        default:
    1454             AssertLogRelMsgFailedReturn(("u2State=%#x\n", u2State), VERR_INTERNAL_ERROR_3);
     1503            AssertLogRelMsgFailedReturn(("u2State=%#x\n", u2State), VERR_NEM_IPE_4);
    14551504    }
    14561505
     
    14951544
    14961545
    1497 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    1498 
    1499 # ifdef IN_RING0
     1546
     1547#if defined(IN_RING0) && defined(NEM_WIN_USE_OUR_OWN_RUN_API)
    15001548/**
    15011549 * Wrapper around nemR0WinImportState that converts VERR_NEM_CHANGE_PGM_MODE and
     
    15261574    AssertMsgFailedReturn(("%s/%u: nemR0WinImportState failed: %Rrc\n", pszCaller, pGVCpu->idCpu, rc), rc);
    15271575}
    1528 # endif /* IN_RING0 */
    1529 
    1530 
     1576#endif /* IN_RING0 && NEM_WIN_USE_OUR_OWN_RUN_API*/
     1577
     1578#if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3)
    15311579/**
    15321580 * Wrapper around nemR0WinImportStateStrict and nemHCWinCopyStateFromHyperV.
     
    15461594    if (pCtx->fExtrn & fWhat)
    15471595    {
    1548 # ifdef IN_RING0
     1596#ifdef IN_RING0
    15491597        RT_NOREF(pVCpu);
    15501598        return nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, fWhat, pszCaller);
    1551 # else
     1599#else
    15521600        RT_NOREF(pGVCpu, pszCaller);
    15531601        int rc = nemHCWinCopyStateFromHyperV(pVCpu->pVMR3, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
    15541602        AssertRCReturn(rc, rc);
    1555 # endif
     1603#endif
    15561604    }
    15571605    return VINF_SUCCESS;
    15581606}
    1559 
    1560 
     1607#endif /* NEM_WIN_USE_OUR_OWN_RUN_API || IN_RING3 */
     1608
     1609#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    15611610/**
    15621611 * Copies register state from the X64 intercept message header.
     
    15671616 * @param   pCtx            The registe rcontext.
    15681617 * @param   pHdr            The X64 intercept message header.
     1618 * @sa      nemR3WinCopyStateFromX64Header
    15691619 */
    15701620DECLINLINE(void) nemHCWinCopyStateFromX64Header(PVMCPU pVCpu, PCPUMCTX pCtx, HV_X64_INTERCEPT_MESSAGE_HEADER const *pHdr)
     
    15891639    pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT);
    15901640}
    1591 
    1592 
     1641#elif defined(IN_RING3)
     1642/**
     1643 * Copies register state from the (common) exit context.
     1644 *
     1645 * ASSUMES no state copied yet.
     1646 *
     1647 * @param   pVCpu           The cross context per CPU structure.
     1648 * @param   pCtx            The registe rcontext.
     1649 * @param   pExitCtx        The common exit context.
     1650 * @sa      nemHCWinCopyStateFromX64Header
     1651 */
     1652DECLINLINE(void) nemR3WinCopyStateFromX64Header(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)
     1653{
     1654    Assert(    (pCtx->fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT))
     1655            ==                 (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT));
     1656    NEM_WIN_COPY_BACK_SEG(pCtx->cs, pExitCtx->Cs);
     1657    pCtx->rip      = pExitCtx->Rip;
     1658    pCtx->rflags.u = pExitCtx->Rflags;
     1659
     1660    pVCpu->nem.s.fLastInterruptShadow = pExitCtx->ExecutionState.InterruptShadow;
     1661    if (!pExitCtx->ExecutionState.InterruptShadow)
     1662    {
     1663        if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     1664        { /* likely */ }
     1665        else
     1666            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     1667    }
     1668    else
     1669        EMSetInhibitInterruptsPC(pVCpu, pExitCtx->Rip);
     1670
     1671    pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT);
     1672}
     1673#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     1674
     1675
     1676#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    15931677/**
    15941678 * Deals with memory intercept message.
     
    16001684 * @param   pCtx            The register context.
    16011685 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     1686 * @sa      nemR3WinHandleExitMemory
    16021687 */
    1603 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageMemory(PVM pVM, PVMCPU pVCpu, HV_X64_MEMORY_INTERCEPT_MESSAGE const *pMsg,
    1604                                                         PCPUMCTX pCtx, PGVMCPU pGVCpu)
     1688NEM_TMPL_STATIC VBOXSTRICTRC
     1689nemHCWinHandleMessageMemory(PVM pVM, PVMCPU pVCpu, HV_X64_MEMORY_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx, PGVMCPU pGVCpu)
    16051690{
    16061691    Assert(   pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ
     
    16971782    /** @todo do we need to do anything wrt debugging here?   */
    16981783    return rcStrict;
    1699 
    1700 }
    1701 
    1702 
     1784}
     1785#elif defined(IN_RING3)
     1786/**
     1787 * Deals with memory access exits (WHvRunVpExitReasonMemoryAccess).
     1788 *
     1789 * @returns Strict VBox status code.
     1790 * @param   pVM             The cross context VM structure.
     1791 * @param   pVCpu           The cross context per CPU structure.
     1792 * @param   pExit           The VM exit information to handle.
     1793 * @param   pCtx            The register context.
     1794 * @sa      nemHCWinHandleMessageMemory
     1795 */
     1796NEM_TMPL_STATIC VBOXSTRICTRC
     1797nemR3WinHandleExitMemory(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     1798{
     1799    Assert(pExit->MemoryAccess.AccessInfo.AccessType != 3);
     1800    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     1801
     1802    /*
     1803     * Whatever we do, we must clear pending event injection upon resume.
     1804     */
     1805    if (pExit->VpContext.ExecutionState.InterruptionPending)
     1806        pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT;
     1807
     1808    /*
     1809     * Ask PGM for information about the given GCPhys.  We need to check if we're
     1810     * out of sync first.
     1811     */
     1812    NEMHCWINHMACPCCSTATE State = { pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite, false, false };
     1813    PGMPHYSNEMPAGEINFO   Info;
     1814    int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pExit->MemoryAccess.Gpa, State.fWriteAccess, &Info,
     1815                                       nemHCWinHandleMemoryAccessPageCheckerCallback, &State);
     1816    if (RT_SUCCESS(rc))
     1817    {
     1818        if (Info.fNemProt & (  pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite
     1819                             ? NEM_PAGE_PROT_WRITE : NEM_PAGE_PROT_READ))
     1820        {
     1821            if (State.fCanResume)
     1822            {
     1823                Log4(("MemExit/%u: %04x:%08RX64/%s: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n",
     1824                      pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     1825                      pExit->MemoryAccess.Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
     1826                      Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
     1827                      State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pExit->MemoryAccess.AccessInfo.AccessType]));
     1828                return VINF_SUCCESS;
     1829            }
     1830        }
     1831        Log4(("MemExit/%u: %04x:%08RX64/%s: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n",
     1832              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     1833              pExit->MemoryAccess.Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
     1834              Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
     1835              State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pExit->MemoryAccess.AccessInfo.AccessType]));
     1836    }
     1837    else
     1838        Log4(("MemExit/%u: %04x:%08RX64/%s: %RGp rc=%Rrc%s; emulating (%s)\n",
     1839              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     1840              pExit->MemoryAccess.Gpa, rc, State.fDidSomething ? " modified-backing" : "",
     1841              g_apszHvInterceptAccessTypes[pExit->MemoryAccess.AccessInfo.AccessType]));
     1842
     1843    /*
     1844     * Emulate the memory access, either access handler or special memory.
     1845     */
     1846    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     1847    rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
     1848    AssertRCReturn(rc, rc);
     1849
     1850    if (pExit->VpContext.ExecutionState.Reserved0 || pExit->VpContext.ExecutionState.Reserved1)
     1851        Log(("MemExit/Hdr/State: Reserved0=%#x Reserved1=%#x\n", pExit->VpContext.ExecutionState.Reserved0, pExit->VpContext.ExecutionState.Reserved1));
     1852    //if (pMsg->InstructionByteCount > 0)
     1853    //    Log4(("InstructionByteCount=%#x %.16Rhxs\n", pMsg->InstructionByteCount, pMsg->InstructionBytes));
     1854
     1855    VBOXSTRICTRC rcStrict;
     1856    if (pExit->MemoryAccess.InstructionByteCount > 0)
     1857        rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pExit->VpContext.Rip,
     1858                                                pExit->MemoryAccess.InstructionBytes, pExit->MemoryAccess.InstructionByteCount);
     1859    else
     1860        rcStrict = IEMExecOne(pVCpu);
     1861    /** @todo do we need to do anything wrt debugging here?   */
     1862    return rcStrict;
     1863}
     1864#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     1865
     1866
     1867#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    17031868/**
    17041869 * Deals with I/O port intercept message.
     
    17111876 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
    17121877 */
    1713 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageIoPort(PVM pVM, PVMCPU pVCpu, HV_X64_IO_PORT_INTERCEPT_MESSAGE const *pMsg,
    1714                                                         PCPUMCTX pCtx, PGVMCPU pGVCpu)
     1878NEM_TMPL_STATIC VBOXSTRICTRC
     1879nemHCWinHandleMessageIoPort(PVM pVM, PVMCPU pVCpu, HV_X64_IO_PORT_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx, PGVMCPU pGVCpu)
    17151880{
    17161881    Assert(   pMsg->AccessInfo.AccessSize == 1
     
    18151980         * Do debug checks.
    18161981         */
    1817         if (   pMsg->Header.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflext DR7? */
     1982        if (   pMsg->Header.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */
    18181983            || (pMsg->Header.Rflags & X86_EFL_TF)
    18191984            || DBGFBpIsHwIoArmed(pVM) )
     
    18241989    return rcStrict;
    18251990}
    1826 
    1827 
     1991#elif defined(IN_RING3)
     1992/**
     1993 * Deals with I/O port access exits (WHvRunVpExitReasonX64IoPortAccess).
     1994 *
     1995 * @returns Strict VBox status code.
     1996 * @param   pVM             The cross context VM structure.
     1997 * @param   pVCpu           The cross context per CPU structure.
     1998 * @param   pExit           The VM exit information to handle.
     1999 * @param   pCtx            The register context.
     2000 * @sa      nemHCWinHandleMessageIoPort
     2001 */
     2002NEM_TMPL_STATIC VBOXSTRICTRC
     2003nemR3WinHandleExitIoPort(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2004{
     2005    Assert(   pExit->IoPortAccess.AccessInfo.AccessSize == 1
     2006           || pExit->IoPortAccess.AccessInfo.AccessSize == 2
     2007           || pExit->IoPortAccess.AccessInfo.AccessSize == 4);
     2008    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2009
     2010    /*
     2011     * Whatever we do, we must clear pending event injection upon resume.
     2012     */
     2013    if (pExit->VpContext.ExecutionState.InterruptionPending)
     2014        pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT;
     2015
     2016    VBOXSTRICTRC rcStrict;
     2017    if (!pExit->IoPortAccess.AccessInfo.StringOp)
     2018    {
     2019        /*
     2020         * Simple port I/O.
     2021         */
     2022        static uint32_t const s_fAndMask[8] =
     2023        {   UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX,   UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX   };
     2024        uint32_t const        fAndMask      = s_fAndMask[pExit->IoPortAccess.AccessInfo.AccessSize];
     2025        if (pExit->IoPortAccess.AccessInfo.IsWrite)
     2026        {
     2027            rcStrict = IOMIOPortWrite(pVM, pVCpu, pExit->IoPortAccess.PortNumber, (uint32_t)pExit->IoPortAccess.Rax & fAndMask,
     2028                                      pExit->IoPortAccess.AccessInfo.AccessSize);
     2029            Log4(("IOExit/%u: %04x:%08RX64/%s: OUT %#x, %#x LB %u rcStrict=%Rrc\n",
     2030                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2031                  pExit->IoPortAccess.PortNumber, (uint32_t)pExit->IoPortAccess.Rax & fAndMask,
     2032                  pExit->IoPortAccess.AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) ));
     2033            if (IOM_SUCCESS(rcStrict))
     2034            {
     2035                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2036                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
     2037            }
     2038        }
     2039        else
     2040        {
     2041            uint32_t uValue = 0;
     2042            rcStrict = IOMIOPortRead(pVM, pVCpu, pExit->IoPortAccess.PortNumber, &uValue, pExit->IoPortAccess.AccessInfo.AccessSize);
     2043            Log4(("IOExit/%u: %04x:%08RX64/%s: IN %#x LB %u -> %#x, rcStrict=%Rrc\n",
     2044                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2045                  pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     2046            if (IOM_SUCCESS(rcStrict))
     2047            {
     2048                if (pExit->IoPortAccess.AccessInfo.AccessSize != 4)
     2049                    pCtx->rax = (pExit->IoPortAccess.Rax & ~(uint64_t)fAndMask) | (uValue & fAndMask);
     2050                else
     2051                    pCtx->rax = uValue;
     2052                pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX;
     2053                Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pExit->IoPortAccess.Rax, pCtx->rax));
     2054                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2055                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
     2056            }
     2057        }
     2058    }
     2059    else
     2060    {
     2061        /*
     2062         * String port I/O.
     2063         */
     2064        /** @todo Someone at Microsoft please explain how we can get the address mode
     2065         * from the IoPortAccess.VpContext.  CS.Attributes is only sufficient for
     2066         * getting the default mode, it can always be overridden by a prefix.   This
     2067         * forces us to interpret the instruction from opcodes, which is suboptimal.
     2068         * Both AMD-V and VT-x includes the address size in the exit info, at least on
     2069         * CPUs that are reasonably new.
     2070         *
     2071         * Of course, it's possible this is an undocumented and we just need to do some
     2072         * experiments to figure out how it's communicated.  Alternatively, we can scan
     2073         * the opcode bytes for possible evil prefixes.
     2074         */
     2075        nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2076        pCtx->fExtrn &= ~(  CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI
     2077                          | CPUMCTX_EXTRN_DS  | CPUMCTX_EXTRN_ES);
     2078        NEM_WIN_COPY_BACK_SEG(pCtx->ds, pExit->IoPortAccess.Ds);
     2079        NEM_WIN_COPY_BACK_SEG(pCtx->es, pExit->IoPortAccess.Es);
     2080        pCtx->rax = pExit->IoPortAccess.Rax;
     2081        pCtx->rcx = pExit->IoPortAccess.Rcx;
     2082        pCtx->rdi = pExit->IoPortAccess.Rdi;
     2083        pCtx->rsi = pExit->IoPortAccess.Rsi;
     2084# ifdef IN_RING0
     2085        rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit");
     2086        if (rcStrict != VINF_SUCCESS)
     2087            return rcStrict;
     2088# else
     2089        int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
     2090        AssertRCReturn(rc, rc);
     2091# endif
     2092
     2093        Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n",
     2094              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2095              pExit->IoPortAccess.AccessInfo.RepPrefix ? "REP " : "",
     2096              pExit->IoPortAccess.AccessInfo.IsWrite ? "OUTS" : "INS",
     2097              pExit->IoPortAccess.PortNumber, pExit->IoPortAccess.AccessInfo.AccessSize ));
     2098        rcStrict = IEMExecOne(pVCpu);
     2099    }
     2100    if (IOM_SUCCESS(rcStrict))
     2101    {
     2102        /*
     2103         * Do debug checks.
     2104         */
     2105        if (   pExit->VpContext.ExecutionState.DebugActive /** @todo Microsoft: Does DebugActive this only reflect DR7? */
     2106            || (pExit->VpContext.Rflags & X86_EFL_TF)
     2107            || DBGFBpIsHwIoArmed(pVM) )
     2108        {
     2109            /** @todo Debugging. */
     2110        }
     2111    }
     2112    return rcStrict;
     2113
     2114}
     2115#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2116
     2117#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    18282118/**
    18292119 * Deals with interrupt window message.
     
    18352125 * @param   pCtx            The register context.
    18362126 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     2127 * @sa      nemR3WinHandleExitInterruptWindow
    18372128 */
    1838 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageInterruptWindow(PVM pVM, PVMCPU pVCpu,
    1839                                                                   HV_X64_INTERRUPT_WINDOW_MESSAGE const *pMsg,
    1840                                                                   PCPUMCTX pCtx, PGVMCPU pGVCpu)
     2129NEM_TMPL_STATIC VBOXSTRICTRC
     2130nemHCWinHandleMessageInterruptWindow(PVM pVM, PVMCPU pVCpu, HV_X64_INTERRUPT_WINDOW_MESSAGE const *pMsg,
     2131                                     PCPUMCTX pCtx, PGVMCPU pGVCpu)
    18412132{
    18422133    /*
     
    18612152    return VINF_SUCCESS;
    18622153}
    1863 
    1864 
     2154#elif defined(IN_RING3)
     2155/**
     2156 * Deals with interrupt window exits (WHvRunVpExitReasonX64InterruptWindow).
     2157 *
     2158 * @returns Strict VBox status code.
     2159 * @param   pVM             The cross context VM structure.
     2160 * @param   pVCpu           The cross context per CPU structure.
     2161 * @param   pExit           The VM exit information to handle.
     2162 * @param   pCtx            The register context.
     2163 * @sa      nemHCWinHandleMessageInterruptWindow
     2164 */
     2165NEM_TMPL_STATIC VBOXSTRICTRC
     2166nemR3WinHandleExitInterruptWindow(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2167{
     2168    /*
     2169     * Assert message sanity.
     2170     */
     2171    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2172    AssertMsg(   pExit->InterruptWindow.DeliverableType == WHvX64PendingInterrupt
     2173              || pExit->InterruptWindow.DeliverableType == WHvX64PendingNmi,
     2174              ("%#x\n", pExit->InterruptWindow.DeliverableType));
     2175
     2176    /*
     2177     * Just copy the state we've got and handle it in the loop for now.
     2178     */
     2179    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2180    Log4(("IntWinExit/%u: %04x:%08RX64/%s: %u IF=%d InterruptShadow=%d\n",
     2181          pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip,  nemR3WinExecStateToLogStr(&pExit->VpContext),
     2182          pExit->InterruptWindow.DeliverableType, RT_BOOL(pExit->VpContext.Rflags & X86_EFL_IF),
     2183          pExit->VpContext.ExecutionState.InterruptShadow));
     2184
     2185    /** @todo call nemHCWinHandleInterruptFF   */
     2186    RT_NOREF(pVM);
     2187    return VINF_SUCCESS;
     2188}
     2189#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2190
     2191#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    18652192/**
    18662193 * Deals with CPUID intercept message.
     
    19062233    return VINF_SUCCESS;
    19072234}
    1908 
    1909 
     2235#elif defined(IN_RING3)
     2236/**
     2237 * Deals with CPUID exits (WHvRunVpExitReasonX64Cpuid).
     2238 *
     2239 * @returns Strict VBox status code.
     2240 * @param   pVM             The cross context VM structure.
     2241 * @param   pVCpu           The cross context per CPU structure.
     2242 * @param   pExit           The VM exit information to handle.
     2243 * @param   pCtx            The register context.
     2244 * @sa      nemHCWinHandleMessageInterruptWindow
     2245 */
     2246NEM_TMPL_STATIC VBOXSTRICTRC
     2247nemR3WinHandleExitCpuId(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2248{
     2249    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2250
     2251    /*
     2252     * Soak up state and execute the instruction.
     2253     *
     2254     * Note! If this grows slightly more complicated, combine into an IEMExecDecodedCpuId
     2255     *       function and make everyone use it.
     2256     */
     2257    /** @todo Combine implementations into IEMExecDecodedCpuId as this will
     2258     *        only get weirder with nested VT-x and AMD-V support. */
     2259    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2260
     2261    /* Copy in the low register values (top is always cleared). */
     2262    pCtx->rax = (uint32_t)pExit->CpuidAccess.Rax;
     2263    pCtx->rcx = (uint32_t)pExit->CpuidAccess.Rcx;
     2264    pCtx->rdx = (uint32_t)pExit->CpuidAccess.Rdx;
     2265    pCtx->rbx = (uint32_t)pExit->CpuidAccess.Rbx;
     2266    pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX);
     2267
     2268    /* Get the correct values. */
     2269    CPUMGetGuestCpuId(pVCpu, pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx);
     2270
     2271    Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n",
     2272          pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2273          pExit->CpuidAccess.Rax,                           pExit->CpuidAccess.Rcx,              pExit->CpuidAccess.Rdx,              pExit->CpuidAccess.Rbx,
     2274          pCtx->eax,                                                     pCtx->ecx,                           pCtx->edx,                           pCtx->ebx,
     2275          pExit->CpuidAccess.DefaultResultRax, pExit->CpuidAccess.DefaultResultRcx, pExit->CpuidAccess.DefaultResultRdx, pExit->CpuidAccess.DefaultResultRbx));
     2276
     2277    /* Move RIP and we're done. */
     2278    nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
     2279
     2280    RT_NOREF_PV(pVM);
     2281    return VINF_SUCCESS;
     2282}
     2283#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2284
     2285#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    19102286/**
    19112287 * Deals with MSR intercept message.
     
    19162292 * @param   pCtx            The register context.
    19172293 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     2294 * @sa      nemR3WinHandleExitMsr
    19182295 */
    19192296NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageMsr(PVMCPU pVCpu, HV_X64_MSR_INTERCEPT_MESSAGE const *pMsg,
     
    19312308     */
    19322309    VBOXSTRICTRC rcStrict;
    1933     if (pMsg->Header.CsSegment.DescriptorPrivilegeLevel == 0)
     2310    if (pMsg->Header.ExecutionState.Cpl == 0)
    19342311    {
    19352312        /*
     
    19382315        if (pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE)
    19392316        {
    1940             rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNummber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx));
     2317            rcStrict = CPUMSetGuestMsr(pVCpu, pMsg->MsrNumber, RT_MAKE_U64((uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx));
    19412318            Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n",
    19422319                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1943                   pMsg->MsrNummber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
     2320                  pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
    19442321            if (rcStrict == VINF_SUCCESS)
    19452322            {
     
    19482325                return VINF_SUCCESS;
    19492326            }
    1950 #ifndef IN_RING3
     2327# ifndef IN_RING3
    19512328            /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
    19522329            if (rcStrict == VERR_CPUM_RAISE_GP_0)
    19532330                rcStrict = VINF_CPUM_R3_MSR_WRITE;
    19542331            return rcStrict;
    1955 #else
     2332# else
    19562333            LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",
    19572334                    pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1958                     pMsg->MsrNummber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
    1959 #endif
     2335                    pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
     2336# endif
    19602337        }
    19612338        /*
     
    19652342        {
    19662343            uint64_t uValue = 0;
    1967             rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNummber, &uValue);
     2344            rcStrict = CPUMQueryGuestMsr(pVCpu, pMsg->MsrNumber, &uValue);
    19682345            Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
    19692346                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1970                   pMsg->MsrNummber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     2347                  pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
    19712348            if (rcStrict == VINF_SUCCESS)
    19722349            {
    19732350                nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
     2351                pCtx->rax = (uint32_t)uValue;
     2352                pCtx->rdx = uValue >> 32;
     2353                pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
    19742354                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
    19752355                return VINF_SUCCESS;
    19762356            }
    1977 #ifndef IN_RING3
     2357# ifndef IN_RING3
    19782358            /* move to ring-3 and handle the trap/whatever there, as we want to LogRel this. */
    19792359            if (rcStrict == VERR_CPUM_RAISE_GP_0)
    19802360                rcStrict = VINF_CPUM_R3_MSR_READ;
    19812361            return rcStrict;
    1982 #else
     2362# else
    19832363            LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
    19842364                    pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1985                     pMsg->MsrNummber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
    1986 #endif
     2365                    pMsg->MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     2366# endif
    19872367        }
    19882368    }
     
    19902370        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); WRMSR %08x, %08x:%08x\n",
    19912371              pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1992               pMsg->Header.CsSegment.DescriptorPrivilegeLevel, pMsg->MsrNummber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx ));
     2372              pMsg->Header.ExecutionState.Cpl, pMsg->MsrNumber, (uint32_t)pMsg->Rax, (uint32_t)pMsg->Rdx ));
    19932373    else
    19942374        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); RDMSR %08x\n",
    19952375              pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header),
    1996               pMsg->Header.CsSegment.DescriptorPrivilegeLevel, pMsg->MsrNummber));
     2376              pMsg->Header.ExecutionState.Cpl, pMsg->MsrNumber));
    19972377
    19982378    /*
     
    20102390    return rcStrict;
    20112391}
    2012 
    2013 
     2392#elif defined(IN_RING3)
     2393/**
     2394 * Deals with MSR access exits (WHvRunVpExitReasonX64MsrAccess).
     2395 *
     2396 * @returns Strict VBox status code.
     2397 * @param   pVM             The cross context VM structure.
     2398 * @param   pVCpu           The cross context per CPU structure.
     2399 * @param   pExit           The VM exit information to handle.
     2400 * @param   pCtx            The register context.
     2401 * @sa      nemHCWinHandleMessageMsr
     2402 */
     2403NEM_TMPL_STATIC VBOXSTRICTRC
     2404nemR3WinHandleExitMsr(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2405{
     2406    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2407
     2408    /*
     2409     * Check CPL as that's common to both RDMSR and WRMSR.
     2410     */
     2411    VBOXSTRICTRC rcStrict;
     2412    if (pExit->VpContext.ExecutionState.Cpl == 0)
     2413    {
     2414        /*
     2415         * Handle writes.
     2416         */
     2417        if (pExit->MsrAccess.AccessInfo.IsWrite)
     2418        {
     2419            rcStrict = CPUMSetGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber,
     2420                                       RT_MAKE_U64((uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx));
     2421            Log4(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc\n",
     2422                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2423                  pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
     2424            if (rcStrict == VINF_SUCCESS)
     2425            {
     2426                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2427                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
     2428                return VINF_SUCCESS;
     2429            }
     2430            LogRel(("MsrExit/%u: %04x:%08RX64/%s: WRMSR %08x, %08x:%08x -> %Rrc!\n",
     2431                    pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2432                    pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx, VBOXSTRICTRC_VAL(rcStrict) ));
     2433        }
     2434        /*
     2435         * Handle reads.
     2436         */
     2437        else
     2438        {
     2439            uint64_t uValue = 0;
     2440            rcStrict = CPUMQueryGuestMsr(pVCpu, pExit->MsrAccess.MsrNumber, &uValue);
     2441            Log4(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
     2442                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2443                  pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     2444            if (rcStrict == VINF_SUCCESS)
     2445            {
     2446                nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2447                pCtx->rax = (uint32_t)uValue;
     2448                pCtx->rdx = uValue >> 32;
     2449                pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX);
     2450                nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);
     2451                return VINF_SUCCESS;
     2452            }
     2453            LogRel(("MsrExit/%u: %04x:%08RX64/%s: RDMSR %08x -> %08RX64 / %Rrc\n",
     2454                    pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2455                    pExit->MsrAccess.MsrNumber, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     2456        }
     2457    }
     2458    else if (pExit->MsrAccess.AccessInfo.IsWrite)
     2459        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); WRMSR %08x, %08x:%08x\n",
     2460              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2461              pExit->VpContext.ExecutionState.Cpl, pExit->MsrAccess.MsrNumber, (uint32_t)pExit->MsrAccess.Rax, (uint32_t)pExit->MsrAccess.Rdx ));
     2462    else
     2463        Log4(("MsrExit/%u: %04x:%08RX64/%s: CPL %u -> #GP(0); RDMSR %08x\n",
     2464              pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext),
     2465              pExit->VpContext.ExecutionState.Cpl, pExit->MsrAccess.MsrNumber));
     2466
     2467    /*
     2468     * If we get down here, we're supposed to #GP(0).
     2469     */
     2470    rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "NMI");
     2471    if (rcStrict == VINF_SUCCESS)
     2472    {
     2473        rcStrict = IEMInjectTrap(pVCpu, X86_XCPT_GP, TRPM_TRAP, 0, 0, 0);
     2474        if (rcStrict == VINF_IEM_RAISED_XCPT)
     2475            rcStrict = VINF_SUCCESS;
     2476        else if (rcStrict != VINF_SUCCESS)
     2477            Log4(("MsrExit/%u: Injecting #GP(0) failed: %Rrc\n", VBOXSTRICTRC_VAL(rcStrict) ));
     2478    }
     2479
     2480    RT_NOREF_PV(pVM);
     2481    return rcStrict;
     2482}
     2483#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2484
     2485#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    20142486/**
    20152487 * Deals with unrecoverable exception (triple fault).
     
    20232495 * @param   pCtx            The register context.
    20242496 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     2497 * @sa      nemR3WinHandleExitUnrecoverableException
    20252498 */
    20262499NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageUnrecoverableException(PVMCPU pVCpu,
     
    20282501                                                                         PCPUMCTX pCtx, PGVMCPU pGVCpu)
    20292502{
    2030     /*
    2031      * Assert message sanity.
    2032      */
    2033     //Assert(   pMsgHdr->InterceptAccessType == HV_INTERCEPT_ACCESS_EXECUTE
    2034     //       || pMsgHdr->InterceptAccessType == HV_INTERCEPT_ACCESS_READ   // READ & WRITE are probably not used here
    2035     //       || pMsgHdr->InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE);
    20362503    AssertMsg(pMsgHdr->InstructionLength < 0x10, ("%#x\n", pMsgHdr->InstructionLength));
    20372504
    2038 #if 0
     2505# if 0
    20392506    /*
    20402507     * Just copy the state we've got and handle it in the loop for now.
     
    20442511         pVCpu->idCpu, pMsgHdr->CsSegment.Selector, pMsgHdr->Rip, nemHCWinExecStateToLogStr(&pMsg->Header), pMsgHdr->Rflags));
    20452512    return VINF_EM_TRIPLE_FAULT;
    2046 #else
     2513# else
    20472514    /*
    20482515     * Let IEM decide whether this is really it.
    20492516     */
    2050 /** @todo check if this happens becaused of incorrectly pending interrupts of smth. */
    20512517    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, pMsgHdr);
    2052     VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM | CPUMCTX_EXTRN_ALL, "TripleExit");
     2518    VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx,
     2519                                                              NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM | CPUMCTX_EXTRN_ALL, "TripleExit");
    20532520    if (rcStrict == VINF_SUCCESS)
    20542521    {
     
    20722539             pMsgHdr->Rip, nemHCWinExecStateToLogStr(pMsgHdr), pMsgHdr->Rflags, VBOXSTRICTRC_VAL(rcStrict) ));
    20732540    return rcStrict;
    2074 #endif
    2075 }
    2076 
    2077 
     2541# endif
     2542}
     2543#elif defined(IN_RING3)
     2544/**
     2545 * Deals with MSR access exits (WHvRunVpExitReasonUnrecoverableException).
     2546 *
     2547 * @returns Strict VBox status code.
     2548 * @param   pVM             The cross context VM structure.
     2549 * @param   pVCpu           The cross context per CPU structure.
     2550 * @param   pExit           The VM exit information to handle.
     2551 * @param   pCtx            The register context.
     2552 * @sa      nemHCWinHandleMessageUnrecoverableException
     2553 */
     2554NEM_TMPL_STATIC VBOXSTRICTRC
     2555nemR3WinHandleExitUnrecoverableException(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2556{
     2557    AssertMsg(pExit->VpContext.InstructionLength < 0x10, ("%#x\n", pExit->VpContext.InstructionLength));
     2558
     2559# if 0
     2560    /*
     2561     * Just copy the state we've got and handle it in the loop for now.
     2562     */
     2563    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2564    Log(("TripleExit/%u: %04x:%08RX64/%s: RFL=%#RX64 -> VINF_EM_TRIPLE_FAULT\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
     2565         pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.Rflags));
     2566    RT_NOREF_PV(pVM);
     2567    return VINF_EM_TRIPLE_FAULT;
     2568# else
     2569    /*
     2570     * Let IEM decide whether this is really it.
     2571     */
     2572    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
     2573    VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx,
     2574                                                              NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM | CPUMCTX_EXTRN_ALL, "TripleExit");
     2575    if (rcStrict == VINF_SUCCESS)
     2576    {
     2577        rcStrict = IEMExecOne(pVCpu);
     2578        if (rcStrict == VINF_SUCCESS)
     2579        {
     2580            Log(("UnrecovExit/%u: %04x:%08RX64/%s: RFL=%#RX64 -> VINF_SUCCESS\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
     2581                 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.Rflags));
     2582            pCtx->fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT; /* Make sure to reset pending #DB(0). */
     2583            return VINF_SUCCESS;
     2584        }
     2585        if (rcStrict == VINF_EM_TRIPLE_FAULT)
     2586            Log(("UnrecovExit/%u: %04x:%08RX64/%s: RFL=%#RX64 -> VINF_EM_TRIPLE_FAULT!\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
     2587                 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.Rflags, VBOXSTRICTRC_VAL(rcStrict) ));
     2588        else
     2589            Log(("UnrecovExit/%u: %04x:%08RX64/%s: RFL=%#RX64 -> %Rrc (IEMExecOne)\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
     2590                 pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.Rflags, VBOXSTRICTRC_VAL(rcStrict) ));
     2591    }
     2592    else
     2593        Log(("UnrecovExit/%u: %04x:%08RX64/%s: RFL=%#RX64 -> %Rrc (state import)\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
     2594             pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.Rflags, VBOXSTRICTRC_VAL(rcStrict) ));
     2595    RT_NOREF_PV(pVM);
     2596    return rcStrict;
     2597# endif
     2598
     2599}
     2600#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2601
     2602#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    20782603/**
    20792604 * Handles messages (VM exits).
     
    20852610 * @param   pCtx            The register context.
    20862611 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
     2612 * @sa      nemR3WinHandleExit
    20872613 */
    20882614NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessage(PVM pVM, PVMCPU pVCpu, VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader,
     
    21402666                LogRel(("Unimplemented msg:\n%.*Rhxd\n", (int)sizeof(*pMsg), pMsg));
    21412667                AssertLogRelMsgFailedReturn(("Message type %#x not implemented!\n%.32Rhxd\n", pMsg->Header.MessageType, pMsg),
    2142                                             VERR_INTERNAL_ERROR_2);
     2668                                            VERR_NEM_IPE_3);
    21432669
    21442670            case HvMessageTypeX64ExceptionIntercept:
     
    21522678                LogRel(("Unexpected msg:\n%.*Rhxd\n", (int)sizeof(*pMsg), pMsg));
    21532679                AssertLogRelMsgFailedReturn(("Unexpected message on CPU #%u: %#x\n", pVCpu->idCpu, pMsg->Header.MessageType),
    2154                                             VERR_INTERNAL_ERROR_2);
     2680                                            VERR_NEM_IPE_3);
    21552681
    21562682            default:
    21572683                LogRel(("Unknown msg:\n%.*Rhxd\n", (int)sizeof(*pMsg), pMsg));
    21582684                AssertLogRelMsgFailedReturn(("Unknown message on CPU #%u: %#x\n", pVCpu->idCpu, pMsg->Header.MessageType),
    2159                                             VERR_INTERNAL_ERROR_2);
     2685                                            VERR_NEM_IPE_3);
    21602686        }
    21612687    }
     
    21632689        AssertLogRelMsgFailedReturn(("Unexpected VID message type on CPU #%u: %#x LB %u\n",
    21642690                                     pVCpu->idCpu, pMappingHeader->enmVidMsgType, pMappingHeader->cbMessage),
    2165                                     VERR_INTERNAL_ERROR_3);
    2166 }
    2167 
    2168 
     2691                                    VERR_NEM_IPE_4);
     2692}
     2693#elif defined(IN_RING3)
     2694/**
     2695 * Handles VM exits.
     2696 *
     2697 * @returns Strict VBox status code.
     2698 * @param   pVM             The cross context VM structure.
     2699 * @param   pVCpu           The cross context per CPU structure.
     2700 * @param   pExit           The VM exit information to handle.
     2701 * @param   pCtx            The register context.
     2702 * @sa      nemHCWinHandleMessage
     2703 */
     2704NEM_TMPL_STATIC VBOXSTRICTRC nemR3WinHandleExit(PVM pVM, PVMCPU pVCpu, WHV_RUN_VP_EXIT_CONTEXT const *pExit, PCPUMCTX pCtx)
     2705{
     2706    switch (pExit->ExitReason)
     2707    {
     2708        case WHvRunVpExitReasonMemoryAccess:
     2709            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitMemUnmapped);
     2710            return nemR3WinHandleExitMemory(pVM, pVCpu, pExit, pCtx);
     2711
     2712        case WHvRunVpExitReasonX64IoPortAccess:
     2713            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitPortIo);
     2714            return nemR3WinHandleExitIoPort(pVM, pVCpu, pExit, pCtx);
     2715
     2716        case WHvRunVpExitReasonX64Halt:
     2717            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHalt);
     2718            Log4(("HaltExit\n"));
     2719            return VINF_EM_HALT;
     2720
     2721        case WHvRunVpExitReasonCanceled:
     2722            return VINF_SUCCESS;
     2723
     2724        case WHvRunVpExitReasonX64InterruptWindow:
     2725            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitInterruptWindow);
     2726            return nemR3WinHandleExitInterruptWindow(pVM, pVCpu, pExit, pCtx);
     2727
     2728        case WHvRunVpExitReasonX64Cpuid:
     2729            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitCpuId);
     2730            return nemR3WinHandleExitCpuId(pVM, pVCpu, pExit, pCtx);
     2731
     2732        case WHvRunVpExitReasonX64MsrAccess:
     2733            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitMsr);
     2734            return nemR3WinHandleExitMsr(pVM, pVCpu, pExit, pCtx);
     2735
     2736        case WHvRunVpExitReasonUnrecoverableException:
     2737            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitUnrecoverable);
     2738            return nemR3WinHandleExitUnrecoverableException(pVM, pVCpu, pExit, pCtx);
     2739
     2740        case WHvRunVpExitReasonException: /* needs configuring */
     2741        case WHvRunVpExitReasonUnsupportedFeature:
     2742        case WHvRunVpExitReasonInvalidVpRegisterValue:
     2743            LogRel(("Unimplemented exit:\n%.*Rhxd\n", (int)sizeof(*pExit), pExit));
     2744            AssertLogRelMsgFailedReturn(("Unexpected exit on CPU #%u: %#x\n%.32Rhxd\n",
     2745                                         pVCpu->idCpu, pExit->ExitReason, pExit), VERR_NEM_IPE_3);
     2746
     2747        /* Undesired exits: */
     2748        case WHvRunVpExitReasonNone:
     2749        default:
     2750            LogRel(("Unknown exit:\n%.*Rhxd\n", (int)sizeof(*pExit), pExit));
     2751            AssertLogRelMsgFailedReturn(("Unknown exit on CPU #%u: %#x!\n", pVCpu->idCpu, pExit->ExitReason), VERR_NEM_IPE_3);
     2752    }
     2753}
     2754#endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     2755
     2756#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    21692757/**
    21702758 * Worker for nemHCWinRunGC that stops the execution on the way out.
     
    22192807# ifdef IN_RING0
    22202808    AssertLogRelMsgReturn(rcNt == ERROR_VID_STOP_PENDING, ("rcNt=%#x\n", rcNt),
    2221                           RT_SUCCESS(rcStrict) ?  VERR_INTERNAL_ERROR_3 : rcStrict);
     2809                          RT_SUCCESS(rcStrict) ?  VERR_NEM_IPE_5 : rcStrict);
    22222810# else
    22232811    DWORD dwErr = RTNtLastErrorValue();
    22242812    AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u (%#x)\n", dwErr, dwErr),
    2225                           RT_SUCCESS(rcStrict) ?  VERR_INTERNAL_ERROR_3 : rcStrict);
     2813                          RT_SUCCESS(rcStrict) ?  VERR_NEM_IPE_5 : rcStrict);
    22262814# endif
    22272815    Log8(("nemHCWinStopCpu: Stopping CPU pending...\n"));
     
    22412829                                   NULL, 0);
    22422830    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
    2243                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2831                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22442832# else
    22452833    BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    22462834                                                     VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/);
    22472835    AssertLogRelMsgReturn(fWait, ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
    2248                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2836                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22492837# endif
    22502838
     
    22542842                          ("Unexpected 1st message following ERROR_VID_STOP_PENDING: %#x LB %#x\n",
    22552843                           enmVidMsgType, pMappingHeader->cbMessage),
    2256                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2844                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22572845
    22582846    VBOXSTRICTRC rcStrict2 = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, CPUMQueryGuestCtxPtr(pVCpu), pGVCpu);
     
    22732861                                   NULL, 0);
    22742862    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("2st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
    2275                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2863                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22762864# else
    22772865    fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    22782866                                                VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/);
    22792867    AssertLogRelMsgReturn(fWait, ("2nd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
    2280                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2868                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22812869# endif
    22822870
     
    22862874                          ("Unexpected 2nd message following ERROR_VID_STOP_PENDING: %#x LB %#x\n",
    22872875                           enmVidMsgType, pMappingHeader->cbMessage),
    2288                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2876                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    22892877
    22902878    /* Mark this as handled. */
     
    22982886                                   NULL, 0);
    22992887    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
    2300                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2888                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    23012889# else
    23022890    fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, VID_MSHAGN_F_HANDLE_MESSAGE, 30000 /*ms*/);
    23032891    AssertLogRelMsgReturn(fWait, ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
    2304                           RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     2892                          RT_SUCCESS(rcStrict) ? VERR_NEM_IPE_5 : rcStrict);
    23052893# endif
    23062894    Log8(("nemHCWinStopCpu: Stopped the CPU (rcStrict=%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict) ));
    23072895    return rcStrict;
    23082896}
    2309 
     2897#endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
     2898
     2899#if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3)
    23102900
    23112901/**
     
    23192909 * @param   pfInterruptWindows  Where to return interrupt window flags.
    23202910 */
    2321 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleInterruptFF(PVM pVM, PVMCPU pVCpu, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint8_t *pfInterruptWindows)
     2911NEM_TMPL_STATIC VBOXSTRICTRC
     2912nemHCWinHandleInterruptFF(PVM pVM, PVMCPU pVCpu, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint8_t *pfInterruptWindows)
    23222913{
    23232914    Assert(!TRPMHasTrap(pVCpu));
     
    23382929     * We don't currently implement SMIs.
    23392930     */
    2340     AssertReturn(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_SMI), VINF_NEM_IPE_0);
     2931    AssertReturn(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_SMI), VERR_NEM_IPE_0);
    23412932
    23422933    /*
     
    24143005
    24153006
     3007/**
     3008 * Inner NEM runloop for windows.
     3009 *
     3010 * @returns Strict VBox status code.
     3011 * @param   pVM             The cross context VM structure.
     3012 * @param   pVCpu           The cross context per CPU structure.
     3013 * @param   pGVM            The ring-0 VM structure (NULL in ring-3).
     3014 * @param   pGVCpu          The ring-0 per CPU structure (NULL in ring-3).
     3015 */
    24163016NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu, PGVM pGVM, PGVMCPU pGVCpu)
    24173017{
     
    24413041     * everything every time.  This will be optimized later.
    24423042     */
     3043# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    24433044    VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader = (VID_MESSAGE_MAPPING_HEADER volatile *)pVCpu->nem.s.pvMsgSlotMapping;
    24443045    uint32_t        cMillies            = 5000; /** @todo lower this later... */
     3046# endif
    24453047    const bool      fSingleStepping     = DBGFIsStepping(pVCpu);
    24463048//    const uint32_t  fCheckVmFFs         = !fSingleStepping ? VM_FF_HP_R0_PRE_HM_MASK
     
    24503052    for (unsigned iLoop = 0;; iLoop++)
    24513053    {
     3054# ifndef NEM_WIN_USE_HYPERCALLS_FOR_PAGES
     3055        /*
     3056         * Hack alert!
     3057         */
     3058        uint32_t const cMappedPages = pVM->nem.s.cMappedPages;
     3059        if (cMappedPages >= 4000)
     3060        {
     3061            PGMPhysNemEnumPagesByState(pVM, pVCpu, NEM_WIN_PAGE_STATE_READABLE, nemR3WinWHvUnmapOnePageCallback, NULL);
     3062            Log(("nemHCWinRunGC: Unmapped all; cMappedPages=%u -> %u\n", cMappedPages, pVM->nem.s.cMappedPages));
     3063        }
     3064# endif
     3065
    24523066        /*
    24533067         * Pending interrupts or such?  Need to check and deal with this prior
     
    24583072                                     | VMCPU_FF_INTERRUPT_NMI  | VMCPU_FF_INTERRUPT_SMI))
    24593073        {
     3074# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    24603075            /* Make sure the CPU isn't executing. */
    24613076            if (pVCpu->nem.s.fHandleAndGetFlags == VID_MSHAGN_F_GET_NEXT_MESSAGE)
     
    24723087                }
    24733088            }
     3089# endif
    24743090
    24753091            /* Try inject interrupt. */
     
    24953111            || pVCpu->nem.s.fCurrentInterruptWindows != pVCpu->nem.s.fDesiredInterruptWindows)
    24963112        {
     3113# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    24973114            Assert(pVCpu->nem.s.fHandleAndGetFlags != VID_MSHAGN_F_GET_NEXT_MESSAGE /* not running */);
     3115# endif
    24983116# ifdef IN_RING0
    24993117            int rc2 = nemR0WinExportState(pGVM, pGVCpu, pCtx);
     
    25113129            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    25123130        {
     3131# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    25133132            if (pVCpu->nem.s.fHandleAndGetFlags)
    25143133            { /* Very likely that the CPU does NOT need starting (pending msg, running). */ }
    25153134            else
    25163135            {
    2517 # ifdef IN_RING0
     3136#  ifdef IN_RING0
    25183137                pVCpu->nem.s.uIoCtlBuf.idCpu = pGVCpu->idCpu;
    25193138                NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction,
     
    25223141                LogFlow(("NEM/%u: IoCtlStartVirtualProcessor -> %#x\n", pVCpu->idCpu, rcNt));
    25233142                AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("VidStartVirtualProcessor failed for CPU #%u: %#x\n", pGVCpu->idCpu, rcNt),
    2524                                       VERR_INTERNAL_ERROR_3);
    2525 # else
     3143                                      VERR_NEM_IPE_5);
     3144#  else
    25263145                AssertLogRelMsgReturn(g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
    25273146                                      ("VidStartVirtualProcessor failed for CPU #%u: %u (%#x, rcNt=%#x)\n",
    25283147                                       pVCpu->idCpu, RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()),
    2529                                       VERR_INTERNAL_ERROR_3);
    2530 # endif
     3148                                      VERR_NEM_IPE_5);
     3149#  endif
    25313150                pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    25323151            }
     3152# endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
    25333153
    25343154            if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM))
    25353155            {
    2536 # ifdef IN_RING0
     3156# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3157#  ifdef IN_RING0
    25373158                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
    25383159                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags   = pVCpu->nem.s.fHandleAndGetFlags;
     
    25443165                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
    25453166                if (rcNt == STATUS_SUCCESS)
    2546 # else
     3167#  else
    25473168                BOOL fRet = VidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    25483169                                                           pVCpu->nem.s.fHandleAndGetFlags, cMillies);
    25493170                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
    25503171                if (fRet)
     3172#  endif
     3173# else
     3174                WHV_RUN_VP_EXIT_CONTEXT ExitReason;
     3175                RT_ZERO(ExitReason);
     3176                HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
     3177                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     3178                if (SUCCEEDED(hrc))
    25513179# endif
    25523180                {
     
    25543182                     * Deal with the message.
    25553183                     */
     3184# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    25563185                    rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pCtx, pGVCpu);
    25573186                    pVCpu->nem.s.fHandleAndGetFlags |= VID_MSHAGN_F_HANDLE_MESSAGE;
     3187# else
     3188                    rcStrict = nemR3WinHandleExit(pVM, pVCpu, &ExitReason, pCtx);
     3189# endif
    25583190                    if (rcStrict == VINF_SUCCESS)
    25593191                    { /* hopefully likely */ }
     
    25673199                else
    25683200                {
     3201# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3202
    25693203                    /* VID.SYS merges STATUS_ALERTED and STATUS_USER_APC into STATUS_TIMEOUT,
    25703204                       so after NtAlertThread we end up here with a STATUS_TIMEOUT.  And yeah,
    25713205                       the error code conversion is into WAIT_XXX, i.e. NT status codes. */
    2572 # ifndef IN_RING0
     3206#  ifndef IN_RING0
    25733207                    DWORD rcNt = GetLastError();
    2574 # endif
     3208#  endif
    25753209                    LogFlow(("NEM/%u: VidMessageSlotHandleAndGetNext -> %#x\n", pVCpu->idCpu, rcNt));
    25763210                    AssertLogRelMsgReturn(   rcNt == STATUS_TIMEOUT
    25773211                                          || rcNt == STATUS_ALERTED  /* just in case */
    25783212                                          || rcNt == STATUS_USER_APC /* ditto */
    2579                                           , ("VidMessageSlotHandleAndGetNext failed for CPU #%u: %#x (%u)\n", pVCpu->idCpu, rcNt, rcNt),
    2580                                           VERR_INTERNAL_ERROR_3);
     3213                                          , ("VidMessageSlotHandleAndGetNext failed for CPU #%u: %#x (%u)\n",
     3214                                             pVCpu->idCpu, rcNt, rcNt),
     3215                                          VERR_NEM_IPE_0);
    25813216                    pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    25823217                    STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatGetMsgTimeout);
     3218# else
     3219                    AssertLogRelMsgFailedReturn(("WHvRunVirtualProcessor failed for CPU #%u: %#x (%u)\n",
     3220                                                 pVCpu->idCpu, hrc, GetLastError()),
     3221                                                VERR_NEM_IPE_0);
     3222
     3223# endif
    25833224                }
    25843225
     
    26153256     * state and return to EM.
    26163257     */
     3258# ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    26173259    if (pVCpu->nem.s.fHandleAndGetFlags == VID_MSHAGN_F_GET_NEXT_MESSAGE)
    26183260    {
     
    26203262        rcStrict = nemHCWinStopCpu(pVM, pVCpu, rcStrict, pMappingHeader, pGVM, pGVCpu);
    26213263    }
     3264# endif
    26223265
    26233266    if (!VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM))
     
    26573300}
    26583301
    2659 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
    2660 
     3302#endif /* defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3) */
    26613303
    26623304/**
     
    26903332            LogRel(("nemHCWinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    26913333                    GCPhys, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    2692             return VERR_INTERNAL_ERROR_2;
     3334            return VERR_NEM_IPE_2;
    26933335#endif
    26943336        }
     
    30113653    LogRel(("nemHCJustUnmapPageFromHyperV(%RGp): failed! hrc=%Rhrc (%#x) Last=%#x/%u\n",
    30123654            GCPhysDst, hrc, hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    3013     return VERR_INTERNAL_ERROR_3;
     3655    return VERR_NEM_IPE_6;
    30143656#endif
    30153657}
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r72403 r72412  
    22702270                    LogRel(("HvCallGetMemoryBalance -> %#RX64 (%#RX64 %#RX64)!!\n",
    22712271                            uResult, pOutput->PagesAvailable, pOutput->PagesInUse));
    2272                     rc = VINF_NEM_IPE_0;
     2272                    rc = VERR_NEM_IPE_0;
    22732273                }
    22742274
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72392 r72412  
    14401440}
    14411441
    1442 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API
     1442#if 0 //ndef NEM_WIN_USE_OUR_OWN_RUN_API - migrating to NEMAllNativeTemplate-win.cpp.h  */
    14431443
    14441444# ifdef LOG_ENABLED
     
    15591559}
    15601560# endif /* LOG_ENABLED */
    1561 
    1562 
    1563 /**
    1564  * Advances the guest RIP and clear EFLAGS.RF.
    1565  *
    1566  * This may clear VMCPU_FF_INHIBIT_INTERRUPTS.
    1567  *
    1568  * @param   pVCpu           The cross context virtual CPU structure.
    1569  * @param   pCtx            The CPU context to update.
    1570  * @param   pExitCtx        The exit context.
    1571  */
    1572 DECLINLINE(void) nemR3WinAdvanceGuestRipAndClearRF(PVMCPU pVCpu, PCPUMCTX pCtx, WHV_VP_EXIT_CONTEXT const *pExitCtx)
    1573 {
    1574     /* Advance the RIP. */
    1575     Assert(pExitCtx->InstructionLength > 0 && pExitCtx->InstructionLength < 16);
    1576     pCtx->rip += pExitCtx->InstructionLength;
    1577     pCtx->rflags.Bits.u1RF = 0;
    1578 
    1579     /* Update interrupt inhibition. */
    1580     if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    1581     { /* likely */ }
    1582     else if (pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
    1583         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    1584 }
    15851561
    15861562
     
    20312007}
    20322008
    2033 #endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */
     2009#endif /* !NEM_WIN_USE_OUR_OWN_RUN_API - migrating to NEMAllNativeTemplate-win.cpp.h*/
    20342010
    20352011
    20362012VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
    20372013{
    2038 #ifndef NEM_WIN_USE_OUR_OWN_RUN_API
    2039     return nemR3WinWHvRunGC(pVM, pVCpu);
    2040 #elif 0
     2014#if !defined(NEM_WIN_USE_OUR_OWN_RUN_API) || 0
    20412015    return nemHCWinRunGC(pVM, pVCpu, NULL /*pGVM*/, NULL /*pGVCpu*/);
    20422016#else
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r72392 r72412  
    4949# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    5050#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
     51# endif
     52# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
     53#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
    5154# endif
    5255
Note: See TracChangeset for help on using the changeset viewer.

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