VirtualBox

Changeset 108388 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Feb 26, 2025 10:15:12 AM (2 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167752
Message:

VMM/NEMR3Native-win-armv8.cpp: Implement NEMHcQueryCpuTick() and NEMHCResumeCpuTickOnAll() for proper suspend resume handling, bugref:10392

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win-armv8.cpp

    r108386 r108388  
    196196static decltype(WHvGetVirtualProcessorRegisters) *  g_pfnWHvGetVirtualProcessorRegisters;
    197197static decltype(WHvSetVirtualProcessorRegisters) *  g_pfnWHvSetVirtualProcessorRegisters;
     198static decltype(WHvSuspendPartitionTime) *          g_pfnWHvSuspendPartitionTime;
     199static decltype(WHvResumePartitionTime) *           g_pfnWHvResumePartitionTime;
     200
    198201//static decltype(WHvGetVirtualProcessorState) *      g_pfnWHvGetVirtualProcessorState;
    199202decltype(WHvRequestInterrupt) *                     g_pfnWHvRequestInterrupt;
     
    233236    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorRegisters),
    234237    NEM_WIN_IMPORT(0, false, WHvSetVirtualProcessorRegisters),
     238    NEM_WIN_IMPORT(0, false, WHvSuspendPartitionTime),
     239    NEM_WIN_IMPORT(0, false, WHvResumePartitionTime),
    235240//    NEM_WIN_IMPORT(0, false, WHvGetVirtualProcessorState),
    236241    NEM_WIN_IMPORT(0, false, WHvRequestInterrupt),
     
    260265# define WHvGetVirtualProcessorRegisters            g_pfnWHvGetVirtualProcessorRegisters
    261266# define WHvSetVirtualProcessorRegisters            g_pfnWHvSetVirtualProcessorRegisters
     267# define WHvSuspendPartitionTime                    g_pfnWHvSuspendPartitionTime
     268# define WHvResumePartitionTime                     g_pfnWHvResumePartitionTime
    262269//# define WHvGetVirtualProcessorState                g_pfnWHvGetVirtualProcessorState
    263270# define WHvRequestInterrupt                        g_pfnWHvRequestInterrupt
    264 
    265 # define VidMessageSlotHandleAndGetNext             g_pfnVidMessageSlotHandleAndGetNext
    266 # define VidStartVirtualProcessor                   g_pfnVidStartVirtualProcessor
    267 # define VidStopVirtualProcessor                    g_pfnVidStopVirtualProcessor
    268 
    269271#endif
    270272
     
    17591761    AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9);
    17601762
    1761 #pragma message("NEMHCQueryCpuTick: Implement it!")
    1762 #if 0 /** @todo */
    17631763    /* Call the offical API. */
    1764     WHV_REGISTER_NAME  aenmNames[2] = { WHvX64RegisterTsc, WHvX64RegisterTscAux };
    1765     WHV_REGISTER_VALUE aValues[2]   = { { {0, 0} }, { {0, 0} } };
    1766     Assert(RT_ELEMENTS(aenmNames) == RT_ELEMENTS(aValues));
    1767     HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, aenmNames, 2, aValues);
     1764    WHV_REGISTER_NAME  enmName = WHvArm64RegisterCntvctEl0;
     1765    WHV_REGISTER_VALUE Value   = { { {0, 0} } };
     1766    HRESULT hrc = WHvGetVirtualProcessorRegisters(pVM->nem.s.hPartition, pVCpu->idCpu, &enmName, 1, &Value);
    17681767    AssertLogRelMsgReturn(SUCCEEDED(hrc),
    1769                           ("WHvGetVirtualProcessorRegisters(%p, %u,{tsc,tsc_aux},2,) -> %Rhrc (Last=%#x/%u)\n",
     1768                          ("WHvGetVirtualProcessorRegisters(%p, %u,{CNTVCT_EL0},1,) -> %Rhrc (Last=%#x/%u)\n",
    17701769                           pVM->nem.s.hPartition, pVCpu->idCpu, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
    17711770                          , VERR_NEM_GET_REGISTERS_FAILED);
    1772     *pcTicks = aValues[0].Reg64;
     1771    *pcTicks = Value.Reg64;
    17731772    if (puAux)
    1774         *puAux = pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_TSC_AUX ? aValues[1].Reg64 : CPUMGetGuestTscAux(pVCpu);
    1775 #else
    1776     RT_NOREF(pVCpu, pcTicks, puAux);
    1777 #endif
     1773        *puAux =0;
     1774
    17781775    return VINF_SUCCESS;
    17791776}
     
    17981795     * Call the offical API to do the job.
    17991796     */
    1800     if (pVM->cCpus > 1)
    1801         RTThreadYield(); /* Try decrease the chance that we get rescheduled in the middle. */
    1802 
    1803 #pragma message("NEMHCResumeCpuTickOnAll: Implement it!")
    1804 #if 0 /** @todo */
    1805     /* Start with the first CPU. */
    1806     WHV_REGISTER_NAME  enmName   = WHvX64RegisterTsc;
    1807     WHV_REGISTER_VALUE Value     = { {0, 0} };
    1808     Value.Reg64 = uPausedTscValue;
    1809     uint64_t const     uFirstTsc = ASMReadTSC();
    1810     HRESULT hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, 0 /*iCpu*/, &enmName, 1, &Value);
     1797    /* Ensure time for the partition is suspended - it will be resumed as soon as a vCPU starts executing. */
     1798    HRESULT hrc = WHvSuspendPartitionTime(pVM->nem.s.hPartition);
    18111799    AssertLogRelMsgReturn(SUCCEEDED(hrc),
    1812                           ("WHvSetVirtualProcessorRegisters(%p, 0,{tsc},2,%#RX64) -> %Rhrc (Last=%#x/%u)\n",
    1813                            pVM->nem.s.hPartition, uPausedTscValue, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     1800                          ("WHvSuspendPartitionTime(%p) -> %Rhrc (Last=%#x/%u)\n",
     1801                           pVM->nem.s.hPartition, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
    18141802                          , VERR_NEM_SET_TSC);
    18151803
    1816     /* Do the other CPUs, adjusting for elapsed TSC and keeping finger crossed
    1817        that we don't introduce too much drift here. */
    1818     for (VMCPUID iCpu = 1; iCpu < pVM->cCpus; iCpu++)
    1819     {
    1820         Assert(enmName == WHvX64RegisterTsc);
    1821         const uint64_t offDelta = (ASMReadTSC() - uFirstTsc);
    1822         Value.Reg64 = uPausedTscValue + offDelta;
    1823         hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, iCpu, &enmName, 1, &Value);
     1804    /*
     1805     * Now set the CNTVCT_EL0 register for each vCPU, Hyper-V will program the timer offset in
     1806     * CNTVOFF_EL2 accordingly. ARM guarantees that CNTVCT_EL0 is synchronised across all CPUs,
     1807     * as long as CNTVOFF_EL2 is the same everywhere. Lets just hope scheduling will not affect it
     1808     * if the partition time is suspended.
     1809     */
     1810    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     1811    {
     1812        WHV_REGISTER_NAME enmName = WHvArm64RegisterCntvctEl0;
     1813        WHV_REGISTER_VALUE Value;
     1814        Value.Reg64 = uPausedTscValue;
     1815        hrc = WHvSetVirtualProcessorRegisters(pVM->nem.s.hPartition, idCpu, &enmName, 1, &Value);
    18241816        AssertLogRelMsgReturn(SUCCEEDED(hrc),
    1825                               ("WHvSetVirtualProcessorRegisters(%p, 0,{tsc},2,%#RX64 + %#RX64) -> %Rhrc (Last=%#x/%u)\n",
    1826                                pVM->nem.s.hPartition, iCpu, uPausedTscValue, offDelta, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
     1817                              ("WHvSetVirtualProcessorRegisters(%p, 0,{CNTVCT_EL0},1,%#RX64) -> %Rhrc (Last=%#x/%u)\n",
     1818                               pVM->nem.s.hPartition, idCpu, uPausedTscValue, hrc, RTNtLastStatusValue(), RTNtLastErrorValue())
    18271819                              , VERR_NEM_SET_TSC);
    18281820    }
    1829 #else
    1830     RT_NOREF(uPausedTscValue);
    1831 #endif
    18321821
    18331822    return VINF_SUCCESS;
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