VirtualBox

Changeset 71222 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Mar 5, 2018 10:07:48 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
121132
Message:

NEM/win,VMM,PGM: Ported NEM runloop to ring-0. bugref:9044

File:
1 edited

Legend:

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

    r71184 r71222  
    4040NEM_TMPL_STATIC const char * const g_apszPageStates[4] = { "not-set", "unmapped", "readable", "writable" };
    4141
     42/** HV_INTERCEPT_ACCESS_TYPE names. */
     43static const char * const g_apszHvInterceptAccessTypes[4] = { "read", "write", "exec", "!undefined!" };
     44
    4245
    4346/*********************************************************************************************************************************
     
    6770    PGVM pGVM = GVMMR0FastGetGVMByVM(pVM);
    6871    AssertReturn(pGVM, VERR_INVALID_VM_HANDLE);
    69     return nemR0WinMapPages(pGVM, pVM, &pGVM->aCpus[pVCpu->idCpu], GCPhysSrc, GCPhysDst, 1, fFlags);
     72    return nemR0WinMapPages(pGVM, pVM, &pGVM->aCpus[pVCpu->idCpu],
     73                            GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
     74                            GCPhysDst & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK,
     75                            1, fFlags);
    7076#else
    7177    pVCpu->nem.s.Hypercall.MapPages.GCPhysSrc   = GCPhysSrc & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
     
    9197    PGVM pGVM = GVMMR0FastGetGVMByVM(pVM);
    9298    AssertReturn(pGVM, VERR_INVALID_VM_HANDLE);
    93     return nemR0WinUnmapPages(pGVM, &pGVM->aCpus[pVCpu->idCpu], GCPhys, 1);
     99    return nemR0WinUnmapPages(pGVM, &pGVM->aCpus[pVCpu->idCpu], GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, 1);
    94100# else
    95101    pVCpu->nem.s.Hypercall.UnmapPages.GCPhys    = GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK;
     
    100106
    101107#endif /* NEM_WIN_USE_HYPERCALLS_FOR_PAGES */
    102 
    103 
    104108#ifndef IN_RING0
    105109
    106110NEM_TMPL_STATIC int nemHCWinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    107111{
    108 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
     112# ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    109113    NOREF(pCtx);
    110114    int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, 0, NULL);
     
    112116    return rc;
    113117
    114 #else
     118# else
    115119    WHV_REGISTER_NAME  aenmNames[128];
    116120    WHV_REGISTER_VALUE aValues[128];
     
    157161
    158162    /* Segments */
    159 #define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
     163#  define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
    160164        do { \
    161165            aenmNames[a_idx]                  = a_enmName; \
     
    391395    Assert(iReg < RT_ELEMENTS(aValues));
    392396    Assert(iReg < RT_ELEMENTS(aenmNames));
    393 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
     397#  ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    394398    Log12(("Calling WHvSetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    395399           pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues));
    396 #endif
     400#  endif
    397401    HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, iReg, aValues);
    398402    if (SUCCEEDED(hrc))
     
    402406                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    403407    return VERR_INTERNAL_ERROR;
    404 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     408# endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    405409}
    406410
     
    408412NEM_TMPL_STATIC int nemHCWinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, uint64_t fWhat)
    409413{
    410 #ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
     414# ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    411415    /* See NEMR0ImportState */
    412416    NOREF(pCtx);
     
    421425    return rc;
    422426
    423 #else
     427# else
    424428    WHV_REGISTER_NAME  aenmNames[128];
    425429
     
    534538    Assert(RT_ELEMENTS(aValues) >= cRegs);
    535539    Assert(RT_ELEMENTS(aenmNames) >= cRegs);
    536 #ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
     540#  ifdef NEM_WIN_INTERCEPT_NT_IO_CTLS
    537541    Log12(("Calling WHvGetVirtualProcessorRegisters(%p, %u, %p, %u, %p)\n",
    538542          pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues));
    539 #endif
     543#  endif
    540544    HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, cRegs, aValues);
    541545    if (SUCCEEDED(hrc))
     
    567571
    568572        /* Segments */
    569 #define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
     573#  define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
    570574            do { \
    571575                Assert(aenmNames[a_idx] == a_enmName); \
     
    774778                           hrc, RTNtLastStatusValue(), RTNtLastErrorValue()));
    775779    return VERR_INTERNAL_ERROR;
    776 #endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    777 }
     780# endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
     781}
     782
     783#endif /* !IN_RING0 */
    778784
    779785
     
    11721178}
    11731179
    1174 #ifdef IN_RING3
     1180#ifdef IN_RING0
     1181/**
     1182 * Wrapper around nemR0WinImportState that converts VERR_NEM_CHANGE_PGM_MODE and
     1183 * VERR_NEM_FLUSH_TBL into informational status codes and logs+asserts statuses.
     1184 *
     1185 * @returns VBox strict status code.
     1186 * @param   pGVM            The global (ring-0) VM structure.
     1187 * @param   pGVCpu          The global (ring-0) per CPU structure.
     1188 * @param   pCtx            The CPU context to import into.
     1189 * @param   fWhat           What to import.
     1190 * @param   pszCaller       Whoe is doing the importing.
     1191 */
     1192DECLINLINE(VBOXSTRICTRC) nemR0WinImportStateStrict(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat, const char *pszCaller)
     1193{
     1194    int rc = nemR0WinImportState(pGVM, pGVCpu, pCtx, fWhat);
     1195    if (RT_SUCCESS(rc))
     1196    {
     1197        Assert(rc == VINF_SUCCESS);
     1198        return VINF_SUCCESS;
     1199    }
     1200
     1201    if (rc == VERR_NEM_CHANGE_PGM_MODE || rc == VERR_NEM_FLUSH_TLB)
     1202    {
     1203        Log4(("%s/%u: nemR0WinImportState -> %Rrc\n", pszCaller, pGVCpu->idCpu, -rc));
     1204        return -rc;
     1205    }
     1206    AssertMsgFailedReturn(("%s/%u: nemR0WinImportState failed: %Rrc\n", pszCaller, pGVCpu->idCpu, rc), rc);
     1207}
     1208#endif /* IN_RING0 */
    11751209
    11761210/**
     
    12011235 * @param   pMsg            The message.
    12021236 * @param   pCtx            The register context.
     1237 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
    12031238 */
    12041239NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageMemory(PVM pVM, PVMCPU pVCpu, HV_X64_MEMORY_INTERCEPT_MESSAGE const *pMsg,
    1205                                                          PCPUMCTX pCtx)
    1206 {
     1240                                                         PCPUMCTX pCtx, PGVMCPU pGVCpu)
     1241{
     1242    Assert(   pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ
     1243           || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     1244           || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_EXECUTE);
     1245
    12071246    /*
    12081247     * Whatever we do, we must clear pending event ejection upon resume.
     
    12261265            if (State.fCanResume)
    12271266            {
    1228                 Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n",
     1267                Log4(("MemExit/%u: %04x:%08RX64: %RGp (=>%RHp) %s fProt=%u%s%s%s; restarting (%s)\n",
     1268                      pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
    12291269                      pMsg->GuestPhysicalAddress, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
    12301270                      Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
    1231                       State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMsg->Header.InterceptAccessType]));
     1271                      State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType]));
    12321272                return VINF_SUCCESS;
    12331273            }
    12341274        }
    1235         Log4(("MemExit: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n",
     1275        Log4(("MemExit/%u: %04x:%08RX64: %RGp (=>%RHp) %s fProt=%u%s%s%s; emulating (%s)\n",
     1276              pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
    12361277              pMsg->GuestPhysicalAddress, Info.HCPhys, g_apszPageStates[Info.u2NemState], Info.fNemProt,
    12371278              Info.fHasHandlers ? " handlers" : "", Info.fZeroPage    ? " zero-pg" : "",
    1238               State.fDidSomething ? "" : " no-change", g_apszWHvMemAccesstypes[pMsg->Header.InterceptAccessType]));
     1279              State.fDidSomething ? "" : " no-change", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType]));
    12391280    }
    12401281    else
    1241         Log4(("MemExit: %RGp rc=%Rrc%s; emulating (%s)\n", pMsg->GuestPhysicalAddress, rc,
    1242               State.fDidSomething ? " modified-backing" : "", g_apszWHvMemAccesstypes[pMsg->Header.InterceptAccessType]));
     1282        Log4(("MemExit/%u: %04x:%08RX64: %RGp rc=%Rrc%s; emulating (%s)\n",
     1283              pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, pMsg->GuestPhysicalAddress, rc,
     1284              State.fDidSomething ? " modified-backing" : "", g_apszHvInterceptAccessTypes[pMsg->Header.InterceptAccessType]));
    12431285
    12441286    /*
     
    12461288     */
    12471289    nemHCWinCopyStateFromX64Header(pCtx, &pMsg->Header);
     1290    VBOXSTRICTRC rcStrict;
     1291#ifdef IN_RING0
     1292    rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "MemExit");
     1293    if (rcStrict != VINF_SUCCESS)
     1294        return rcStrict;
     1295#else
    12481296    rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
    12491297    AssertRCReturn(rc, rc);
    1250 
    1251     VBOXSTRICTRC rcStrict;
     1298    NOREF(pGVCpu);
     1299#endif
     1300
    12521301    if (pMsg->InstructionByteCount > 0)
    12531302        rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(pCtx), pMsg->Header.Rip,
     
    12681317 * @param   pVCpu           The cross context per CPU structure.
    12691318 * @param   pMsg            The message.
     1319 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
    12701320 */
    12711321NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageIoPort(PVM pVM, PVMCPU pVCpu, HV_X64_IO_PORT_INTERCEPT_MESSAGE const *pMsg,
    1272                                                          PCPUMCTX pCtx)
     1322                                                         PCPUMCTX pCtx, PGVMCPU pGVCpu)
    12731323{
    12741324    Assert(   pMsg->AccessInfo.AccessSize == 1
    12751325           || pMsg->AccessInfo.AccessSize == 2
    12761326           || pMsg->AccessInfo.AccessSize == 4);
     1327    Assert(   pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_READ
     1328           || pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE);
    12771329
    12781330    /*
     
    12941346        {
    12951347            rcStrict = IOMIOPortWrite(pVM, pVCpu, pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize);
    1296             Log4(("IOExit: %04x:%08RX64: OUT %#x, %#x LB %u rcStrict=%Rrc\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
    1297                   pMsg->PortNumber, (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) ));
     1348            Log4(("IOExit/%u: %04x:%08RX64: OUT %#x, %#x LB %u rcStrict=%Rrc\n",
     1349                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, pMsg->PortNumber,
     1350                  (uint32_t)pMsg->Rax & fAndMask, pMsg->AccessInfo.AccessSize, VBOXSTRICTRC_VAL(rcStrict) ));
    12981351            if (IOM_SUCCESS(rcStrict))
    12991352            {
     
    13061359            uint32_t uValue = 0;
    13071360            rcStrict = IOMIOPortRead(pVM, pVCpu, pMsg->PortNumber, &uValue, pMsg->AccessInfo.AccessSize);
    1308             Log4(("IOExit: %04x:%08RX64: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
    1309                   pMsg->PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
     1361            Log4(("IOExit/%u: %04x:%08RX64: IN %#x LB %u -> %#x, rcStrict=%Rrc\n", pVCpu->idCpu, pMsg->Header.CsSegment.Selector,
     1362                  pMsg->Header.Rip, pMsg->PortNumber, pMsg->AccessInfo.AccessSize, uValue, VBOXSTRICTRC_VAL(rcStrict) ));
    13101363            if (IOM_SUCCESS(rcStrict))
    13111364            {
     
    13151368                    pCtx->rax = uValue;
    13161369                pCtx->fExtrn &= ~CPUMCTX_EXTRN_RAX;
    1317                 Log4(("IOExit: RAX %#RX64 -> %#RX64\n", pMsg->Rax, pCtx->rax));
     1370                Log4(("IOExit/%u: RAX %#RX64 -> %#RX64\n", pVCpu->idCpu, pMsg->Rax, pCtx->rax));
    13181371                nemHCWinCopyStateFromX64Header(pCtx, &pMsg->Header);
    13191372                nemHCWinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pMsg->Header);
     
    13461399        pCtx->rdi = pMsg->Rdi;
    13471400        pCtx->rsi = pMsg->Rsi;
     1401#ifdef IN_RING0
     1402        rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit");
     1403        if (rcStrict != VINF_SUCCESS)
     1404            return rcStrict;
     1405#else
    13481406        int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM);
    13491407        AssertRCReturn(rc, rc);
    1350 
    1351         Log4(("IOExit: %04x:%08RX64: %s%s %#x LB %u (emulating)\n", pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
     1408        RT_NOREF(pGVCpu);
     1409#endif
     1410
     1411        Log4(("IOExit/%u: %04x:%08RX64: %s%s %#x LB %u (emulating)\n",
     1412              pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
    13521413              pMsg->AccessInfo.RepPrefix ? "REP " : "",
    13531414              pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE ? "OUTS" : "INS",
     
    13791440 * @param   pMappingHeader  The message slot mapping.
    13801441 * @param   pCtx            The register context.
     1442 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
    13811443 */
    13821444NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessage(PVM pVM, PVMCPU pVCpu, VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader,
    1383                                                    PCPUMCTX pCtx)
     1445                                                   PCPUMCTX pCtx, PGVMCPU pGVCpu)
    13841446{
    13851447    if (pMappingHeader->enmVidMsgType == VidMessageHypervisorMessage)
     
    13911453            case HvMessageTypeUnmappedGpa:
    13921454                Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment));
    1393                 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx);
     1455                return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu);
    13941456
    13951457            case HvMessageTypeGpaIntercept:
    13961458                Assert(pMsg->Header.PayloadSize == RT_UOFFSETOF(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment));
    1397                 return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx);
     1459                return nemHCWinHandleMessageMemory(pVM, pVCpu, &pMsg->X64MemoryIntercept, pCtx, pGVCpu);
    13981460
    13991461            case HvMessageTypeX64IoPortIntercept:
    14001462                Assert(pMsg->Header.PayloadSize == sizeof(pMsg->X64IoPortIntercept));
    1401                 return nemHCWinHandleMessageIoPort(pVM, pVCpu, &pMsg->X64IoPortIntercept, pCtx);
     1463                return nemHCWinHandleMessageIoPort(pVM, pVCpu, &pMsg->X64IoPortIntercept, pCtx, pGVCpu);
    14021464
    14031465            case HvMessageTypeX64Halt:
     
    14541516 *                          exit.
    14551517 * @param   pMappingHeader  The message slot mapping.
     1518 * @param   pGVM            The global (ring-0) VM structure (NULL in r3).
     1519 * @param   pGVCpu          The global (ring-0) per CPU structure (NULL in r3).
    14561520 */
    14571521NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinStopCpu(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rcStrict,
    1458                                              VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader)
     1522                                             VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader,
     1523                                             PGVM pGVM, PGVMCPU pGVCpu)
    14591524{
    14601525    /*
     
    14621527     * does another VM exit.
    14631528     */
     1529#ifdef IN_RING0
     1530    pVCpu->nem.s.uIoCtlBuf.idCpu = pGVCpu->idCpu;
     1531    NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlStopVirtualProcessor.uFunction,
     1532                                            &pVCpu->nem.s.uIoCtlBuf.idCpu, sizeof(pVCpu->nem.s.uIoCtlBuf.idCpu),
     1533                                            NULL, 0);
     1534    if (NT_SUCCESS(rcNt))
     1535    {
     1536        Log8(("nemHCWinStopCpu: Stopping CPU succeeded (cpu status %u)\n", nemHCWinCpuGetRunningStatus(pVCpu) ));
     1537        return rcStrict;
     1538    }
     1539#else
    14641540    BOOL fRet = VidStopVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu);
    14651541    if (fRet)
     
    14681544        return rcStrict;
    14691545    }
     1546    RT_NOREF(pGVM, pGVCpu);
     1547#endif
    14701548
    14711549    /*
    14721550     * Dang. The CPU stopped by itself and we got a couple of message to deal with.
    14731551     */
     1552#ifdef IN_RING0
     1553    AssertLogRelMsgReturn(rcNt == ERROR_VID_STOP_PENDING, ("rcNt=%#x\n", rcNt),
     1554                          RT_SUCCESS(rcStrict) ?  VERR_INTERNAL_ERROR_3 : rcStrict);
     1555#else
    14741556    DWORD dwErr = RTNtLastErrorValue();
    1475     AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u\n", dwErr),
     1557    AssertLogRelMsgReturn(dwErr == ERROR_VID_STOP_PENDING, ("dwErr=%#u (%#x)\n", dwErr, dwErr),
    14761558                          RT_SUCCESS(rcStrict) ?  VERR_INTERNAL_ERROR_3 : rcStrict);
     1559#endif
    14771560    Log8(("nemHCWinStopCpu: Stopping CPU pending...\n"));
    14781561
     
    14811564     * Note! We can safely ASSUME that rcStrict isn't an important information one.
    14821565     */
     1566#ifdef IN_RING0
     1567    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
     1568    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags   = VID_MSHAGN_F_GET_NEXT_MESSAGE;
     1569    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/
     1570    rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction,
     1571                                   &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,
     1572                                   sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext),
     1573                                   NULL, 0);
     1574    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
     1575                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1576#else
    14831577    BOOL fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    14841578                                                     VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/);
    1485     AssertLogRelMsgReturn(fWait,
    1486                           ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
     1579    AssertLogRelMsgReturn(fWait, ("1st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
    14871580                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1581#endif
    14881582
    14891583    /* It should be a hypervisor message and definitely not a stop request completed message. */
     
    14941588                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
    14951589
    1496     VBOXSTRICTRC rcStrict2 = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, CPUMQueryGuestCtxPtr(pVCpu));
     1590    VBOXSTRICTRC rcStrict2 = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, CPUMQueryGuestCtxPtr(pVCpu), pGVCpu);
    14971591    if (rcStrict2 != VINF_SUCCESS && RT_SUCCESS(rcStrict))
    14981592        rcStrict = rcStrict2;
     
    15021596     * that as handled too.  CPU is back into fully stopped stated then.
    15031597     */
     1598#ifdef IN_RING0
     1599    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
     1600    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags   = VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE;
     1601    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/
     1602    rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction,
     1603                                   &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,
     1604                                   sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext),
     1605                                   NULL, 0);
     1606    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("2st VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
     1607                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1608#else
    15041609    fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    15051610                                                VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE, 30000 /*ms*/);
    1506     AssertLogRelMsgReturn(fWait,
    1507                           ("2nd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
     1611    AssertLogRelMsgReturn(fWait, ("2nd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
    15081612                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1613#endif
    15091614
    15101615    /* It should be a stop request completed message. */
     
    15161621
    15171622    /* Mark this as handled. */
    1518     fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    1519                                                 VID_MSHAGN_F_HANDLE_MESSAGE, 30000 /*ms*/);
    1520     AssertLogRelMsgReturn(fWait,
    1521                           ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
     1623#ifdef IN_RING0
     1624    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
     1625    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags   = VID_MSHAGN_F_HANDLE_MESSAGE;
     1626    pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = 30000; /*ms*/
     1627    rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction,
     1628                                   &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,
     1629                                   sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext),
     1630                                   NULL, 0);
     1631    AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %#x\n", rcNt),
    15221632                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1633#else
     1634    fWait = g_pfnVidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu, VID_MSHAGN_F_HANDLE_MESSAGE, 30000 /*ms*/);
     1635    AssertLogRelMsgReturn(fWait, ("3rd VidMessageSlotHandleAndGetNext after ERROR_VID_STOP_PENDING failed: %u\n", RTNtLastErrorValue()),
     1636                          RT_SUCCESS(rcStrict) ? VERR_INTERNAL_ERROR_3 : rcStrict);
     1637#endif
    15231638    Log8(("nemHCWinStopCpu: Stopped the CPU (rcStrict=%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict) ));
    15241639    return rcStrict;
     
    15261641
    15271642
    1528 NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu)
     1643NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinRunGC(PVM pVM, PVMCPU pVCpu, PGVM pGVM, PGVMCPU pGVCpu)
    15291644{
    15301645    PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
    1531     LogFlow(("nemHCWinRunGC: Entering #%u cs:rip=%04x:%08RX64 efl=%#08RX64\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags));
     1646    LogFlow(("NEM/%u: %04x:%08RX64 efl=%#08RX64 <=\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags));
    15321647#ifdef LOG_ENABLED
    15331648    if (LogIs3Enabled())
     
    15521667        if ((pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK)) != (CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK))
    15531668        {
     1669#ifdef IN_RING0
     1670            int rc2 = nemR0WinExportState(pGVM, pGVCpu, pCtx);
     1671#else
    15541672            int rc2 = nemHCWinCopyStateToHyperV(pVM, pVCpu, pCtx);
     1673            RT_NOREF(pGVM, pGVCpu);
     1674#endif
    15551675            AssertRCReturn(rc2, rc2);
    15561676        }
     
    15661686            else
    15671687            {
    1568                 if (g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu))
    1569                     pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    1570                 else
    1571                     AssertLogRelMsgFailedReturn(("VidStartVirtualProcessor failed for CPU #%u: %u (%#x, rcNt=%#x)\n",
    1572                                                  pVCpu->idCpu, RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()),
    1573                                                 VERR_INTERNAL_ERROR_3);
     1688#ifdef IN_RING0
     1689                pVCpu->nem.s.uIoCtlBuf.idCpu = pGVCpu->idCpu;
     1690                NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlStartVirtualProcessor.uFunction,
     1691                                                        &pVCpu->nem.s.uIoCtlBuf.idCpu, sizeof(pVCpu->nem.s.uIoCtlBuf.idCpu),
     1692                                                        NULL, 0);
     1693                LogFlow(("NEM/%u: IoCtlStartVirtualProcessor -> %#x\n", pVCpu->idCpu, rcNt));
     1694                AssertLogRelMsgReturn(NT_SUCCESS(rcNt), ("VidStartVirtualProcessor failed for CPU #%u: %#x\n", pGVCpu->idCpu, rcNt),
     1695                                      VERR_INTERNAL_ERROR_3);
     1696#else
     1697                AssertLogRelMsgReturn(g_pfnVidStartVirtualProcessor(pVM->nem.s.hPartitionDevice, pVCpu->idCpu),
     1698                                      ("VidStartVirtualProcessor failed for CPU #%u: %u (%#x, rcNt=%#x)\n",
     1699                                       pVCpu->idCpu, RTNtLastErrorValue(), RTNtLastErrorValue(), RTNtLastStatusValue()),
     1700                                      VERR_INTERNAL_ERROR_3);
     1701#endif
     1702                pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    15741703            }
    15751704
    1576             if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM, VMCPUSTATE_STARTED))
     1705            if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED))
    15771706            {
     1707#ifdef IN_RING0
     1708                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
     1709                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.fFlags   = pVCpu->nem.s.fHandleAndGetFlags;
     1710                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.cMillies = cMillies;
     1711                NTSTATUS rcNt = nemR0NtPerformIoControl(pGVM, pGVM->nem.s.IoCtlMessageSlotHandleAndGetNext.uFunction,
     1712                                                        &pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext,
     1713                                                        sizeof(pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext),
     1714                                                        NULL, 0);
     1715                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
     1716                if (rcNt == STATUS_SUCCESS)
     1717#else
    15781718                BOOL fRet = VidMessageSlotHandleAndGetNext(pVM->nem.s.hPartitionDevice, pVCpu->idCpu,
    15791719                                                           pVCpu->nem.s.fHandleAndGetFlags, cMillies);
    1580                 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM);
     1720                VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_NEM_WAIT);
    15811721                if (fRet)
     1722#endif
    15821723                {
    15831724                    /*
    15841725                     * Deal with the message.
    15851726                     */
    1586                     rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pCtx);
     1727                    rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pCtx, pGVCpu);
    15871728                    pVCpu->nem.s.fHandleAndGetFlags |= VID_MSHAGN_F_HANDLE_MESSAGE;
     1729                    if (rcStrict == VINF_SUCCESS)
     1730                    { /* hopefully likely */ }
     1731                    else
     1732                    {
     1733                        LogFlow(("NEM/%u: breaking: nemHCWinHandleMessage -> %Rrc\n", pVCpu->idCpu, VBOXSTRICTRC_VAL(rcStrict) ));
     1734                        break;
     1735                    }
    15881736                }
    15891737                else
     
    15921740                       so after NtAlertThread we end up here with a STATUS_TIMEOUT.  And yeah,
    15931741                       the error code conversion is into WAIT_XXX, i.e. NT status codes. */
    1594                     DWORD dwErr = GetLastError();
    1595                     if (   dwErr == STATUS_TIMEOUT
    1596                         || dwErr == STATUS_ALERTED  /* just in case */
    1597                         || dwErr == STATUS_USER_APC /* ditto */ )
    1598                         pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; /* exits are likely */
    1599                     else
    1600                         AssertLogRelMsgFailedReturn(("VidMessageSlotHandleAndGetNext failed for CPU #%u: %u (%#x, rcNt=%#x)\n",
    1601                                                      pVCpu->idCpu, dwErr, dwErr, RTNtLastStatusValue()),
    1602                                                     VERR_INTERNAL_ERROR_3);
     1742#ifndef IN_RING0
     1743                    DWORD rcNt = GetLastError();
     1744#endif
     1745                    LogFlow(("NEM/%u: VidMessageSlotHandleAndGetNext -> %#x\n", pVCpu->idCpu, rcNt));
     1746                    AssertLogRelMsgReturn(   rcNt == STATUS_TIMEOUT
     1747                                          || rcNt == STATUS_ALERTED  /* just in case */
     1748                                          || rcNt == STATUS_USER_APC /* ditto */
     1749                                          , ("VidMessageSlotHandleAndGetNext failed for CPU #%u: %#x (%u)\n", pVCpu->idCpu, rcNt, rcNt),
     1750                                          VERR_INTERNAL_ERROR_3);
     1751                    pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE; /* exits are likely */
    16031752                }
    16041753
     
    16121761                /** @todo Try handle pending flags, not just return to EM loops.  Take care
    16131762                 *        not to set important RCs here unless we've handled a message. */
    1614                 LogFlow(("nemHCWinRunGC: returning: pending FF (%#x / %#x)\n", pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions));
     1763                LogFlow(("NEM/%u: breaking: pending FF (%#x / %#x)\n",
     1764                         pVCpu->idCpu, pVM->fGlobalForcedActions, pVCpu->fLocalForcedActions));
    16151765            }
    16161766            else
    1617                 LogFlow(("nemHCWinRunGC: returning: canceled %d (pre exec)\n", VMCPU_GET_STATE(pVCpu) ));
     1767                LogFlow(("NEM/%u: breaking: canceled %d (pre exec)\n", pVCpu->idCpu, VMCPU_GET_STATE(pVCpu) ));
    16181768        }
    16191769        else
    1620             LogFlow(("nemHCWinRunGC: returning: pending FF (pre exec)\n"));
     1770            LogFlow(("NEM/%u: breaking: pending FF (pre exec)\n", pVCpu->idCpu));
    16211771        break;
    16221772    } /* the run loop */
     
    16301780    {
    16311781        pVCpu->nem.s.fHandleAndGetFlags = 0;
    1632         rcStrict = nemHCWinStopCpu(pVM, pVCpu, rcStrict, pMappingHeader);
     1782        rcStrict = nemHCWinStopCpu(pVM, pVCpu, rcStrict, pMappingHeader, pGVM, pGVCpu);
    16331783    }
    16341784
     
    16371787    if (pCtx->fExtrn & (CPUMCTX_EXTRN_ALL | (CPUMCTX_EXTRN_NEM_WIN_MASK & ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT)))
    16381788    {
     1789#ifdef IN_RING0
     1790        int rc2 = nemR0WinImportState(pGVM, pGVCpu, pCtx, CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK);
     1791        if (RT_SUCCESS(rc2))
     1792            pCtx->fExtrn = 0;
     1793        else if (rc2 == VERR_NEM_CHANGE_PGM_MODE || rc2 == VERR_NEM_FLUSH_TLB)
     1794        {
     1795            pCtx->fExtrn = 0;
     1796            if (rcStrict == VINF_SUCCESS || rcStrict == -rc2)
     1797                rcStrict = -rc2;
     1798            else
     1799            {
     1800                pVCpu->nem.s.rcPgmPending = -rc2;
     1801                LogFlow(("NEM/%u: rcPgmPending=%Rrc (rcStrict=%Rrc)\n", pVCpu->idCpu, rc2, VBOXSTRICTRC_VAL(rcStrict) ));
     1802            }
     1803        }
     1804#else
    16391805        int rc2 = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_NEM_WIN_MASK);
    16401806        if (RT_SUCCESS(rc2))
    16411807            pCtx->fExtrn = 0;
     1808#endif
    16421809        else if (RT_SUCCESS(rcStrict))
    16431810            rcStrict = rc2;
     
    16461813        pCtx->fExtrn = 0;
    16471814
    1648     LogFlow(("nemHCWinRunGC: Leaving #%u cs:rip=%04x:%08RX64 efl=%#08RX64\n", pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags));
     1815    LogFlow(("NEM/%u: %04x:%08RX64 efl=%#08RX64 => %Rrc\n",
     1816             pVCpu->idCpu, pCtx->cs.Sel, pCtx->rip, pCtx->rflags, VBOXSTRICTRC_VAL(rcStrict) ));
    16491817    return rcStrict;
    16501818}
    1651 #endif
    1652 
    1653 #endif /* IN_RING0 */
     1819
    16541820
    16551821
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