VirtualBox

Changeset 72924 in vbox


Ignore:
Timestamp:
Jul 5, 2018 4:14:26 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123474
Message:

NEM/win: Make it possible to select between ring-0 runloop hypercalls+VID.SYS and ring-3 runloop using WHv API via CFGM setting. bugref:9044

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

Legend:

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

    r72917 r72924  
    151151NEM_TMPL_STATIC int nemHCWinCopyStateToHyperV(PVM pVM, PVMCPU pVCpu)
    152152{
    153 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    154     int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, 0, NULL);
    155     AssertLogRelRCReturn(rc, rc);
    156     return rc;
    157 
    158 # else
     153# if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)
     154#  if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)
     155    if (pVM->nem.s.fUseRing0Runloop)
     156#  endif
     157    {
     158        int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_EXPORT_STATE, 0, NULL);
     159        AssertLogRelRCReturn(rc, rc);
     160        return rc;
     161    }
     162# endif
     163# ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
     164
    159165    /*
    160166     * The following is very similar to what nemR0WinExportState() does.
     
    480486NEM_TMPL_STATIC int nemHCWinCopyStateFromHyperV(PVM pVM, PVMCPU pVCpu, uint64_t fWhat)
    481487{
    482 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    483     /* See NEMR0ImportState */
    484     int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_IMPORT_STATE, fWhat, NULL);
    485     if (RT_SUCCESS(rc))
     488# if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)
     489#  if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)
     490    if (pVM->nem.s.fUseRing0Runloop)
     491#  endif
     492    {
     493        /* See NEMR0ImportState */
     494        int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_IMPORT_STATE, fWhat, NULL);
     495        if (RT_SUCCESS(rc))
     496            return rc;
     497        if (rc == VERR_NEM_FLUSH_TLB)
     498            return PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /*fGlobal*/);
     499        if (rc == VERR_NEM_CHANGE_PGM_MODE)
     500            return PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
     501        AssertLogRelRCReturn(rc, rc);
    486502        return rc;
    487     if (rc == VERR_NEM_FLUSH_TLB)
    488         return PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /*fGlobal*/);
    489     if (rc == VERR_NEM_CHANGE_PGM_MODE)
    490         return PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
    491     AssertLogRelRCReturn(rc, rc);
    492     return rc;
    493 
    494 # else
     503    }
     504# endif
     505# ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    495506    WHV_REGISTER_NAME  aenmNames[128];
    496507
     
    11221133
    11231134#ifdef IN_RING0
     1135# ifdef NEM_WIN_WITH_RING0_RUNLOOP
    11241136    /** @todo improve and secure this translation */
    11251137    PGVM pGVM = GVMMR0ByHandle(pVCpu->pVMR0->hSelf);
     
    11301142
    11311143    return nemR0WinImportState(pGVM, &pGVM->aCpus[idCpu], &pVCpu->cpum.GstCtx, fWhat);
     1144# else
     1145    RT_NOREF(pVCpu, fWhat);
     1146    return VERR_NOT_IMPLEMENTED;
     1147# endif
    11321148#else
    11331149    return nemHCWinCopyStateFromHyperV(pVCpu->pVMR3, pVCpu, fWhat);
     
    11531169    AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9);
    11541170
    1155 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    1156     /* Call ring-0 and get the values. */
    1157     int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_QUERY_CPU_TICK, 0, NULL);
    1158     AssertLogRelRCReturn(rc, rc);
    1159     *pcTicks = pVCpu->nem.s.Hypercall.QueryCpuTick.cTicks;
    1160     if (puAux)
    1161         *puAux = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX
    1162                ? pVCpu->nem.s.Hypercall.QueryCpuTick.uAux : CPUMGetGuestTscAux(pVCpu);
    1163     return VINF_SUCCESS;
    1164 
    1165 # else
     1171# if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)
     1172#  if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)
     1173    if (pVM->nem.s.fUseRing0Runloop)
     1174#  endif
     1175    {
     1176        /* Call ring-0 and get the values. */
     1177        int rc = VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_QUERY_CPU_TICK, 0, NULL);
     1178        AssertLogRelRCReturn(rc, rc);
     1179        *pcTicks = pVCpu->nem.s.Hypercall.QueryCpuTick.cTicks;
     1180        if (puAux)
     1181            *puAux = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX
     1182                   ? pVCpu->nem.s.Hypercall.QueryCpuTick.uAux : CPUMGetGuestTscAux(pVCpu);
     1183        return VINF_SUCCESS;
     1184    }
     1185# endif
     1186# ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    11661187    /* Call the offical API. */
    11671188    WHV_REGISTER_NAME  aenmNames[2] = { WHvX64RegisterTsc, WHvX64RegisterTscAux };
     
    11771198        *pcTicks = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX ? aValues[0].Reg64 : CPUMGetGuestTscAux(pVCpu);
    11781199    return VINF_SUCCESS;
    1179 #endif
     1200# endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    11801201#else  /* IN_RING0 */
     1202# ifdef NEM_WIN_WITH_RING0_RUNLOOP
    11811203    /** @todo improve and secure this translation */
    11821204    PGVM pGVM = GVMMR0ByHandle(pVCpu->pVMR0->hSelf);
     
    11901212        *puAux = CPUMGetGuestTscAux(pVCpu);
    11911213    return rc;
     1214# else
     1215    RT_NOREF(pVCpu, pcTicks, puAux);
     1216    return VERR_NOT_IMPLEMENTED;
     1217# endif
    11921218#endif /* IN_RING0 */
    11931219}
     
    12071233{
    12081234#ifdef IN_RING0
     1235# ifdef NEM_WIN_WITH_RING0_RUNLOOP
    12091236    /** @todo improve and secure this translation */
    12101237    PGVM pGVM = GVMMR0ByHandle(pVM->hSelf);
     
    12151242
    12161243    return nemR0WinResumeCpuTickOnAll(pGVM, &pGVM->aCpus[idCpu], uPausedTscValue);
     1244# else
     1245    RT_NOREF(pVM, pVCpu, uPausedTscValue);
     1246    return VERR_NOT_IMPLEMENTED;
     1247# endif
    12171248#else  /* IN_RING3 */
    12181249    VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_VM_THREAD_NOT_EMT);
    12191250    AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9);
    12201251
    1221 # ifdef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    1222     /* Call ring-0 and do it all there. */
    1223     return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_RESUME_CPU_TICK_ON_ALL, uPausedTscValue, NULL);
    1224 
    1225 # else
     1252# if defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) || defined(NEM_WIN_WITH_RING0_RUNLOOP)
     1253#  if !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) && defined(NEM_WIN_WITH_RING0_RUNLOOP)
     1254    if (pVM->nem.s.fUseRing0Runloop)
     1255#  endif
     1256    {
     1257        /* Call ring-0 and do it all there. */
     1258        return VMMR3CallR0Emt(pVM, pVCpu, VMMR0_DO_NEM_RESUME_CPU_TICK_ON_ALL, uPausedTscValue, NULL);
     1259    }
     1260# endif
     1261# ifndef NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    12261262    /*
    12271263     * Call the offical API to do the job.
     
    12561292
    12571293    return VINF_SUCCESS;
    1258 # endif
     1294# endif /* !NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    12591295#endif /* IN_RING3 */
    12601296}
     
    13411377
    13421378
    1343 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1379#if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(NEM_WIN_WITH_RING0_RUNLOOP)
    13441380# ifdef IN_RING3 /* hopefully not needed in ring-0, as we'd need KTHREADs and KeAlertThread. */
    13451381/**
     
    14081444}
    14091445# endif /* IN_RING3 */
    1410 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
     1446#endif /* NEM_WIN_USE_OUR_OWN_RUN_API || NEM_WIN_WITH_RING0_RUNLOOP */
    14111447
    14121448
     
    14791515    while (0)
    14801516
    1481 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1517#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    14821518/**
    14831519 * Translates the execution stat bitfield into a short log string, VID version.
     
    15171553        SWITCH_IT("RM");
    15181554}
    1519 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     1555#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
    15201556#undef SWITCH_IT
    15211557
    15221558
    1523 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1559#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    15241560/**
    15251561 * Advances the guest RIP and clear EFLAGS.RF, VID version.
     
    15721608        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    15731609}
    1574 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     1610#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
    15751611
    15761612
     
    17961832
    17971833
    1798 #if defined(IN_RING0) && defined(NEM_WIN_USE_OUR_OWN_RUN_API)
     1834#if defined(IN_RING0) && defined(NEM_WIN_TEMPLATE_MODE_OWN_RUN_API)
    17991835/**
    18001836 * Wrapper around nemR0WinImportState that converts VERR_NEM_CHANGE_PGM_MODE and
     
    18251861    AssertMsgFailedReturn(("%s/%u: nemR0WinImportState failed: %Rrc\n", pszCaller, pGVCpu->idCpu, rc), rc);
    18261862}
    1827 #endif /* IN_RING0 && NEM_WIN_USE_OUR_OWN_RUN_API*/
    1828 
    1829 #if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3)
     1863#endif /* IN_RING0 && NEM_WIN_TEMPLATE_MODE_OWN_RUN_API*/
     1864
     1865#if defined(NEM_WIN_TEMPLATE_MODE_OWN_RUN_API) || defined(IN_RING3)
    18301866/**
    18311867 * Wrapper around nemR0WinImportStateStrict and nemHCWinCopyStateFromHyperV.
     
    18431879    if (pVCpu->cpum.GstCtx.fExtrn & fWhat)
    18441880    {
    1845 #ifdef IN_RING0
     1881# ifdef IN_RING0
    18461882        return nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pVCpu, fWhat, pszCaller);
    1847 #else
     1883# else
    18481884        RT_NOREF(pGVCpu, pszCaller);
    18491885        int rc = nemHCWinCopyStateFromHyperV(pVCpu->pVMR3, pVCpu, fWhat);
    18501886        AssertRCReturn(rc, rc);
    1851 #endif
     1887# endif
    18521888    }
    18531889    return VINF_SUCCESS;
    18541890}
    1855 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API || IN_RING3 */
    1856 
    1857 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1891#endif /* NEM_WIN_TEMPLATE_MODE_OWN_RUN_API || IN_RING3 */
     1892
     1893#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    18581894/**
    18591895 * Copies register state from the X64 intercept message header.
     
    19171953    pVCpu->cpum.GstCtx.fExtrn &= ~(CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_NEM_WIN_INHIBIT_INT);
    19181954}
    1919 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    1920 
    1921 
    1922 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     1955#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     1956
     1957
     1958#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    19231959/**
    19241960 * Deals with memory intercept message.
     
    21422178    return rcStrict;
    21432179}
    2144 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    2145 
    2146 
    2147 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2180#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     2181
     2182
     2183#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    21482184/**
    21492185 * Deals with I/O port intercept message.
     
    25242560    return rcStrict;
    25252561}
    2526 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    2527 
    2528 
    2529 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2562#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     2563
     2564
     2565#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    25302566/**
    25312567 * Deals with interrupt window message.
     
    25992635    return VINF_SUCCESS;
    26002636}
    2601 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    2602 
    2603 
    2604 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2637#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     2638
     2639
     2640#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    26052641/**
    26062642 * Deals with CPUID intercept message.
     
    27672803    return rcStrict;
    27682804}
    2769 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    2770 
    2771 
    2772 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2805#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     2806
     2807
     2808#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    27732809/**
    27742810 * Deals with MSR intercept message.
     
    30513087    return rcStrict;
    30523088}
    3053 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     3089#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
    30543090
    30553091
     
    31193155
    31203156
    3121 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3157#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    31223158/**
    31233159 * Copies state included in a exception intercept message.
     
    31663202        pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT;
    31673203}
    3168 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    3169 
    3170 
    3171 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3204#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     3205
     3206
     3207#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    31723208/**
    31733209 * Deals with exception intercept message (HvMessageTypeX64ExceptionIntercept).
     
    33993435    return rcStrict;
    34003436}
    3401 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    3402 
    3403 
    3404 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3437#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     3438
     3439
     3440#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    34053441/**
    34063442 * Deals with unrecoverable exception (triple fault).
     
    35193555
    35203556}
    3521 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
    3522 
    3523 
    3524 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3557#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     3558
     3559
     3560#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    35253561/**
    35263562 * Handles messages (VM exits).
     
    36833719    }
    36843720}
    3685 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */
     3721#endif /* IN_RING3 && !NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
    36863722
    36873723
     
    37403776
    37413777
    3742 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     3778#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    37433779/**
    37443780 * Worker for nemHCWinRunGC that stops the execution on the way out.
     
    38983934    return rcStrict;
    38993935}
    3900 #endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
    3901 
    3902 #if defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3)
     3936#endif /* NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
     3937
     3938#if defined(NEM_WIN_TEMPLATE_MODE_OWN_RUN_API) || defined(IN_RING3)
    39033939
    39043940/**
     
    40484084     * everything every time.  This will be optimized later.
    40494085     */
    4050 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4086# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    40514087    VID_MESSAGE_MAPPING_HEADER volatile *pMappingHeader = (VID_MESSAGE_MAPPING_HEADER volatile *)pVCpu->nem.s.pvMsgSlotMapping;
    40524088    uint32_t        cMillies            = 5000; /** @todo lower this later... */
     
    40794115                                     | VMCPU_FF_INTERRUPT_NMI  | VMCPU_FF_INTERRUPT_SMI))
    40804116        {
    4081 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4117# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    40824118            /* Make sure the CPU isn't executing. */
    40834119            if (pVCpu->nem.s.fHandleAndGetFlags == VID_MSHAGN_F_GET_NEXT_MESSAGE)
     
    41184154            || pVCpu->nem.s.fCurrentInterruptWindows != pVCpu->nem.s.fDesiredInterruptWindows)
    41194155        {
    4120 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4156# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    41214157            Assert(pVCpu->nem.s.fHandleAndGetFlags != VID_MSHAGN_F_GET_NEXT_MESSAGE /* not running */);
    41224158# endif
     
    41364172            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
    41374173        {
    4138 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4174# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    41394175            if (pVCpu->nem.s.fHandleAndGetFlags)
    41404176            { /* Very likely that the CPU does NOT need starting (pending msg, running). */ }
     
    41574193                pVCpu->nem.s.fHandleAndGetFlags = VID_MSHAGN_F_GET_NEXT_MESSAGE;
    41584194            }
    4159 # endif /* NEM_WIN_USE_OUR_OWN_RUN_API */
     4195# endif /* NEM_WIN_TEMPLATE_MODE_OWN_RUN_API */
    41604196
    41614197            if (VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC_NEM_WAIT, VMCPUSTATE_STARTED_EXEC_NEM))
    41624198            {
    4163 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4199# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    41644200#  ifdef IN_RING0
    41654201                pVCpu->nem.s.uIoCtlBuf.MsgSlotHandleAndGetNext.iCpu     = pGVCpu->idCpu;
     
    41894225                     * Deal with the message.
    41904226                     */
    4191 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4227# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    41924228                    rcStrict = nemHCWinHandleMessage(pVM, pVCpu, pMappingHeader, pGVCpu);
    41934229                    pVCpu->nem.s.fHandleAndGetFlags |= VID_MSHAGN_F_HANDLE_MESSAGE;
     
    42064242                else
    42074243                {
    4208 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4244# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    42094245
    42104246                    /* VID.SYS merges STATUS_ALERTED and STATUS_USER_APC into STATUS_TIMEOUT,
     
    42634299     * state and return to EM.  We don't sync back the whole state if we can help it.
    42644300     */
    4265 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     4301# ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    42664302    if (pVCpu->nem.s.fHandleAndGetFlags == VID_MSHAGN_F_GET_NEXT_MESSAGE)
    42674303    {
     
    43374373}
    43384374
    4339 #endif /* defined(NEM_WIN_USE_OUR_OWN_RUN_API) || defined(IN_RING3) */
     4375#endif /* defined(NEM_WIN_TEMPLATE_MODE_OWN_RUN_API) || defined(IN_RING3) */
    43404376
    43414377/**
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r72918 r72924  
    8282                                      uint32_t cPages, uint32_t fFlags);
    8383NEM_TMPL_STATIC int  nemR0WinUnmapPages(PGVM pGVM, PGVMCPU pGVCpu, RTGCPHYS GCPhys, uint32_t cPages);
     84#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    8485NEM_TMPL_STATIC int  nemR0WinExportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx);
    8586NEM_TMPL_STATIC int  nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat);
    8687NEM_TMPL_STATIC int  nemR0WinQueryCpuTick(PGVM pGVM, PGVMCPU pGVCpu, uint64_t *pcTicks, uint32_t *pcAux);
    8788NEM_TMPL_STATIC int  nemR0WinResumeCpuTickOnAll(PGVM pGVM, PGVMCPU pGVCpu, uint64_t uPausedTscValue);
     89#endif
    8890DECLINLINE(NTSTATUS) nemR0NtPerformIoControl(PGVM pGVM, uint32_t uFunction, void *pvInput, uint32_t cbInput,
    8991                                             void *pvOutput, uint32_t cbOutput);
     
    9395 * Instantate the code we share with ring-0.
    9496 */
     97#ifdef NEM_WIN_WITH_RING0_RUNLOOP
     98# define NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
     99#else
     100# undef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
     101#endif
    95102#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
     103
     104
    96105
    97106/**
     
    582591
    583592
     593#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    584594/**
    585595 * Worker for NEMR0ExportState.
     
    722732
    723733    /* Segments */
    724 #define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
     734# define COPY_OUT_SEG(a_idx, a_enmName, a_SReg) \
    725735        do { \
    726736            HV_REGISTER_ASSOC_ZERO_PADDING(&pInput->Elements[a_idx]); \
     
    10981108        pInput->Elements[iReg].Value.Reg64          = pCtx->msrPAT;
    10991109        iReg++;
    1100 #if 0 /** @todo HvX64RegisterMtrrCap is read only?  Seems it's not even readable. */
     1110# if 0 /** @todo HvX64RegisterMtrrCap is read only?  Seems it's not even readable. */
    11011111        HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(&pInput->Elements[iReg]);
    11021112        pInput->Elements[iReg].Name                 = HvX64RegisterMtrrCap;
    11031113        pInput->Elements[iReg].Value.Reg64          = CPUMGetGuestIa32MtrrCap(pVCpu);
    11041114        iReg++;
    1105 #endif
     1115# endif
    11061116
    11071117        PCPUMCTXMSRS pCtxMsrs = CPUMQueryGuestCtxMsrsPtr(pVCpu);
     
    11631173        iReg++;
    11641174
    1165 #if 0 /** @todo Why can't we write these on Intel systems? Not that we really care... */
     1175# if 0 /** @todo Why can't we write these on Intel systems? Not that we really care... */
    11661176        const CPUMCPUVENDOR enmCpuVendor = CPUMGetHostCpuVendor(pGVM->pVM);
    11671177        if (enmCpuVendor != CPUMCPUVENDOR_AMD)
     
    11761186            iReg++;
    11771187        }
    1178 #endif
     1188# endif
    11791189    }
    11801190
     
    12601270    return VINF_SUCCESS;
    12611271}
     1272#endif /* NEM_WIN_WITH_RING0_RUNLOOP || NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    12621273
    12631274
     
    12731284VMMR0_INT_DECL(int)  NEMR0ExportState(PGVM pGVM, PVM pVM, VMCPUID idCpu)
    12741285{
     1286#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    12751287    /*
    12761288     * Validate the call.
     
    12891301    }
    12901302    return rc;
     1303#else
     1304    RT_NOREF(pGVM, pVM, idCpu);
     1305    return VERR_NOT_IMPLEMENTED;
     1306#endif
    12911307}
    12921308
    12931309
     1310#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    12941311/**
    12951312 * Worker for NEMR0ImportState.
     
    14701487    }
    14711488
    1472 #ifdef LOG_ENABLED
     1489# ifdef LOG_ENABLED
    14731490    const CPUMCPUVENDOR enmCpuVendor = CPUMGetHostCpuVendor(pGVM->pVM);
    1474 #endif
     1491# endif
    14751492    if (fWhat & CPUMCTX_EXTRN_OTHER_MSRS)
    14761493    {
    14771494        pInput->Names[iReg++] = HvX64RegisterApicBase; /// @todo APIC BASE
    14781495        pInput->Names[iReg++] = HvX64RegisterPat;
    1479 #if 0 /*def LOG_ENABLED*/ /** @todo something's wrong with HvX64RegisterMtrrCap? (AMD) */
     1496# if 0 /*def LOG_ENABLED*/ /** @todo something's wrong with HvX64RegisterMtrrCap? (AMD) */
    14801497        pInput->Names[iReg++] = HvX64RegisterMtrrCap;
    1481 #endif
     1498# endif
    14821499        pInput->Names[iReg++] = HvX64RegisterMtrrDefType;
    14831500        pInput->Names[iReg++] = HvX64RegisterMtrrFix64k00000;
     
    14931510        pInput->Names[iReg++] = HvX64RegisterMtrrFix4kF8000;
    14941511        pInput->Names[iReg++] = HvX64RegisterTscAux;
    1495 #if 0 /** @todo why can't we read HvX64RegisterIa32MiscEnable? */
     1512# if 0 /** @todo why can't we read HvX64RegisterIa32MiscEnable? */
    14961513        if (enmCpuVendor != CPUMCPUVENDOR_AMD)
    14971514            pInput->Names[iReg++] = HvX64RegisterIa32MiscEnable;
    1498 #endif
    1499 #ifdef LOG_ENABLED
     1515# endif
     1516# ifdef LOG_ENABLED
    15001517        if (enmCpuVendor != CPUMCPUVENDOR_AMD)
    15011518            pInput->Names[iReg++] = HvX64RegisterIa32FeatureControl;
    1502 #endif
     1519# endif
    15031520    }
    15041521
     
    16091626
    16101627    /* Segments */
    1611 #define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
     1628# define COPY_BACK_SEG(a_idx, a_enmName, a_SReg) \
    16121629        do { \
    16131630            Assert(pInput->Names[a_idx] == a_enmName); \
     
    19892006        iReg++;
    19902007
    1991 #if 0 /*def LOG_ENABLED*/ /** @todo something's wrong with HvX64RegisterMtrrCap? (AMD) */
     2008# if 0 /*def LOG_ENABLED*/ /** @todo something's wrong with HvX64RegisterMtrrCap? (AMD) */
    19922009        Assert(pInput->Names[iReg] == HvX64RegisterMtrrCap);
    19932010        if (paValues[iReg].Reg64 != CPUMGetGuestIa32MtrrCap(pVCpu))
    19942011            Log7(("NEM/%u: MSR MTRR_CAP changed %RX64 -> %RX64 (!!)\n", pVCpu->idCpu, CPUMGetGuestIa32MtrrCap(pVCpu), paValues[iReg].Reg64));
    19952012        iReg++;
    1996 #endif
     2013# endif
    19972014
    19982015        PCPUMCTXMSRS pCtxMsrs = CPUMQueryGuestCtxMsrsPtr(pVCpu);
     
    20772094        iReg++;
    20782095
    2079 #if 0 /** @todo why can't we even read HvX64RegisterIa32MiscEnable? */
     2096# if 0 /** @todo why can't we even read HvX64RegisterIa32MiscEnable? */
    20802097        if (enmCpuVendor != CPUMCPUVENDOR_AMD)
    20812098        {
     
    20862103            iReg++;
    20872104        }
    2088 #endif
    2089 #ifdef LOG_ENABLED
     2105# endif
     2106# ifdef LOG_ENABLED
    20902107        if (enmCpuVendor != CPUMCPUVENDOR_AMD)
    20912108        {
     
    20952112            iReg++;
    20962113        }
    2097 #endif
     2114# endif
    20982115    }
    20992116
     
    21792196    return rc;
    21802197}
     2198#endif /* NEM_WIN_WITH_RING0_RUNLOOP || NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    21812199
    21822200
     
    21942212VMMR0_INT_DECL(int) NEMR0ImportState(PGVM pGVM, PVM pVM, VMCPUID idCpu, uint64_t fWhat)
    21952213{
     2214#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    21962215    /*
    21972216     * Validate the call.
     
    22102229    }
    22112230    return rc;
     2231#else
     2232    RT_NOREF(pGVM, pVM, idCpu, fWhat);
     2233    return VERR_NOT_IMPLEMENTED;
     2234#endif
    22122235}
    22132236
    22142237
     2238#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    22152239/**
    22162240 * Worker for NEMR0QueryCpuTick and the ring-0 NEMHCQueryCpuTick.
     
    22582282    return VINF_SUCCESS;
    22592283}
     2284#endif /* NEM_WIN_WITH_RING0_RUNLOOP || NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    22602285
    22612286
     
    22712296VMMR0_INT_DECL(int) NEMR0QueryCpuTick(PGVM pGVM, PVM pVM, VMCPUID idCpu)
    22722297{
     2298#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    22732299    /*
    22742300     * Validate the call.
     
    22902316    }
    22912317    return rc;
     2318#else
     2319    RT_NOREF(pGVM, pVM, idCpu);
     2320    return VERR_NOT_IMPLEMENTED;
     2321#endif
    22922322}
    22932323
    22942324
     2325#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    22952326/**
    22962327 * Worker for NEMR0ResumeCpuTickOnAll and the ring-0 NEMHCResumeCpuTickOnAll.
     
    23602391    return VINF_SUCCESS;
    23612392}
     2393#endif /* NEM_WIN_WITH_RING0_RUNLOOP || NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS */
    23622394
    23632395
     
    23742406VMMR0_INT_DECL(int) NEMR0ResumeCpuTickOnAll(PGVM pGVM, PVM pVM, VMCPUID idCpu, uint64_t uPausedTscValue)
    23752407{
     2408#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    23762409    /*
    23772410     * Validate the call.
     
    23922425    }
    23932426    return rc;
     2427#else
     2428    RT_NOREF(pGVM, pVM, idCpu, uPausedTscValue);
     2429    return VERR_NOT_IMPLEMENTED;
     2430#endif
    23942431}
    23952432
     
    23972434VMMR0_INT_DECL(VBOXSTRICTRC) NEMR0RunGuestCode(PGVM pGVM, VMCPUID idCpu)
    23982435{
    2399 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     2436#ifdef NEM_WIN_WITH_RING0_RUNLOOP
    24002437    PVM pVM = pGVM->pVM;
    24012438    return nemHCWinRunGC(pVM, &pVM->aCpus[idCpu], pGVM, &pGVM->aCpus[idCpu]);
  • trunk/src/VBox/VMM/VMMR3/NEMR3.cpp

    r72634 r72924  
    7878                                  "/NEM/",
    7979                                  "Enabled"
    80                                   "|Allow64BitGuests",
     80                                  "|Allow64BitGuests"
     81#ifdef RT_OS_WINDOWS
     82                                  "|UseRing0Runloop"
     83#endif
     84                                  ,
    8185                                  "" /* pszValidNodes */, "NEM" /* pszWho */, 0 /* uInstance */);
    8286    if (RT_FAILURE(rc))
     
    9094
    9195#ifdef VBOX_WITH_64_BITS_GUESTS
    92     /** @cfgm{/HM/Allow64BitGuests, bool, 32-bit:false, 64-bit:true}
     96    /** @cfgm{/NEM/Allow64BitGuests, bool, 32-bit:false, 64-bit:true}
    9397     * Enables AMD64 CPU features.
    9498     * On 32-bit hosts this isn't default and require host CPU support. 64-bit hosts
     
    100104#endif
    101105
     106#ifdef RT_OS_WINDOWS
     107    /** @cfgm{/NEM/UseRing0Runloop, bool, true}
     108     * Whether to use the ring-0 runloop (if enabled in the build) or the ring-3 one.
     109     * The latter is generally slower.  This option serves as a way out in case
     110     * something breaks in the ring-0 loop. */
     111# ifdef NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT
     112    bool fUseRing0Runloop = true;
     113# else
     114    bool fUseRing0Runloop = false;
     115# endif
     116    rc = CFGMR3QueryBoolDef(pCfgNem, "UseRing0Runloop", &fUseRing0Runloop, fUseRing0Runloop);
     117    AssertLogRelRCReturn(rc, rc);
     118    pVM->nem.s.fUseRing0Runloop = fUseRing0Runloop;
     119#endif
    102120
    103121    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72918 r72924  
    234234 * Instantate the code we share with ring-0.
    235235 */
     236#ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     237# define NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
     238#else
     239# undef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
     240#endif
    236241#include "../VMMAll/NEMAllNativeTemplate-win.cpp.h"
    237242
     
    13881393        Assert((HANDLE)pVCpu->nem.s.hNativeThreadHandle != INVALID_HANDLE_VALUE);
    13891394
    1390 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    1391         VID_MAPPED_MESSAGE_SLOT MappedMsgSlot = { NULL, UINT32_MAX, UINT32_MAX };
    1392         if (g_pfnVidMessageSlotMap(hPartitionDevice, &MappedMsgSlot, iCpu))
     1395#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
     1396# ifdef NEM_WIN_WITH_RING0_RUNLOOP
     1397        if (!pVM->nem.s.fUseRing0Runloop)
     1398# endif
    13931399        {
    1394             AssertLogRelMsg(MappedMsgSlot.iCpu == iCpu && MappedMsgSlot.uParentAdvisory == UINT32_MAX,
    1395                             ("%#x %#x (iCpu=%#x)\n", MappedMsgSlot.iCpu, MappedMsgSlot.uParentAdvisory, iCpu));
    1396             pVCpu->nem.s.pvMsgSlotMapping = MappedMsgSlot.pMsgBlock;
     1400            hrc = WHvCreateVirtualProcessor(hPartition, iCpu, 0 /*fFlags*/);
     1401            if (FAILED(hrc))
     1402            {
     1403                NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     1404                DWORD const    dwErrLast = RTNtLastErrorValue();
     1405                while (iCpu-- > 0)
     1406                {
     1407                    HRESULT hrc2 = WHvDeleteVirtualProcessor(hPartition, iCpu);
     1408                    AssertLogRelMsg(SUCCEEDED(hrc2), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
     1409                                                      hPartition, iCpu, hrc2, RTNtLastStatusValue(),
     1410                                                      RTNtLastErrorValue()));
     1411                }
     1412                return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     1413                                  "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
     1414            }
    13971415        }
     1416# ifdef NEM_WIN_WITH_RING0_RUNLOOP
    13981417        else
     1418# endif
     1419#endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */
     1420#if defined(NEM_WIN_WITH_RING0_RUNLOOP) || defined(NEM_WIN_USE_OUR_OWN_RUN_API)
    13991421        {
    1400             NTSTATUS const rcNtLast  = RTNtLastStatusValue();
    1401             DWORD const    dwErrLast = RTNtLastErrorValue();
    1402             return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    1403                               "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
     1422            VID_MAPPED_MESSAGE_SLOT MappedMsgSlot = { NULL, UINT32_MAX, UINT32_MAX };
     1423            if (g_pfnVidMessageSlotMap(hPartitionDevice, &MappedMsgSlot, iCpu))
     1424            {
     1425                AssertLogRelMsg(MappedMsgSlot.iCpu == iCpu && MappedMsgSlot.uParentAdvisory == UINT32_MAX,
     1426                                ("%#x %#x (iCpu=%#x)\n", MappedMsgSlot.iCpu, MappedMsgSlot.uParentAdvisory, iCpu));
     1427                pVCpu->nem.s.pvMsgSlotMapping = MappedMsgSlot.pMsgBlock;
     1428            }
     1429            else
     1430            {
     1431                NTSTATUS const rcNtLast  = RTNtLastStatusValue();
     1432                DWORD const    dwErrLast = RTNtLastErrorValue();
     1433                return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     1434                                  "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
     1435            }
    14041436        }
    1405 #else
    1406         hrc = WHvCreateVirtualProcessor(hPartition, iCpu, 0 /*fFlags*/);
    1407         if (FAILED(hrc))
    1408         {
    1409             NTSTATUS const rcNtLast  = RTNtLastStatusValue();
    1410             DWORD const    dwErrLast = RTNtLastErrorValue();
    1411             while (iCpu-- > 0)
    1412             {
    1413                 HRESULT hrc2 = WHvDeleteVirtualProcessor(hPartition, iCpu);
    1414                 AssertLogRelMsg(SUCCEEDED(hrc2), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    1415                                                   hPartition, iCpu, hrc2, RTNtLastStatusValue(),
    1416                                                   RTNtLastErrorValue()));
    1417             }
    1418             return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    1419                               "Call to WHvSetupPartition failed: %Rhrc (Last=%#x/%u)", hrc, rcNtLast, dwErrLast);
    1420         }
    1421 #endif /* !NEM_WIN_USE_OUR_OWN_RUN_API */
     1437#endif
    14221438    }
    14231439    pVM->nem.s.fCreatedEmts = true;
     
    15831599        while (iCpu-- > 0)
    15841600        {
    1585 #ifdef NEM_WIN_USE_OUR_OWN_RUN_API
    15861601            pVM->aCpus[iCpu].nem.s.pvMsgSlotMapping = NULL;
    1587 #else
    1588             HRESULT hrc = WHvDeleteVirtualProcessor(hPartition, iCpu);
    1589             AssertLogRelMsg(SUCCEEDED(hrc), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
    1590                                              hPartition, iCpu, hrc, RTNtLastStatusValue(),
    1591                                              RTNtLastErrorValue()));
     1602#ifndef NEM_WIN_USE_OUR_OWN_RUN_API
     1603# ifdef NEM_WIN_WITH_RING0_RUNLOOP
     1604            if (!pVM->nem.s.fUseRing0Runloop)
     1605# endif
     1606            {
     1607                HRESULT hrc = WHvDeleteVirtualProcessor(hPartition, iCpu);
     1608                AssertLogRelMsg(SUCCEEDED(hrc), ("WHvDeleteVirtualProcessor(%p, %u) -> %Rhrc (Last=%#x/%u)\n",
     1609                                                 hPartition, iCpu, hrc, RTNtLastStatusValue(),
     1610                                                 RTNtLastErrorValue()));
     1611            }
    15921612#endif
    15931613        }
     
    16341654VBOXSTRICTRC nemR3NativeRunGC(PVM pVM, PVMCPU pVCpu)
    16351655{
    1636 #if !defined(NEM_WIN_USE_OUR_OWN_RUN_API) || 0
    1637     return nemHCWinRunGC(pVM, pVCpu, NULL /*pGVM*/, NULL /*pGVCpu*/);
    1638 #else
    1639     for (;;)
     1656#ifdef NEM_WIN_WITH_RING0_RUNLOOP
     1657    if (pVM->nem.s.fUseRing0Runloop)
    16401658    {
    1641         VBOXSTRICTRC rcStrict = VMMR3CallR0EmtFast(pVM, pVCpu, VMMR0_DO_NEM_RUN);
    1642         if (RT_SUCCESS(rcStrict))
     1659        for (;;)
    16431660        {
    1644             /*
    1645              * We deal with VINF_NEM_CHANGE_PGM_MODE, VINF_NEM_FLUSH_TLB and
    1646              * VINF_NEM_UPDATE_APIC_BASE  here, since we're running the risk of
    1647              * getting these while we already got another RC (I/O ports).
    1648              *
    1649              * The APIC base update and a PGM update can happen at the same time, so
    1650              * we don't depend on the status code for that and always checks it first.
    1651              */
    1652             /* APIC base: */
    1653             if (pVCpu->nem.s.uPendingApicBase != UINT64_MAX)
     1661            VBOXSTRICTRC rcStrict = VMMR3CallR0EmtFast(pVM, pVCpu, VMMR0_DO_NEM_RUN);
     1662            if (RT_SUCCESS(rcStrict))
    16541663            {
    1655                 LogFlow(("nemR3NativeRunGC: calling APICSetBaseMsr(,%RX64)...\n", pVCpu->nem.s.uPendingApicBase));
    1656                 VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, pVCpu->nem.s.uPendingApicBase);
    1657                 AssertLogRelMsg(rc2 == VINF_SUCCESS, ("rc2=%Rrc [%#RX64]\n", VBOXSTRICTRC_VAL(rc2), pVCpu->nem.s.uPendingApicBase));
    1658                 pVCpu->nem.s.uPendingApicBase = UINT64_MAX;
    1659             }
    1660 
    1661             /* Status codes: */
    1662             VBOXSTRICTRC rcPending = pVCpu->nem.s.rcPending;
    1663             pVCpu->nem.s.rcPending = VINF_SUCCESS;
    1664             if (   rcStrict == VINF_NEM_CHANGE_PGM_MODE
    1665                 || rcStrict == VINF_PGM_CHANGE_MODE
    1666                 || rcPending == VINF_NEM_CHANGE_PGM_MODE )
    1667             {
    1668                 LogFlow(("nemR3NativeRunGC: calling PGMChangeMode...\n"));
    1669                 int rc = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
    1670                 AssertRCReturn(rc, rc);
     1664                /*
     1665                 * We deal with VINF_NEM_CHANGE_PGM_MODE, VINF_NEM_FLUSH_TLB and
     1666                 * VINF_NEM_UPDATE_APIC_BASE  here, since we're running the risk of
     1667                 * getting these while we already got another RC (I/O ports).
     1668                 *
     1669                 * The APIC base update and a PGM update can happen at the same time, so
     1670                 * we don't depend on the status code for that and always checks it first.
     1671                 */
     1672                /* APIC base: */
     1673                if (pVCpu->nem.s.uPendingApicBase != UINT64_MAX)
     1674                {
     1675                    LogFlow(("nemR3NativeRunGC: calling APICSetBaseMsr(,%RX64)...\n", pVCpu->nem.s.uPendingApicBase));
     1676                    VBOXSTRICTRC rc2 = APICSetBaseMsr(pVCpu, pVCpu->nem.s.uPendingApicBase);
     1677                    AssertLogRelMsg(rc2 == VINF_SUCCESS, ("rc2=%Rrc [%#RX64]\n", VBOXSTRICTRC_VAL(rc2), pVCpu->nem.s.uPendingApicBase));
     1678                    pVCpu->nem.s.uPendingApicBase = UINT64_MAX;
     1679                }
     1680
     1681                /* Status codes: */
     1682                VBOXSTRICTRC rcPending = pVCpu->nem.s.rcPending;
     1683                pVCpu->nem.s.rcPending = VINF_SUCCESS;
    16711684                if (   rcStrict == VINF_NEM_CHANGE_PGM_MODE
    16721685                    || rcStrict == VINF_PGM_CHANGE_MODE
    1673                     || rcStrict == VINF_NEM_FLUSH_TLB)
     1686                    || rcPending == VINF_NEM_CHANGE_PGM_MODE )
    16741687                {
    1675                     if (   !VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK | VM_FF_HP_R0_PRE_HM_MASK)
    1676                         && !VMCPU_FF_IS_PENDING(pVCpu,   (VMCPU_FF_HIGH_PRIORITY_POST_MASK | VMCPU_FF_HP_R0_PRE_HM_MASK)
    1677                                                        & ~VMCPU_FF_RESUME_GUEST_MASK))
     1688                    LogFlow(("nemR3NativeRunGC: calling PGMChangeMode...\n"));
     1689                    int rc = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
     1690                    AssertRCReturn(rc, rc);
     1691                    if (   rcStrict == VINF_NEM_CHANGE_PGM_MODE
     1692                        || rcStrict == VINF_PGM_CHANGE_MODE
     1693                        || rcStrict == VINF_NEM_FLUSH_TLB)
    16781694                    {
    1679                         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
    1680                         continue;
     1695                        if (   !VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK | VM_FF_HP_R0_PRE_HM_MASK)
     1696                            && !VMCPU_FF_IS_PENDING(pVCpu,   (VMCPU_FF_HIGH_PRIORITY_POST_MASK | VMCPU_FF_HP_R0_PRE_HM_MASK)
     1697                                                           & ~VMCPU_FF_RESUME_GUEST_MASK))
     1698                        {
     1699                            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
     1700                            continue;
     1701                        }
     1702                        rcStrict = VINF_SUCCESS;
    16811703                    }
    1682                     rcStrict = VINF_SUCCESS;
    16831704                }
     1705                else if (rcStrict == VINF_NEM_FLUSH_TLB || rcPending == VINF_NEM_FLUSH_TLB)
     1706                {
     1707                    LogFlow(("nemR3NativeRunGC: calling PGMFlushTLB...\n"));
     1708                    int rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true);
     1709                    AssertRCReturn(rc, rc);
     1710                    if (rcStrict == VINF_NEM_FLUSH_TLB || rcStrict == VINF_NEM_CHANGE_PGM_MODE)
     1711                    {
     1712                        if (   !VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK | VM_FF_HP_R0_PRE_HM_MASK)
     1713                            && !VMCPU_FF_IS_PENDING(pVCpu,   (VMCPU_FF_HIGH_PRIORITY_POST_MASK | VMCPU_FF_HP_R0_PRE_HM_MASK)
     1714                                                           & ~VMCPU_FF_RESUME_GUEST_MASK))
     1715                        {
     1716                            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
     1717                            continue;
     1718                        }
     1719                        rcStrict = VINF_SUCCESS;
     1720                    }
     1721                }
     1722                else if (rcStrict == VINF_NEM_UPDATE_APIC_BASE || rcPending == VERR_NEM_UPDATE_APIC_BASE)
     1723                    continue;
     1724                else
     1725                    AssertMsg(rcPending == VINF_SUCCESS, ("rcPending=%Rrc\n", VBOXSTRICTRC_VAL(rcPending) ));
    16841726            }
    1685             else if (rcStrict == VINF_NEM_FLUSH_TLB || rcPending == VINF_NEM_FLUSH_TLB)
    1686             {
    1687                 LogFlow(("nemR3NativeRunGC: calling PGMFlushTLB...\n"));
    1688                 int rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true);
    1689                 AssertRCReturn(rc, rc);
    1690                 if (rcStrict == VINF_NEM_FLUSH_TLB || rcStrict == VINF_NEM_CHANGE_PGM_MODE)
    1691                 {
    1692                     if (   !VM_FF_IS_PENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK | VM_FF_HP_R0_PRE_HM_MASK)
    1693                         && !VMCPU_FF_IS_PENDING(pVCpu,   (VMCPU_FF_HIGH_PRIORITY_POST_MASK | VMCPU_FF_HP_R0_PRE_HM_MASK)
    1694                                                        & ~VMCPU_FF_RESUME_GUEST_MASK))
    1695                     {
    1696                         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
    1697                         continue;
    1698                     }
    1699                     rcStrict = VINF_SUCCESS;
    1700                 }
    1701             }
    1702             else if (rcStrict == VINF_NEM_UPDATE_APIC_BASE || rcPending == VERR_NEM_UPDATE_APIC_BASE)
    1703                 continue;
    1704             else
    1705                 AssertMsg(rcPending == VINF_SUCCESS, ("rcPending=%Rrc\n", VBOXSTRICTRC_VAL(rcPending) ));
     1727            LogFlow(("nemR3NativeRunGC: returns %Rrc\n", VBOXSTRICTRC_VAL(rcStrict) ));
     1728            return rcStrict;
    17061729        }
    1707         LogFlow(("nemR3NativeRunGC: returns %Rrc\n", VBOXSTRICTRC_VAL(rcStrict) ));
    1708         return rcStrict;
    17091730    }
    17101731#endif
     1732    return nemHCWinRunGC(pVM, pVCpu, NULL /*pGVM*/, NULL /*pGVCpu*/);
    17111733}
    17121734
     
    17411763    nemHCWinCancelRunVirtualProcessor(pVM, pVCpu);
    17421764#else
    1743     Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu));
    1744     HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0);
    1745     AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc));
    1746     RT_NOREF_PV(hrc);
     1765# ifdef NEM_WIN_WITH_RING0_RUNLOOP
     1766    if (pVM->nem.s.fUseRing0Runloop)
     1767        nemHCWinCancelRunVirtualProcessor(pVM, pVCpu);
     1768    else
     1769# endif
     1770    {
     1771        Log8(("nemR3NativeNotifyFF: canceling %u\n", pVCpu->idCpu));
     1772        HRESULT hrc = WHvCancelRunVirtualProcessor(pVM->nem.s.hPartition, pVCpu->idCpu, 0);
     1773        AssertMsg(SUCCEEDED(hrc), ("WHvCancelRunVirtualProcessor -> hrc=%Rhrc\n", hrc));
     1774        RT_NOREF_PV(hrc);
     1775    }
    17471776#endif
    17481777    RT_NOREF_PV(fFlags);
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r72690 r72924  
    4545 */
    4646# define NEM_WIN_USE_HYPERCALLS_FOR_PAGES
    47 # define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS
    48 # define NEM_WIN_USE_OUR_OWN_RUN_API
     47//# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS /**< Applies to ring-3 code only. Useful for testing VID API. */
     48//# define NEM_WIN_USE_OUR_OWN_RUN_API          /**< Applies to ring-3 code only. Useful for testing VID API. */
     49# define NEM_WIN_WITH_RING0_RUNLOOP             /**< Enables the ring-0 runloop. */
     50# define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT   /**< For quickly testing ring-3 API without messing with CFGM. */
    4951# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS)
    5052#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
     
    5254# if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
    5355#  error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
     56# endif
     57# if defined(NEM_WIN_WITH_RING0_RUNLOOP) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_PAGES)
     58#  error "NEM_WIN_WITH_RING0_RUNLOOP requires NEM_WIN_USE_HYPERCALLS_FOR_PAGES"
    5459# endif
    5560
     
    148153    /** WHvRunVpExitReasonException is supported. */
    149154    bool                        fExtendedXcptExit : 1;
     155    /** Set if we're using the ring-0 API to do the work. */
     156    bool                        fUseRing0Runloop : 1;
    150157    /** Set if we've started more than one CPU and cannot mess with A20. */
    151158    bool                        fA20Fixed : 1;
     
    228235     * This is set to UINT64_MAX when not pending  */
    229236    uint64_t                    uPendingApicBase;
    230 # ifdef NEM_WIN_USE_OUR_OWN_RUN_API
     237# ifdef NEM_WIN_WITH_RING0_RUNLOOP
    231238    /** Pending VINF_NEM_CHANGE_PGM_MODE, VINF_NEM_FLUSH_TLB or VINF_NEM_UPDATE_APIC_BASE. */
    232239    int32_t                     rcPending;
     240# else
     241    uint32_t                    uPadding;
     242# endif
    233243    /** The VID_MSHAGN_F_XXX flags.
    234244     * Either VID_MSHAGN_F_HANDLE_MESSAGE | VID_MSHAGN_F_GET_NEXT_MESSAGE or zero. */
     
    236246    /** What VidMessageSlotMap returns and is used for passing exit info. */
    237247    RTR3PTR                     pvMsgSlotMapping;
    238 # endif
    239248    /** The windows thread handle. */
    240249    RTR3PTR                     hNativeThreadHandle;
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