VirtualBox

Changeset 99976 in vbox


Ignore:
Timestamp:
May 25, 2023 11:44:00 AM (18 months ago)
Author:
vboxsync
Message:

VMM/NEMR3Native-darwin-armv8: Set the vTimer offset to account for suspending VMs, bugref:10387 bugref:10390

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpumctx-armv8.h

    r99956 r99976  
    165165    uint64_t        fExtrn;
    166166
    167     uint64_t        au64Padding2[1];
     167    /** The CNTV_CTL_EL0 register, always synced during VM-exit. */
     168    uint64_t        CntvCtlEl0;
     169    /** The CNTV_CVAL_EL0 register, always synced during VM-exit. */
     170    uint64_t        CntvCValEl0;
     171
     172    uint64_t        au64Padding2[7];
    168173} CPUMCTX;
    169174
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin-armv8.cpp

    r99888 r99976  
    5050#include <iprt/armv8.h>
    5151#include <iprt/asm.h>
     52#include <iprt/asm-arm.h>
    5253#include <iprt/ldr.h>
    5354#include <iprt/mem.h>
     
    443444{
    444445    RT_NOREF(pVM);
    445     hv_return_t hrc = HV_SUCCESS;
    446 
    447     if (fWhat & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_PC | CPUMCTX_EXTRN_FPCR | CPUMCTX_EXTRN_FPSR))
     446
     447    hv_return_t hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CTL_EL0, &pVCpu->cpum.GstCtx.CntvCtlEl0);
     448    if (hrc == HV_SUCCESS)
     449        hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CVAL_EL0, &pVCpu->cpum.GstCtx.CntvCValEl0);
     450
     451    if (   hrc == HV_SUCCESS
     452        && (fWhat & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_PC | CPUMCTX_EXTRN_FPCR | CPUMCTX_EXTRN_FPSR)))
    448453    {
    449454        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumRegs); i++)
     
    595600    if (hrc == HV_SUCCESS)
    596601    {
    597         pVM->nem.s.fCreatedVm = true;
     602        pVM->nem.s.fCreatedVm  = true;
     603        pVM->nem.s.u64CntFrqHz = ASMReadCntFrqEl0();
    598604        VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API);
    599605        Log(("NEM: Marked active!\n"));
     
    632638        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
    633639                          "Call to hv_vcpu_create failed on vCPU %u: %#x (%Rrc)", idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
     640
     641    /* Set the vTiemr offset so all vCpus start at (nearly) 0. */
     642    pVCpu->nem.s.u64VTimerOff = ASMReadTSC();
     643
     644    hrc = hv_vcpu_set_vtimer_offset(pVCpu->nem.s.hVCpu, pVCpu->nem.s.u64VTimerOff);
     645    AssertLogRelMsg(hrc == HV_SUCCESS, ("vCPU#%u: Failed to set vTimer offset to %#RX64 -> hrc = %#x\n",
     646                                        pVCpu->idCpu, pVCpu->nem.s.u64VTimerOff, hrc));
    634647
    635648    if (idCpu == 0)
     
    11871200     * everything every time.  This will be optimized later.
    11881201     */
     1202
     1203    /* Update the vTimer offset after resuming if instructed. */
     1204    if (pVCpu->nem.s.fVTimerOffUpdate)
     1205    {
     1206        /*
     1207         * Program the new offset, first get the new TSC value with the old vTimer offset and then adjust the
     1208         * the new offset to let the guest not notice the pause.
     1209         */
     1210        uint64_t u64TscNew = ASMReadTSC() - pVCpu->nem.s.u64VTimerOff;
     1211        Assert(u64TscNew >= pVM->nem.s.u64VTimerValuePaused);
     1212        pVCpu->nem.s.u64VTimerOff += u64TscNew - pVM->nem.s.u64VTimerValuePaused;
     1213        hv_return_t hrc = hv_vcpu_set_vtimer_offset(pVCpu->nem.s.hVCpu, pVCpu->nem.s.u64VTimerOff);
     1214        if (hrc != HV_SUCCESS)
     1215            return nemR3DarwinHvSts2Rc(hrc);
     1216
     1217        pVCpu->nem.s.fVTimerOffUpdate = false;
     1218    }
    11891219
    11901220    /*
     
    16671697    STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatQueryCpuTick);
    16681698
    1669     AssertReleaseFailed();
    1670     return VERR_NOT_IMPLEMENTED;
     1699    if (puAux)
     1700        *puAux = 0;
     1701    *pcTicks = ASMReadTSC() - pVCpu->nem.s.u64VTimerOff; /* This is the host timer minus the offset. */
     1702    return VINF_SUCCESS;
    16711703}
    16721704
     
    16881720    AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9);
    16891721
    1690     //AssertReleaseFailed();
     1722    pVM->nem.s.u64VTimerValuePaused = uPausedTscValue;
     1723
     1724    /*
     1725     * Set the flag to update the vTimer offset when the vCPU resumes for the first time
     1726     * (needs to be done on the actual EMT).
     1727     */
     1728    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     1729    {
     1730        PVMCPUCC pVCpuDst = pVM->apCpusR3[idCpu];
     1731        pVCpuDst->nem.s.fVTimerOffUpdate = true;
     1732    }
     1733
    16911734    return VINF_SUCCESS;
    16921735}
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r99735 r99976  
    287287    bool                        fCreatedVm   : 1;
    288288# if defined(VBOX_VMM_TARGET_ARMV8)
    289     /** @todo */
     289    /** @name vTimer related state.
     290     * @{ */
     291    /** The counter frequency in Hz as obtained from CNTFRQ_EL0. */
     292    uint64_t                    u64CntFrqHz;
     293    /** The CNTVCT_EL0 value after the VM was resumed. */
     294    uint64_t                    u64VTimerValuePaused;
     295    /** @} */
    290296# else
    291297    /** Set if hv_vm_space_create() was called successfully. */
     
    485491    /** Flag whether the vTimer got activated and is masked. */
    486492    bool                        fVTimerActivated;
     493    /** Flag whether to update the vTimer offset. */
     494    bool                        fVTimerOffUpdate;
     495    /** The vTimer offset programmed. */
     496    uint64_t                    u64VTimerOff;
    487497# else
    488498    /** The vCPU handle associated with the EMT executing this vCPU. */
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