VirtualBox

Changeset 100102 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Jun 7, 2023 5:54:44 PM (20 months ago)
Author:
vboxsync
Message:

VMM/NEMR3Native-darwin-armv8: Some basic PSCI implementation required to boot secondary CPUs + fixes the vTimer offset implementation for SMP support, bugref:10454, bugref:10390

File:
1 edited

Legend:

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

    r100076 r100102  
    4646#include "NEMInternal.h"
    4747#include <VBox/vmm/vmcc.h>
     48#include <VBox/vmm/vmm.h>
    4849#include "dtrace/VBoxVMM.h"
    4950
     
    5859#include <iprt/system.h>
    5960#include <iprt/utf16.h>
     61
     62#include <iprt/formats/arm-psci.h>
    6063
    6164#include <mach/mach_time.h>
     
    603606        pVM->nem.s.fCreatedVm  = true;
    604607        pVM->nem.s.u64CntFrqHz = ASMReadCntFrqEl0();
     608
     609        /* Will be initialized in NEMHCResumeCpuTickOnAll() before executing guest code. */
     610        pVM->nem.s.u64VTimerOff = 0;
     611
    605612        VM_SET_MAIN_EXECUTION_ENGINE(pVM, VM_EXEC_ENGINE_NATIVE_API);
    606613        Log(("NEM: Marked active!\n"));
     
    640647                          "Call to hv_vcpu_create failed on vCPU %u: %#x (%Rrc)", idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
    641648
    642     /* Will be initialized in NEMHCResumeCpuTickOnAll() before executing guest code. */
    643     pVCpu->nem.s.u64VTimerOff = 0;
     649    hrc = hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_MPIDR_EL1, idCpu);
     650    if (hrc != HV_SUCCESS)
     651        return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     652                          "Setting MPIDR_EL1 failed on vCPU %u: %#x (%Rrc)", idCpu, hrc, nemR3DarwinHvSts2Rc(hrc));
    644653
    645654    if (idCpu == 0)
     
    9971006    RT_NOREF(pVM);
    9981007    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    999     /** @todo Raise exception to EL1 if PSCI not configured. */
    1000     /** @todo Need a generic mechanism here to pass this to, GIM maybe?. Always return -1 for now (PSCI). */
    1001     nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, true /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)-1);
     1008    if (u16Imm == 0)
     1009    {
     1010        /** @todo Raise exception to EL1 if PSCI not configured. */
     1011        /** @todo Need a generic mechanism here to pass this to, GIM maybe?. */
     1012        uint32_t uFunId = pVCpu->cpum.GstCtx.aGRegs[ARMV8_AARCH64_REG_X0].w;
     1013        bool fHvc64 = RT_BOOL(uFunId & ARM_SMCCC_FUNC_ID_64BIT); RT_NOREF(fHvc64);
     1014        uint32_t uEntity = ARM_SMCCC_FUNC_ID_ENTITY_GET(uFunId);
     1015        uint32_t uFunNum = ARM_SMCCC_FUNC_ID_NUM_GET(uFunId);
     1016        if (uEntity == ARM_SMCCC_FUNC_ID_ENTITY_STD_SEC_SERVICE)
     1017        {
     1018            switch (uFunNum)
     1019            {
     1020                case ARM_PSCI_FUNC_ID_PSCI_VERSION:
     1021                    nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_FUNC_ID_PSCI_VERSION_SET(1, 2));
     1022                    break;
     1023                case ARM_PSCI_FUNC_ID_SYSTEM_OFF:
     1024                    rcStrict = VINF_EM_OFF;
     1025                    break;
     1026                case ARM_PSCI_FUNC_ID_SYSTEM_RESET:
     1027                    rcStrict = VINF_EM_RESET;
     1028                    break;
     1029                case ARM_PSCI_FUNC_ID_CPU_ON:
     1030                {
     1031                    uint64_t u64TgtCpu      = nemR3DarwinGetGReg(pVCpu, ARMV8_AARCH64_REG_X1);
     1032                    RTGCPHYS GCPhysExecAddr = nemR3DarwinGetGReg(pVCpu, ARMV8_AARCH64_REG_X2);
     1033                    uint64_t u64CtxId       = nemR3DarwinGetGReg(pVCpu, ARMV8_AARCH64_REG_X3);
     1034                    VMMR3CpuOn(pVM, u64TgtCpu & 0xff, GCPhysExecAddr, u64CtxId);
     1035                    nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, true /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_STS_SUCCESS);
     1036                    break;
     1037                }
     1038                default:
     1039                    nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
     1040            }
     1041        }
     1042        else
     1043            nemR3DarwinSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
     1044    }
     1045    /** @todo What to do if immediate is != 0? */
    10021046
    10031047    return rcStrict;
     
    10421086                && !(pVCpu->cpum.GstCtx.CntvCtlEl0 & ARMV8_CNTV_CTL_EL0_AARCH64_IMASK))
    10431087            {
    1044                 uint64_t cTicksVTimer = ASMReadTSC() - pVCpu->nem.s.u64VTimerOff;
     1088                uint64_t cTicksVTimer = mach_absolute_time() - pVM->nem.s.u64VTimerOff;
    10451089
    10461090                /* Check whether it expired and start executing guest code. */
     
    10571101                 * between CPU load when the guest is idle and performance).
    10581102                 */
    1059                 if (cNanoSecsVTimerToExpire < 5 * RT_NS_1MS)
     1103                if (cNanoSecsVTimerToExpire < 2 * RT_NS_1MS)
    10601104                    return VINF_SUCCESS;
    10611105
    10621106                LogFlowFunc(("Set vTimer activation to cNanoSecsVTimerToExpire=%#RX64 (CntvCValEl0=%#RX64, u64VTimerOff=%#RX64 cTicksVTimer=%#RX64 u64CntFrqHz=%#RX64)\n",
    1063                              cNanoSecsVTimerToExpire, pVCpu->cpum.GstCtx.CntvCValEl0, pVCpu->nem.s.u64VTimerOff, cTicksVTimer, pVM->nem.s.u64CntFrqHz));
     1107                             cNanoSecsVTimerToExpire, pVCpu->cpum.GstCtx.CntvCValEl0, pVM->nem.s.u64VTimerOff, cTicksVTimer, pVM->nem.s.u64CntFrqHz));
    10641108                TMCpuSetVTimerNextActivation(pVCpu, cNanoSecsVTimerToExpire);
    10651109            }
     
    12401284    if (pVCpu->nem.s.fVTimerOffUpdate)
    12411285    {
    1242         /*
    1243          * Program the new offset, first get the new TSC value with the old vTimer offset and then adjust the
    1244          * the new offset to let the guest not notice the pause.
    1245          */
    1246         uint64_t u64TscNew = mach_absolute_time() - pVCpu->nem.s.u64VTimerOff;
    1247         Assert(u64TscNew >= pVM->nem.s.u64VTimerValuePaused);
    1248         LogFlowFunc(("u64VTimerOffOld=%#RX64 u64TscNew=%#RX64 u64VTimerValuePaused=%#RX64 -> u64VTimerOff=%#RX64\n",
    1249                      pVCpu->nem.s.u64VTimerOff, u64TscNew, pVM->nem.s.u64VTimerValuePaused,
    1250                      pVCpu->nem.s.u64VTimerOff + (u64TscNew - pVM->nem.s.u64VTimerValuePaused)));
    1251 
    1252         pVCpu->nem.s.u64VTimerOff += u64TscNew - pVM->nem.s.u64VTimerValuePaused;
    1253         hv_return_t hrc = hv_vcpu_set_vtimer_offset(pVCpu->nem.s.hVCpu, pVCpu->nem.s.u64VTimerOff);
     1286        hv_return_t hrc = hv_vcpu_set_vtimer_offset(pVCpu->nem.s.hVCpu, pVM->nem.s.u64VTimerOff);
    12541287        if (hrc != HV_SUCCESS)
    12551288            return nemR3DarwinHvSts2Rc(hrc);
     
    17391772    if (puAux)
    17401773        *puAux = 0;
    1741     *pcTicks = mach_absolute_time() - pVCpu->nem.s.u64VTimerOff; /* This is the host timer minus the offset. */
     1774    *pcTicks = mach_absolute_time() - pVCpu->pVMR3->nem.s.u64VTimerOff; /* This is the host timer minus the offset. */
    17421775    return VINF_SUCCESS;
    17431776}
     
    17601793    AssertReturn(VM_IS_NEM_ENABLED(pVM), VERR_NEM_IPE_9);
    17611794
    1762     pVM->nem.s.u64VTimerValuePaused = uPausedTscValue;
     1795    /*
     1796     * Calculate the new offset, first get the new TSC value with the old vTimer offset and then adjust the
     1797     * the new offset to let the guest not notice the pause.
     1798     */
     1799    uint64_t u64TscNew = mach_absolute_time() - pVCpu->pVMR3->nem.s.u64VTimerOff;
     1800    Assert(u64TscNew >= uPausedTscValue);
     1801    LogFlowFunc(("u64VTimerOffOld=%#RX64 u64TscNew=%#RX64 u64VTimerValuePaused=%#RX64 -> u64VTimerOff=%#RX64\n",
     1802                 pVM->nem.s.u64VTimerOff, u64TscNew, uPausedTscValue,
     1803                 pVM->nem.s.u64VTimerOff + (u64TscNew - uPausedTscValue)));
     1804
     1805    pVM->nem.s.u64VTimerOff += u64TscNew - uPausedTscValue;
    17631806
    17641807    /*
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