VirtualBox

Ignore:
Timestamp:
Feb 16, 2018 4:24:43 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120903
Message:

NEM: More code - DSL is getting somewhere now, but VRAM access sucks. bugref:9044

File:
1 edited

Legend:

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

    r71035 r71040  
    55 * Log group 2: Exit logging.
    66 * Log group 3: Log context on exit.
     7 * Log group 12: API intercepts.
    78 */
    89
     
    6970#define NEM_WIN_PAGE_STATE_WRITABLE     3
    7071/** @} */
     72
     73/** Checks if a_GCPhys is subject to the limited A20 gate emulation.  */
     74#define NEM_WIN_IS_SUBJECT_TO_A20(a_GCPhys)     ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K)
     75
     76/** Checks if a_GCPhys is relevant to the limited A20 gate emulation.  */
     77#define NEM_WIN_IS_RELEVANT_TO_A20(a_GCPhys)    \
     78    ( ((RTGCPHYS)((a_GCPhys) - _1M) < (RTGCPHYS)_64K) || ((RTGCPHYS)(a_GCPhys) < (RTGCPHYS)_64K) )
    7179
    7280
     
    149157#endif
    150158
     159/** NEM_WIN_PAGE_STATE_XXX names. */
     160static const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" };
     161/** WHV_MEMORY_ACCESS_TYPE names */
     162static const char * const g_apszWHvMemAccesstypes[4] = { "read", "write", "exec", "!undefined!" };
     163
    151164
    152165/*********************************************************************************************************************************
    153166*   Internal Functions                                                                                                           *
    154167*********************************************************************************************************************************/
    155 static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhys, uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged);
     168static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt,
     169                                  uint8_t *pu2State, bool fBackingChanged);
    156170
    157171
     
    174188                                               pvInput, cbInput, pvOutput, cbOutput);
    175189    if (!hEvt && !pfnApcCallback && !pvApcCtx)
    176         Log6(("VID!NtDeviceIoControlFile: hFile=%#zx pIos=%p->{s:%#x, i:%#zx} uFunction=%#x Input=%p LB %#x Output=%p LB %#x) -> %#x; Caller=%p\n",
    177               hFile, pIos, pIos->Status, pIos->Information, uFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     190        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",
     191               hFile, pIos, pIos->Status, pIos->Information, uFunction, pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
    178192    else
    179         Log6(("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",
    180               hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, uFunction,
    181               pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
     193        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",
     194               hFile, hEvt, pfnApcCallback, pvApcCtx, pIos, pIos->Status, pIos->Information, uFunction,
     195               pvInput, cbInput, pvOutput, cbOutput, rcNt, ASMReturnAddress()));
    182196    return rcNt;
    183197}
     
    869883
    870884
     885/**
     886 * VM reset notification.
     887 *
     888 * @param   pVM         The cross context VM structure.
     889 */
    871890void nemR3NativeReset(PVM pVM)
    872891{
    873     NOREF(pVM);
    874 }
    875 
    876 
    877 void nemR3NativeResetCpu(PVMCPU pVCpu)
    878 {
    879     NOREF(pVCpu);
     892    /* Unfix the A20 gate. */
     893    pVM->nem.s.fA20Fixed = false;
     894}
     895
     896
     897/**
     898 * Reset CPU due to INIT IPI or hot (un)plugging.
     899 *
     900 * @param   pVCpu       The cross context virtual CPU structure of the CPU being
     901 *                      reset.
     902 * @param   fInitIpi    Whether this is the INIT IPI or hot (un)plugging case.
     903 */
     904void nemR3NativeResetCpu(PVMCPU pVCpu, bool fInitIpi)
     905{
     906    /* Lock the A20 gate if INIT IPI, make sure it's enabled.  */
     907    if (fInitIpi && pVCpu->idCpu > 0)
     908    {
     909        PVM pVM = pVCpu->CTX_SUFF(pVM);
     910        if (!pVM->nem.s.fA20Enabled)
     911            nemR3NativeNotifySetA20(pVCpu, true);
     912        pVM->nem.s.fA20Enabled = true;
     913        pVM->nem.s.fA20Fixed   = true;
     914    }
    880915}
    881916
     
    11601195    Assert(iReg < RT_ELEMENTS(aenmNames));
    11611196#ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    1162     Log6(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    1163           pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));
     1197    Log12(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
     1198           pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));
    11641199#endif
    11651200    HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues);
     
    12871322    Assert(RT_ELEMENTS(aenmNames) >= cRegs);
    12881323#ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    1289     Log6(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
     1324    Log12(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    12901325          pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues));
    12911326#endif
     
    13471382        /* Control registers. */
    13481383        Assert(aenmNames[28] == WHvX64RegisterCr0);
     1384        bool fMaybeChangedMode = false;
     1385        bool fFlushTlb         = false;
     1386        bool fFlushGlobalTlb   = false;
    13491387        if (pCtx->cr0 != aValues[28].Reg64)
    13501388        {
    13511389            CPUMSetGuestCR0(pVCpu, aValues[28].Reg64);
    1352             /** @todo more to do here! */
     1390            fMaybeChangedMode = true;
     1391            fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
    13531392        }
    13541393        pCtx->cr2 = aValues[29].Reg64;
     
    13561395        {
    13571396            CPUMSetGuestCR3(pVCpu, aValues[30].Reg64);
    1358             /** @todo more to do here! */
     1397            fFlushTlb = true;
    13591398        }
    13601399        if (pCtx->cr4 != aValues[31].Reg64)
    13611400        {
    13621401            CPUMSetGuestCR4(pVCpu, aValues[31].Reg64);
    1363             /** @todo more to do here! */
     1402            fMaybeChangedMode = true;
     1403            fFlushTlb = fFlushGlobalTlb = true; /// @todo fix this
    13641404        }
    13651405        APICSetTpr(pVCpu, (uint8_t)aValues[32].Reg64 << 4);
     
    14621502        {
    14631503            pCtx->msrEFER = aValues[65].Reg64;
    1464             /** @todo more to do here! */
     1504            fMaybeChangedMode = true;
    14651505        }
    14661506
     
    14961536
    14971537
     1538        if (fMaybeChangedMode)
     1539        {
     1540            int rc = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
     1541            AssertRC(rc);
     1542        }
     1543        if (fFlushTlb)
     1544        {
     1545            int rc = PGMFlushTLB(pVCpu, pCtx->cr3, fFlushGlobalTlb);
     1546            AssertRC(rc);
     1547        }
     1548
    14981549        return VINF_SUCCESS;
    14991550    }
     
    15211572            Log2(("Exit: Memory access: GCPhys=%RGp GCVirt=%RGv %s %s %s\n",
    15221573                  pExitReason->MemoryAccess.Gpa, pExitReason->MemoryAccess.Gva,
    1523                   pExitReason->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessRead ? "read"
    1524                   : pExitReason->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite ? "write"
    1525                   : pExitReason->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessExecute ? "exec" : "!invalid access!",
     1574                  g_apszWHvMemAccesstypes[pExitReason->MemoryAccess.AccessInfo.AccessType],
    15261575                  pExitReason->MemoryAccess.AccessInfo.GpaUnmapped ? "unmapped" : "mapped",
    15271576                  pExitReason->MemoryAccess.AccessInfo.GvaValid    ? "" : "invalid-gc-virt"));
     
    17051754
    17061755/**
    1707  * @callback_method_impl{FNPGMPHYSNEMQUERYCHECKER}
     1756 * @callback_method_impl{FNPGMPHYSNEMQUERYCHECKER,
     1757 *      Worker for nemR3WinHandleMemoryAccess.
     1758 *      On input the boolean at pvUser indicates the desire to make the page
     1759 *      writable, whereas upon return it indicates whether we did anything to
     1760 *      the page mapping/protection. }
    17081761 */
    17091762static DECLCALLBACK(int) nemR3WinHandleMemoryAccessPageCheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys,
    17101763                                                                       PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)
    17111764{
    1712     uint8_t u2State = pInfo->u2NemState;
     1765    /* If A20 is disabled, we may need to make another query on the masked
     1766       page to get the correct protection information. */
     1767    uint8_t  u2State = pInfo->u2NemState;
     1768    RTGCPHYS GCPhysSrc;
     1769    if (   pVM->nem.s.fA20Enabled
     1770        || !NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
     1771        GCPhysSrc = GCPhys;
     1772    else
     1773    {
     1774        GCPhysSrc = GCPhys & ~(RTGCPHYS)RT_BIT_32(20);
     1775        bool const fMakeWritable = *(bool *)pvUser;
     1776        PGMPHYSNEMPAGEINFO Info2;
     1777        int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, GCPhysSrc, fMakeWritable, &Info2, NULL, NULL);
     1778        AssertRCReturn(rc, rc);
     1779
     1780        *pInfo = Info2;
     1781        pInfo->u2NemState = u2State;
     1782    }
     1783
     1784    bool   *pfDidSomething  = (bool *)pvUser;
    17131785    bool    fBackingChanged = true;
    17141786    switch (u2State)
     
    17161788        case NEM_WIN_PAGE_STATE_UNMAPPED:
    17171789        case NEM_WIN_PAGE_STATE_NOT_SET:
     1790        {
    17181791            if (pInfo->fNemProt == NEM_PAGE_PROT_NONE)
     1792            {
     1793                Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #1\n", GCPhys));
     1794                *pfDidSomething = false;
    17191795                return VINF_SUCCESS;
     1796            }
     1797
     1798#if 0
     1799            /* Remap it. */
     1800            *pfDidSomething = true;
     1801            int rc = nemR3NativeSetPhysPage(pVM, GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
     1802                                            GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pInfo->fNemProt, &u2State, fBackingChanged);
     1803            pInfo->u2NemState = u2State;
     1804            Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - synced => %s + %Rrc\n",
     1805                  GCPhys, g_apszPageStates[u2State], rc));
     1806            RT_NOREF(pVCpu);
     1807            return rc;
     1808#else
    17201809            break;
     1810#endif
     1811        }
    17211812        case NEM_WIN_PAGE_STATE_READABLE:
    17221813            if (pInfo->fNemProt != NEM_PAGE_PROT_NONE)
    17231814            {
    17241815                if (!(pInfo->fNemProt & NEM_PAGE_PROT_WRITE))
     1816                {
     1817                    Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #2\n", GCPhys));
     1818                    *pfDidSomething = false;
    17251819                    return VINF_SUCCESS;
     1820                }
    17261821                fBackingChanged = false;
    17271822            }
     
    17291824        case NEM_WIN_PAGE_STATE_WRITABLE:
    17301825            if (pInfo->fNemProt & NEM_PAGE_PROT_WRITE)
     1826            {
     1827                Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - #3\n", GCPhys));
     1828                *pfDidSomething = false;
    17311829                return VINF_SUCCESS;
     1830            }
    17321831            if (pInfo->fNemProt != NEM_PAGE_PROT_NONE)
    17331832                fBackingChanged = false;
     
    17351834    }
    17361835
    1737     int rc = nemR3NativeSetPhysPage(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pInfo->fNemProt, &u2State, fBackingChanged);
     1836#if 0
     1837    /* Unmap it first, then take another fault, remap it. */
     1838    HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
     1839    if (SUCCEEDED(hrc))
     1840    {
     1841        *pfDidSomething = true;
     1842        pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
     1843        Log5(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp => unmapped\n", GCPhys));
     1844        return VINF_SUCCESS;
     1845    }
     1846    LogRel(("nemR3WinHandleMemoryAccessPageCheckerCallback/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
     1847            GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     1848    return VERR_NEM_INIT_FAILED;
     1849
     1850#else
     1851    *pfDidSomething = true;
     1852    int rc = nemR3NativeSetPhysPage(pVM, GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
     1853                                    GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pInfo->fNemProt, &u2State, fBackingChanged);
    17381854    pInfo->u2NemState = u2State;
    1739     RT_NOREF(pVCpu, pvUser);
     1855    Log4(("nemR3WinHandleMemoryAccessPageCheckerCallback: %RGp - synced => %s + %Rrc\n",
     1856          GCPhys, g_apszPageStates[u2State], rc));
     1857    RT_NOREF(pVCpu);
    17401858    return rc;
     1859#endif
    17411860}
    17421861
     
    17591878     * out of sync first.
    17601879     */
     1880    bool               fMakeWritableThenDidSomething = pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite;
    17611881    PGMPHYSNEMPAGEINFO Info;
    1762     int rc = PGMPhysNemQueryPageInfo(pVM, pVCpu, pMemCtx->Gpa, &Info, nemR3WinHandleMemoryAccessPageCheckerCallback, NULL);
     1882    int rc = PGMPhysNemPageInfoChecker(pVM, pVCpu, pMemCtx->Gpa, fMakeWritableThenDidSomething, &Info,
     1883                                       nemR3WinHandleMemoryAccessPageCheckerCallback, &fMakeWritableThenDidSomething);
    17631884    if (RT_SUCCESS(rc))
    17641885    {
    1765         if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE :NEM_PAGE_PROT_READ))
    1766             return VINF_SUCCESS;
    1767     }
     1886        if (Info.fNemProt & (pMemCtx->AccessInfo.AccessType == WHvMemoryAccessWrite ? NEM_PAGE_PROT_WRITE : NEM_PAGE_PROT_READ))
     1887        {
     1888            ////if (fMakeWritableThenDidSomething)
     1889            //{
     1890            //    Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n",
     1891            //          pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
     1892            //          Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
     1893            //          fMakeWritableThenDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
     1894            //    return VINF_SUCCESS;
     1895            //}
     1896        }
     1897        Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n",
     1898              pMemCtx->Gpa, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
     1899              Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
     1900              fMakeWritableThenDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
     1901    }
     1902    else
     1903        Log4(("MemExit: %RGp rc=%Rrc%s; emulating (%s)\n", pMemCtx->Gpa, rc,
     1904              fMakeWritableThenDidSomething ? " modified-backing" : "", g_apszWHvMemAccesstypes[pMemCtx->AccessInfo.AccessType]));
    17681905
    17691906    /*
     
    19532090            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    19542091        {
     2092            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED);
    19552093            HRESULT hrc = WHvRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, &ExitReason, sizeof(ExitReason));
     2094            VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
    19562095            AssertLogRelMsgBreakStmt(SUCCEEDED(hrc),
    19572096                                     ("WHvRunVirtualProcessor(%p, %u,,) -> %Rhrc (Last=%#x/%u)\n", pVM->nem.s.hPartition, pVCpu->idCpu,
     
    21042243
    21052244
     2245/**
     2246 * Forced flag notification call from VMEmt.h.
     2247 *
     2248 * This is only called when pVCpu is in the VMCPUSTATE_STARTED_EXEC_NEM state.
     2249 *
     2250 * @param   pVM             The cross context VM structure.
     2251 * @param   pVCpu           The cross context virtual CPU structure of the CPU
     2252 *                          to be notified.
     2253 * @param   fFlags          Notification flags, VMNOTIFYFF_FLAGS_XXX.
     2254 */
     2255void nemR3NativeNotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags)
     2256{
     2257    HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0);
     2258    AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc));
     2259
     2260    RT_NOREF_PV(hrc);
     2261    RT_NOREF_PV(fFlags);
     2262}
     2263
     2264
    21062265DECLINLINE(int) nemR3NativeGCPhys2R3PtrReadOnly(PVM pVM, RTGCPHYS GCPhys, const void **ppv)
    21072266{
     
    22162375
    22172376
     2377/**
     2378 * @callback_method_impl{FNPGMPHYSNEMQUERYCHECKER}
     2379 */
     2380static DECLCALLBACK(int) nemR3WinUnsetForA20CheckerCallback(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys,
     2381                                                            PPGMPHYSNEMPAGEINFO pInfo, void *pvUser)
     2382{
     2383    Assert(pVCpu == NULL);
     2384
     2385    /* We'll just unmap the memory. */
     2386    if (pInfo->u2NemState > NEM_WIN_PAGE_STATE_UNMAPPED)
     2387    {
     2388        HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
     2389        if (SUCCEEDED(hrc))
     2390            pInfo->u2NemState = NEM_WIN_PAGE_STATE_UNMAPPED;
     2391        else
     2392        {
     2393            LogRel(("nemR3WinUnsetForA20CheckerCallback/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2394                    GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     2395            return VERR_INTERNAL_ERROR_2;
     2396        }
     2397    }
     2398    RT_NOREF(pVCpu, pvUser);
     2399    return VINF_SUCCESS;
     2400}
     2401
     2402
     2403/**
     2404 * Unmaps a page from Hyper-V for the purpose of emulating A20 gate behavior.
     2405 *
     2406 * @returns The PGMPhysNemQueryPageInfo result.
     2407 * @param   pVM             The cross context VM structure.
     2408 * @param   pVCpu           The cross context virtual CPU structure.  Optional.
     2409 * @param   GCPhys          The page to unmap.
     2410 */
     2411static int nemR3WinUnmapPageForA20Gate(PVM pVM, RTGCPHYS GCPhys)
     2412{
     2413    PGMPHYSNEMPAGEINFO Info;
     2414    return PGMPhysNemPageInfoChecker(pVM, NULL /*pVCpu*/, GCPhys, false /*fMakeWritable*/, &Info,
     2415                                     nemR3WinUnsetForA20CheckerCallback, NULL);
     2416}
     2417
     2418
     2419/**
     2420 * Called when the A20 state changes.
     2421 *
     2422 * Hyper-V doesn't seem to offer a simple way of implementing the A20 line
     2423 * features of PCs.  So, we do a very minimal emulation of the HMA to make DOS
     2424 * happy.
     2425 *
     2426 * @param   pVCpu           The CPU the A20 state changed on.
     2427 * @param   fEnabled        Whether it was enabled (true) or disabled.
     2428 */
    22182429void nemR3NativeNotifySetA20(PVMCPU pVCpu, bool fEnabled)
    22192430{
    2220     LogRel(("nemR3NativeNotifySetA20: fEnabled=%RTbool\n", fEnabled));
    2221     NOREF(pVCpu); NOREF(fEnabled);
     2431    Log(("nemR3NativeNotifySetA20: fEnabled=%RTbool\n", fEnabled));
     2432    PVM pVM = pVCpu->CTX_SUFF(pVM);
     2433    if (!pVM->nem.s.fA20Fixed)
     2434    {
     2435        pVM->nem.s.fA20Enabled = fEnabled;
     2436        for (RTGCPHYS GCPhys = _1M; GCPhys < _1M + _64K; GCPhys += X86_PAGE_SIZE)
     2437            nemR3WinUnmapPageForA20Gate(pVM, GCPhys);
     2438    }
    22222439}
    22232440
     
    22482465
    22492466
    2250 static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhys, uint32_t fPageProt, uint8_t *pu2State, bool fBackingChanged)
     2467/**
     2468 * Worker that maps pages into Hyper-V.
     2469 *
     2470 * This is used by the PGM physical page notifications as well as the memory
     2471 * access VMEXIT handlers.
     2472 *
     2473 * @returns VBox status code.
     2474 * @param   pVM             The cross context VM structure.
     2475 * @param   GCPhysSrc       The source page address.
     2476 * @param   GCPhysDst       The hyper-V destination page.  This may differ from
     2477 *                          GCPhysSrc when A20 is disabled.
     2478 * @param   fPageProt       NEM_PAGE_PROT_XXX.
     2479 * @param   pu2State        Our page state (input/output).
     2480 * @param   fBackingChanged Set if the page backing is being changed.
     2481 */
     2482static int nemR3NativeSetPhysPage(PVM pVM, RTGCPHYS GCPhysSrc, RTGCPHYS GCPhysDst, uint32_t fPageProt,
     2483                                  uint8_t *pu2State, bool fBackingChanged)
    22512484{
    22522485    /*
     
    22572490    uint8_t const u2OldState = *pu2State;
    22582491    uint8_t const u2NewState = fPageProt & NEM_PAGE_PROT_WRITE ? NEM_WIN_PAGE_STATE_WRITABLE
    2259                              : fPageProt & NEM_PAGE_PROT_READ  ? NEM_WIN_PAGE_STATE_READABLE : NEM_WIN_PAGE_STATE_NOT_SET;
     2492                             : fPageProt & NEM_PAGE_PROT_READ  ? NEM_WIN_PAGE_STATE_READABLE : NEM_WIN_PAGE_STATE_UNMAPPED;
    22602493    if (   fBackingChanged
    22612494        || u2NewState != u2OldState)
    22622495    {
    2263         if (u2OldState > NEM_WIN_PAGE_STATE_NOT_SET)
    2264         {
    2265             HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhys, X86_PAGE_SIZE);
     2496        if (u2OldState > NEM_WIN_PAGE_STATE_UNMAPPED)
     2497        {
     2498            HRESULT hrc = WHvUnmapGpaRange(pVM->nem.s.hPartition, GCPhysDst, X86_PAGE_SIZE);
    22662499            if (SUCCEEDED(hrc))
    22672500            {
    2268                 *pu2State = NEM_WIN_PAGE_STATE_NOT_SET;
    2269                 if (u2NewState == NEM_WIN_PAGE_STATE_NOT_SET)
     2501                *pu2State = NEM_WIN_PAGE_STATE_UNMAPPED;
     2502                if (u2NewState == NEM_WIN_PAGE_STATE_UNMAPPED)
     2503                {
     2504                    Log5(("nemR3NativeSetPhysPage: %RGp => unmapped\n", GCPhysDst));
    22702505                    return VINF_SUCCESS;
     2506                }
    22712507            }
    22722508            else
    22732509            {
    2274                 LogRel(("nemR3NativeSetPhysPage/unmap: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2275                         GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     2510                LogRel(("nemR3NativeSetPhysPage/unmap: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2511                        GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
    22762512                return VERR_NEM_INIT_FAILED;
    22772513            }
     
    22852521    {
    22862522        void *pvPage;
    2287         int rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhys, &pvPage);
     2523        int rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhysSrc, &pvPage);
    22882524        if (RT_SUCCESS(rc))
    22892525        {
    2290             HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPage, GCPhys, X86_PAGE_SIZE,
     2526            HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, pvPage, GCPhysDst, X86_PAGE_SIZE,
    22912527                                         WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute | WHvMapGpaRangeFlagWrite);
    22922528            if (SUCCEEDED(hrc))
    22932529            {
     2530                Log5(("nemR3NativeSetPhysPage: %RGp => writable\n", GCPhysDst));
    22942531                *pu2State = NEM_WIN_PAGE_STATE_WRITABLE;
    22952532                return VINF_SUCCESS;
    22962533            }
    2297             LogRel(("nemR3NativeSetPhysPage/writable: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2298                     GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     2534            LogRel(("nemR3NativeSetPhysPage/writable: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2535                    GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
    22992536            return VERR_NEM_INIT_FAILED;
    23002537        }
    2301         LogRel(("nemR3NativeSetPhysPage/writable: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));
     2538        LogRel(("nemR3NativeSetPhysPage/writable: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    23022539        return rc;
    23032540    }
     
    23062543    {
    23072544        const void *pvPage;
    2308         int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhys, &pvPage);
     2545        int rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhysSrc, &pvPage);
    23092546        if (RT_SUCCESS(rc))
    23102547        {
    2311             HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhys, X86_PAGE_SIZE,
     2548            HRESULT hrc = WHvMapGpaRange(pVM->nem.s.hPartition, (void *)pvPage, GCPhysDst, X86_PAGE_SIZE,
    23122549                                         WHvMapGpaRangeFlagRead | WHvMapGpaRangeFlagExecute);
    23132550            if (SUCCEEDED(hrc))
    23142551            {
    23152552                *pu2State = NEM_WIN_PAGE_STATE_READABLE;
     2553                Log5(("nemR3NativeSetPhysPage: %RGp => read+exec\n", GCPhysDst));
    23162554                return VINF_SUCCESS;
    23172555            }
    2318             LogRel(("nemR3NativeSetPhysPage/readonly: GCPhys=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
    2319                     GCPhys, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
     2556            LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysDst=%RGp hrc=%Rhrc (%#x) Last=%#x/%u\n",
     2557                    GCPhysDst, hrc, hrc, RTNtCurrentTeb()->LastStatusValue, RTNtCurrentTeb()->LastErrorValue));
    23202558            return VERR_NEM_INIT_FAILED;
    23212559        }
    2322         LogRel(("nemR3NativeSetPhysPage/readonly: GCPhys=%RGp rc=%Rrc\n", GCPhys, rc));
     2560        LogRel(("nemR3NativeSetPhysPage/readonly: GCPhysSrc=%RGp rc=%Rrc\n", GCPhysSrc, rc));
    23232561        return rc;
    23242562    }
     
    23372575    RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType);
    23382576
    2339     return nemR3NativeSetPhysPage(pVM, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     2577    int rc;
     2578    if (   pVM->nem.s.fA20Enabled
     2579        || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
     2580        rc = nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     2581    else
     2582    {
     2583        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
     2584        rc = nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2585        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys) && RT_SUCCESS(rc))
     2586            rc = nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     2587
     2588    }
     2589    return rc;
    23402590}
    23412591
     
    23482598    RT_NOREF_PV(HCPhys); RT_NOREF_PV(enmType);
    23492599
    2350     nemR3NativeSetPhysPage(pVM, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
     2600    if (   pVM->nem.s.fA20Enabled
     2601        || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
     2602        nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
     2603    else
     2604    {
     2605        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
     2606        nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2607        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
     2608            nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, false /*fBackingChanged*/);
     2609    }
    23512610}
    23522611
     
    23592618    RT_NOREF_PV(HCPhysPrev); RT_NOREF_PV(HCPhysNew); RT_NOREF_PV(enmType);
    23602619
    2361     nemR3NativeSetPhysPage(pVM, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
    2362 }
    2363 
     2620    if (   pVM->nem.s.fA20Enabled
     2621        || !NEM_WIN_IS_RELEVANT_TO_A20(GCPhys))
     2622        nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     2623    else
     2624    {
     2625        /* To keep effort at a minimum, we unmap the HMA page alias and resync it lazily when needed. */
     2626        nemR3WinUnmapPageForA20Gate(pVM, GCPhys | RT_BIT_32(20));
     2627        if (!NEM_WIN_IS_SUBJECT_TO_A20(GCPhys))
     2628            nemR3NativeSetPhysPage(pVM, GCPhys, GCPhys, fPageProt, pu2State, true /*fBackingChanged*/);
     2629    }
     2630}
     2631
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