VirtualBox

Changeset 72546 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Jun 13, 2018 3:45:39 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123036
Message:

NEM/win,TM: Setting TSC on TM start/restore/resume/etc as best we can. bugref:9044

Location:
trunk/src/VBox/VMM/VMMR0
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp

    r72544 r72546  
    8484NEM_TMPL_STATIC int  nemR0WinImportState(PGVM pGVM, PGVMCPU pGVCpu, PCPUMCTX pCtx, uint64_t fWhat);
    8585NEM_TMPL_STATIC int  nemR0WinQueryCpuTick(PGVM pGVM, PGVMCPU pGVCpu, uint64_t *pcTicks, uint32_t *pcAux);
     86NEM_TMPL_STATIC int  nemR0WinResumeCpuTickOnAll(PGVM pGVM, PGVMCPU pGVCpu, uint64_t uPausedTscValue);
    8687DECLINLINE(NTSTATUS) nemR0NtPerformIoControl(PGVM pGVM, uint32_t uFunction, void *pvInput, uint32_t cbInput,
    8788                                             void *pvOutput, uint32_t cbOutput);
     
    595596    HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
    596597    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
     598    AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    597599
    598600    pInput->PartitionId = pGVM->nem.s.idHvPartition;
     
    13041306    HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
    13051307    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
     1308    AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    13061309
    13071310    fWhat &= pCtx->fExtrn;
     
    22222225    HV_INPUT_GET_VP_REGISTERS *pInput = (HV_INPUT_GET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
    22232226    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
     2227    AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    22242228
    22252229    pInput->PartitionId = pGVM->nem.s.idHvPartition;
     
    22802284        rc = nemR0WinQueryCpuTick(pGVM, pGVCpu, &pVCpu->nem.s.Hypercall.QueryCpuTick.cTicks,
    22812285                                  &pVCpu->nem.s.Hypercall.QueryCpuTick.uAux);
     2286    }
     2287    return rc;
     2288}
     2289
     2290
     2291/**
     2292 * Worker for NEMR0ResumeCpuTickOnAll and the ring-0 NEMHCResumeCpuTickOnAll.
     2293 *
     2294 * @returns VBox status code.
     2295 * @param   pGVM            The ring-0 VM handle.
     2296 * @param   pGVCpu          The ring-0 VCPU handle.
     2297 * @param   uPausedTscValue The TSC value at the time of pausing.
     2298 */
     2299NEM_TMPL_STATIC int nemR0WinResumeCpuTickOnAll(PGVM pGVM, PGVMCPU pGVCpu, uint64_t uPausedTscValue)
     2300{
     2301    AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
     2302
     2303    /*
     2304     * Set up the hypercall parameters.
     2305     */
     2306    HV_INPUT_SET_VP_REGISTERS *pInput = (HV_INPUT_SET_VP_REGISTERS *)pGVCpu->nem.s.HypercallData.pbPage;
     2307    AssertPtrReturn(pInput, VERR_INTERNAL_ERROR_3);
     2308
     2309    pInput->PartitionId = pGVM->nem.s.idHvPartition;
     2310    pInput->VpIndex     = 0;
     2311    pInput->RsvdZ       = 0;
     2312    pInput->Elements[0].Name  = HvX64RegisterTsc;
     2313    pInput->Elements[0].Pad0  = 0;
     2314    pInput->Elements[0].Pad1  = 0;
     2315    pInput->Elements[0].Value.Reg128.High64 = 0;
     2316    pInput->Elements[0].Value.Reg64 = uPausedTscValue;
     2317
     2318    /*
     2319     * Disable interrupts and do the first virtual CPU.
     2320     */
     2321    RTCCINTREG const fSavedFlags = ASMIntDisableFlags();
     2322    uint64_t const   uFirstTsc   = ASMReadTSC();
     2323    uint64_t uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallSetVpRegisters, 1),
     2324                                               pGVCpu->nem.s.HypercallData.HCPhysPage, 0 /* no output */);
     2325    AssertLogRelMsgReturnStmt(uResult == HV_MAKE_CALL_REP_RET(1), ("uResult=%RX64 uTsc=%#RX64\n", uResult, uPausedTscValue),
     2326                              ASMSetFlags(fSavedFlags), VERR_NEM_SET_TSC);
     2327
     2328    /*
     2329     * Do secondary processors, adjusting for elapsed TSC and keeping finger crossed
     2330     * that we don't introduce too much drift here.
     2331     */
     2332    for (VMCPUID iCpu = 1; iCpu < pGVM->cCpus; iCpu++)
     2333    {
     2334        Assert(pInput->PartitionId == pGVM->nem.s.idHvPartition);
     2335        Assert(pInput->RsvdZ       == 0);
     2336        Assert(pInput->Elements[0].Name == HvX64RegisterTsc);
     2337        Assert(pInput->Elements[0].Pad0 == 0);
     2338        Assert(pInput->Elements[0].Pad1 == 0);
     2339        Assert(pInput->Elements[0].Value.Reg128.High64 == 0);
     2340
     2341        pInput->VpIndex = iCpu;
     2342        const uint64_t offDelta = (ASMReadTSC() - uFirstTsc);
     2343        pInput->Elements[0].Value.Reg64 = uPausedTscValue + offDelta;
     2344
     2345        uResult = g_pfnHvlInvokeHypercall(HV_MAKE_CALL_INFO(HvCallSetVpRegisters, 1),
     2346                                          pGVCpu->nem.s.HypercallData.HCPhysPage, 0 /* no output */);
     2347        AssertLogRelMsgReturnStmt(uResult == HV_MAKE_CALL_REP_RET(1),
     2348                                  ("uResult=%RX64 uTsc=%#RX64 + %#RX64\n", uResult, uPausedTscValue, offDelta),
     2349                                  ASMSetFlags(fSavedFlags), VERR_NEM_SET_TSC);
     2350    }
     2351
     2352    /*
     2353     * Done.
     2354     */
     2355    ASMSetFlags(fSavedFlags);
     2356    return VINF_SUCCESS;
     2357}
     2358
     2359
     2360/**
     2361 * Sets the TSC register to @a uPausedTscValue on all CPUs.
     2362 *
     2363 * @returns VBox status code
     2364 * @param   pGVM            The ring-0 VM handle.
     2365 * @param   pVM             The cross context VM handle.
     2366 * @param   idCpu           The calling EMT.  Necessary for getting the
     2367 *                          hypercall page and arguments.
     2368 * @param   uPausedTscValue The TSC value at the time of pausing.
     2369 */
     2370VMMR0_INT_DECL(int) NEMR0ResumeCpuTickOnAll(PGVM pGVM, PVM pVM, VMCPUID idCpu, uint64_t uPausedTscValue)
     2371{
     2372    /*
     2373     * Validate the call.
     2374     */
     2375    int rc = GVMMR0ValidateGVMandVMandEMT(pGVM, pVM, idCpu);
     2376    if (RT_SUCCESS(rc))
     2377    {
     2378        PVMCPU  pVCpu  = &pVM->aCpus[idCpu];
     2379        PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
     2380        AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
     2381
     2382        /*
     2383         * Call worker.
     2384         */
     2385        pVCpu->nem.s.Hypercall.QueryCpuTick.cTicks = 0;
     2386        pVCpu->nem.s.Hypercall.QueryCpuTick.uAux   = 0;
     2387        rc = nemR0WinResumeCpuTickOnAll(pGVM, pGVCpu, uPausedTscValue);
    22822388    }
    22832389    return rc;
     
    23872493    if (RT_SUCCESS(rc))
    23882494    {
    2389         AssertPtrReturn(g_pfnHvlInvokeHypercall, VERR_INTERNAL_ERROR_3);
     2495        AssertReturn(g_pfnHvlInvokeHypercall, VERR_NEM_MISSING_KERNEL_API);
    23902496
    23912497        PGVMCPU pGVCpu = &pGVM->aCpus[idCpu];
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r72541 r72546  
    20702070            break;
    20712071
     2072        case VMMR0_DO_NEM_RESUME_CPU_TICK_ON_ALL:
     2073            if (pReqHdr || idCpu == NIL_VMCPUID)
     2074                return VERR_INVALID_PARAMETER;
     2075            rc = NEMR0ResumeCpuTickOnAll(pGVM, pVM, idCpu, u64Arg);
     2076            VMM_CHECK_SMAP_CHECK2(pVM, RT_NOTHING);
     2077            break;
     2078
    20722079        case VMMR0_DO_NEM_UPDATE_STATISTICS:
    20732080            if (u64Arg || pReqHdr)
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