VirtualBox

Changeset 70056 in vbox


Ignore:
Timestamp:
Dec 11, 2017 2:40:02 PM (7 years ago)
Author:
vboxsync
Message:

VMM: Nested hw.virt: Apply nested-guest TSC offset when executing the nested-guest.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpum.h

    r70000 r70056  
    12081208VMM_INT_DECL(void)      CPUMSvmVmExitRestoreHostState(PVMCPU pVCpu, PCPUMCTX pCtx);
    12091209VMM_INT_DECL(void)      CPUMSvmVmRunSaveHostState(PCPUMCTX pCtx, uint8_t cbInstr);
     1210VMM_INT_DECL(uint64_t)  CPUMApplyNestedGuestTscOffset(PVMCPU pVCpu, uint64_t uTicks);
    12101211/** @} */
    12111212
  • trunk/include/VBox/vmm/hm_svm.h

    r70000 r70056  
    991991    /** Cache of MSRPM nested-guest physical address. */
    992992    uint64_t            u64MSRPMPhysAddr;
     993    /** Cache of the TSC offset. */
     994    uint64_t            u64TSCOffset;
    993995    /** Cache of the VMCB clean bits. */
    994996    uint64_t            u64VmcbCleanBits;
  • trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp

    r69216 r70056  
    184184    RT_NOREF_PV(pVCpu); RT_NOREF_PV(idMsr); RT_NOREF_PV(pRange);
    185185    *puValue = TMCpuTickGet(pVCpu);
     186#ifdef VBOX_WITH_NESTED_HWVIRT
     187    *puValue = CPUMApplyNestedGuestTscOffset(pVCpu, *puValue);
     188#endif
    186189    return VINF_SUCCESS;
    187190}
     
    342345     *        what we want? */
    343346    *puValue = TMCpuTickGet(pVCpu);
     347#ifdef VBOX_WITH_NESTED_HWVIRT
     348    *puValue = CPUMApplyNestedGuestTscOffset(pVCpu, *puValue);
     349#endif
    344350    return VINF_SUCCESS;
    345351}
     
    362368     *        what we want? */
    363369    *puValue = TMCpuTickGet(pVCpu);
     370#ifdef VBOX_WITH_NESTED_HWVIRT
     371    *puValue = CPUMApplyNestedGuestTscOffset(pVCpu, *puValue);
     372#endif
    364373    return VINF_SUCCESS;
    365374}
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r70000 r70056  
    26952695}
    26962696
     2697
     2698/**
     2699 * Applies the TSC offset of a nested-guest if any and returns the new TSC
     2700 * value for the guest.
     2701 *
     2702 * @returns The TSC offset after applying any nested-guest TSC offset.
     2703 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
     2704 * @param   uTicks      The guest TSC.
     2705 */
     2706VMM_INT_DECL(uint64_t) CPUMApplyNestedGuestTscOffset(PVMCPU pVCpu, uint64_t uTicks)
     2707{
     2708#ifndef IN_RC
     2709    PCCPUMCTX pCtx  = &pVCpu->cpum.s.Guest;
     2710    if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
     2711    {
     2712        PCSVMVMCB pVmcb = pCtx->hwvirt.svm.CTX_SUFF(pVmcb);
     2713        return uTicks + pVmcb->ctrl.u64TSCOffset;
     2714    }
     2715
     2716    /** @todo Intel. */
     2717#else
     2718    RT_NOREF(pVCpu);
     2719#endif
     2720    return uTicks;
     2721}
     2722
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r69111 r70056  
    13151315
    13161316    uint64_t uTicks = TMCpuTickGet(pVCpu);
     1317#ifdef VBOX_WITH_NESTED_HWVIRT
     1318    uTicks = CPUMApplyNestedGuestTscOffset(pVCpu, uTicks);
     1319#endif
    13171320
    13181321    /* Same behaviour in 32 & 64 bits mode */
     
    13511354
    13521355    uint64_t uTicks = TMCpuTickGet(pVCpu);
     1356#ifdef VBOX_WITH_NESTED_HWVIRT
     1357    uTicks = CPUMApplyNestedGuestTscOffset(pVCpu, uTicks);
     1358#endif
    13531359
    13541360    /* Same behaviour in 32 & 64 bits mode */
  • trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp

    r70020 r70056  
    366366        pVmcbNstGstCtrl->u64IOPMPhysAddr          = pNstGstVmcbCache->u64IOPMPhysAddr;
    367367        pVmcbNstGstCtrl->u64MSRPMPhysAddr         = pNstGstVmcbCache->u64MSRPMPhysAddr;
     368        pVmcbNstGstCtrl->u64TSCOffset             = pNstGstVmcbCache->u64TSCOffset;
    368369        pVmcbNstGstCtrl->IntCtrl.n.u1VIntrMasking = pNstGstVmcbCache->fVIntrMasking;
    369370        pVmcbNstGstCtrl->TLBCtrl                  = pNstGstVmcbCache->TLBCtrl;
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r70006 r70056  
    21562156        pNstGstVmcbCache->u64IOPMPhysAddr   = pVmcbNstGstCtrl->u64IOPMPhysAddr;
    21572157        pNstGstVmcbCache->u64MSRPMPhysAddr  = pVmcbNstGstCtrl->u64MSRPMPhysAddr;
     2158        pNstGstVmcbCache->u64TSCOffset      = pVmcbNstGstCtrl->u64TSCOffset;
    21582159        pNstGstVmcbCache->u64VmcbCleanBits  = pVmcbNstGstCtrl->u64VmcbCleanBits;
    21592160        pNstGstVmcbCache->fVIntrMasking     = pVmcbNstGstCtrl->IntCtrl.n.u1VIntrMasking;
     
    27072708    return rcExit;
    27082709}
     2710
     2711
     2712#ifdef VBOX_WITH_NESTED_HWVIRT
     2713/**
     2714 * Updates the use of TSC offsetting mode for the CPU and adjusts the necessary
     2715 * intercepts for the nested-guest.
     2716 *
     2717 * @param   pVM             The cross context VM structure.
     2718 * @param   pVCpu           The cross context virtual CPU structure.
     2719 * @param   pCtx            Pointer to the nested guest-CPU context.
     2720 * @param   pVmcbNstGst     Pointer to the nested-guest VM control block.
     2721 *
     2722 * @remarks No-long-jump zone!!!
     2723 */
     2724static void hmR0SvmUpdateTscOffsettingNested(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, PSVMVMCB pVmcbNstGst)
     2725{
     2726    Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx));
     2727
     2728    bool                 fParavirtTsc;
     2729    uint64_t             uTscOffset;
     2730    bool fCanUseRealTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
     2731
     2732    PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
     2733    PSVMVMCBCTRL         pVmcbNstGstCtrl  = &pVmcbNstGst->ctrl;
     2734
     2735    /*
     2736     * Only avoid intercepting if we determined the host TSC (++) is stable enough
     2737     * to not intercept -and- the nested-hypervisor itself does not want to intercept it.
     2738     */
     2739    if (    fCanUseRealTsc
     2740        && !(pVmcbNstGstCache->u64InterceptCtrl & (SVM_CTRL_INTERCEPT_RDTSC | SVM_CTRL_INTERCEPT_RDTSCP)))
     2741    {
     2742        pVmcbNstGstCtrl->u64InterceptCtrl &= ~SVM_CTRL_INTERCEPT_RDTSC;
     2743        pVmcbNstGstCtrl->u64InterceptCtrl &= ~SVM_CTRL_INTERCEPT_RDTSCP;
     2744        STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
     2745    }
     2746    else
     2747    {
     2748        pVmcbNstGstCtrl->u64InterceptCtrl |= SVM_CTRL_INTERCEPT_RDTSC;
     2749        pVmcbNstGstCtrl->u64InterceptCtrl |= SVM_CTRL_INTERCEPT_RDTSCP;
     2750        STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
     2751    }
     2752
     2753    /* Apply the nested-guest VMCB's TSC offset over the guest one. */
     2754    uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
     2755
     2756    /* Update the nested-guest VMCB with the combined TSC offset (of guest and nested-guest). */
     2757    pVmcbNstGstCtrl->u64TSCOffset = uTscOffset;
     2758
     2759    /* Finally update the VMCB clean bits since we touched the intercepts as well as the TSC offset. */
     2760    pVmcbNstGstCtrl->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS;
     2761
     2762    if (fParavirtTsc)
     2763    {
     2764        /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
     2765           information before every VM-entry, hence disable it for performance sake. */
     2766        STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
     2767    }
     2768}
     2769#endif
    27092770
    27102771
     
    39604021        || idCurrentCpu != pVCpu->hm.s.idLastCpu)
    39614022    {
    3962         hmR0SvmUpdateTscOffsetting(pVM, pVCpu, pVmcbNstGst);
     4023        hmR0SvmUpdateTscOffsettingNested(pVM, pVCpu, pCtx, pVmcbNstGst);
    39634024        pSvmTransient->fUpdateTscOffsetting = false;
    39644025    }
     
    42134274
    42144275    /* TSC read must be done early for maximum accuracy. */
    4215     PSVMVMCB     pVmcbNstGst     = pMixedCtx->hwvirt.svm.CTX_SUFF(pVmcb);
    4216     PSVMVMCBCTRL pVmcbNstGstCtrl = &pVmcbNstGst->ctrl;
     4276    PSVMVMCB             pVmcbNstGst     = pMixedCtx->hwvirt.svm.CTX_SUFF(pVmcb);
     4277    PSVMVMCBCTRL         pVmcbNstGstCtrl = &pVmcbNstGst->ctrl;
     4278    PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
    42174279    if (!(pVmcbNstGstCtrl->u64InterceptCtrl & SVM_CTRL_INTERCEPT_RDTSC))
    4218         TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVmcbNstGstCtrl->u64TSCOffset);
     4280    {
     4281        /*
     4282         * Undo what we did in hmR0SvmUpdateTscOffsettingNested() but don't restore the
     4283         * nested-guest VMCB TSC offset here. It shall eventually be restored on #VMEXIT
     4284         * later by HMSvmNstGstVmExitNotify().
     4285         */
     4286        TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVmcbNstGstCtrl->u64TSCOffset - pVmcbNstGstCache->u64TSCOffset);
     4287    }
    42194288
    42204289    if (pSvmTransient->fRestoreTscAuxMsr)
Note: See TracChangeset for help on using the changeset viewer.

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