VirtualBox

Ignore:
Timestamp:
Apr 22, 2024 8:30:25 PM (9 months ago)
Author:
vboxsync
Message:

VMM/NEMR3Native-linux-armv8.cpp: Add PSCI handling which enables SMP + power off + reset, and implement vCPU state syncing between the VMM and KVM, bugref:10391

File:
1 edited

Legend:

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

    r104387 r104399  
    4646#include <iprt/armv8.h>
    4747
     48#include <iprt/formats/arm-psci.h>
     49
    4850#include <errno.h>
    4951#include <unistd.h>
     
    5658 *        We'll see whether it would make sense to merge things later on when things have settled.
    5759 */
     60
     61
     62/*********************************************************************************************************************************
     63*   Defined Constants And Macros                                                                                                 *
     64*********************************************************************************************************************************/
    5865
    5966/** Core register group. */
     
    8289#define KVM_ARM64_REG_SYS_CREATE(a_idSysReg) (KVM_ARM64_REG_SYS_GROUP  | ((uint64_t)(a_idSysReg) & 0xffff))
    8390
    84 #define KVM_ARM64_REG_SIMD_CREATE(a_iVecReg) (KVM_ARM64_REG_SIMD_GROUP | (((uint64_t)(a_idReg) << 2) & 0xffff))
     91#define KVM_ARM64_REG_SIMD_CREATE(a_iVecReg) (KVM_ARM64_REG_SIMD_GROUP | (((uint64_t)(a_iVecReg) << 2) & 0xffff))
    8592
    8693#define KVM_ARM64_REG_FP_CREATE(a_idReg)     (KVM_ARM64_REG_FP_GROUP   | ((uint64_t)(a_idReg) & 0xffff))
     
    8996
    9097
     98/*********************************************************************************************************************************
     99*   Structures and Typedefs                                                                                                      *
     100*********************************************************************************************************************************/
     101
     102
     103/*********************************************************************************************************************************
     104*   Global Variables                                                                                                             *
     105*********************************************************************************************************************************/
     106/** The general registers. */
     107static const struct
     108{
     109    uint64_t    idKvmReg;
     110    uint32_t    fCpumExtrn;
     111    uint32_t    offCpumCtx;
     112} s_aCpumRegs[] =
     113{
     114#define CPUM_GREG_EMIT_X0_X3(a_Idx)  { KVM_ARM64_REG_GPR(a_Idx), CPUMCTX_EXTRN_X ## a_Idx, RT_UOFFSETOF(CPUMCTX, aGRegs[a_Idx].x) }
     115#define CPUM_GREG_EMIT_X4_X28(a_Idx) { KVM_ARM64_REG_GPR(a_Idx), CPUMCTX_EXTRN_X4_X28,     RT_UOFFSETOF(CPUMCTX, aGRegs[a_Idx].x) }
     116    CPUM_GREG_EMIT_X0_X3(0),
     117    CPUM_GREG_EMIT_X0_X3(1),
     118    CPUM_GREG_EMIT_X0_X3(2),
     119    CPUM_GREG_EMIT_X0_X3(3),
     120    CPUM_GREG_EMIT_X4_X28(4),
     121    CPUM_GREG_EMIT_X4_X28(5),
     122    CPUM_GREG_EMIT_X4_X28(6),
     123    CPUM_GREG_EMIT_X4_X28(7),
     124    CPUM_GREG_EMIT_X4_X28(8),
     125    CPUM_GREG_EMIT_X4_X28(9),
     126    CPUM_GREG_EMIT_X4_X28(10),
     127    CPUM_GREG_EMIT_X4_X28(11),
     128    CPUM_GREG_EMIT_X4_X28(12),
     129    CPUM_GREG_EMIT_X4_X28(13),
     130    CPUM_GREG_EMIT_X4_X28(14),
     131    CPUM_GREG_EMIT_X4_X28(15),
     132    CPUM_GREG_EMIT_X4_X28(16),
     133    CPUM_GREG_EMIT_X4_X28(17),
     134    CPUM_GREG_EMIT_X4_X28(18),
     135    CPUM_GREG_EMIT_X4_X28(19),
     136    CPUM_GREG_EMIT_X4_X28(20),
     137    CPUM_GREG_EMIT_X4_X28(21),
     138    CPUM_GREG_EMIT_X4_X28(22),
     139    CPUM_GREG_EMIT_X4_X28(23),
     140    CPUM_GREG_EMIT_X4_X28(24),
     141    CPUM_GREG_EMIT_X4_X28(25),
     142    CPUM_GREG_EMIT_X4_X28(26),
     143    CPUM_GREG_EMIT_X4_X28(27),
     144    CPUM_GREG_EMIT_X4_X28(28),
     145    { KVM_ARM64_REG_GPR(29), CPUMCTX_EXTRN_FP,   RT_UOFFSETOF(CPUMCTX, aGRegs[29].x) },
     146    { KVM_ARM64_REG_GPR(30), CPUMCTX_EXTRN_LR,   RT_UOFFSETOF(CPUMCTX, aGRegs[30].x) },
     147    { KVM_ARM64_REG_PC,      CPUMCTX_EXTRN_PC,   RT_UOFFSETOF(CPUMCTX, Pc.u64)       },
     148#undef CPUM_GREG_EMIT_X0_X3
     149#undef CPUM_GREG_EMIT_X4_X28
     150};
     151/** SIMD/FP registers. */
     152static const struct
     153{
     154    uint64_t    idKvmReg;
     155    uint32_t    offCpumCtx;
     156} s_aCpumFpRegs[] =
     157{
     158#define CPUM_VREG_EMIT(a_Idx)  { KVM_ARM64_REG_SIMD_CREATE(a_Idx), RT_UOFFSETOF(CPUMCTX, aVRegs[a_Idx].v) }
     159    CPUM_VREG_EMIT(0),
     160    CPUM_VREG_EMIT(1),
     161    CPUM_VREG_EMIT(2),
     162    CPUM_VREG_EMIT(3),
     163    CPUM_VREG_EMIT(4),
     164    CPUM_VREG_EMIT(5),
     165    CPUM_VREG_EMIT(6),
     166    CPUM_VREG_EMIT(7),
     167    CPUM_VREG_EMIT(8),
     168    CPUM_VREG_EMIT(9),
     169    CPUM_VREG_EMIT(10),
     170    CPUM_VREG_EMIT(11),
     171    CPUM_VREG_EMIT(12),
     172    CPUM_VREG_EMIT(13),
     173    CPUM_VREG_EMIT(14),
     174    CPUM_VREG_EMIT(15),
     175    CPUM_VREG_EMIT(16),
     176    CPUM_VREG_EMIT(17),
     177    CPUM_VREG_EMIT(18),
     178    CPUM_VREG_EMIT(19),
     179    CPUM_VREG_EMIT(20),
     180    CPUM_VREG_EMIT(21),
     181    CPUM_VREG_EMIT(22),
     182    CPUM_VREG_EMIT(23),
     183    CPUM_VREG_EMIT(24),
     184    CPUM_VREG_EMIT(25),
     185    CPUM_VREG_EMIT(26),
     186    CPUM_VREG_EMIT(27),
     187    CPUM_VREG_EMIT(28),
     188    CPUM_VREG_EMIT(29),
     189    CPUM_VREG_EMIT(30),
     190    CPUM_VREG_EMIT(31)
     191#undef CPUM_VREG_EMIT
     192};
     193/** System registers. */
     194static const struct
     195{
     196    uint64_t    idKvmReg;
     197    uint32_t    fCpumExtrn;
     198    uint32_t    offCpumCtx;
     199} s_aCpumSysRegs[] =
     200{
     201    { KVM_ARM64_REG_SP_EL0,                                          CPUMCTX_EXTRN_SP,               RT_UOFFSETOF(CPUMCTX, aSpReg[0].u64)    },
     202    { KVM_ARM64_REG_SP_EL1,                                          CPUMCTX_EXTRN_SP,               RT_UOFFSETOF(CPUMCTX, aSpReg[1].u64)    },
     203    { KVM_ARM64_REG_SPSR_EL1,                                        CPUMCTX_EXTRN_SPSR,             RT_UOFFSETOF(CPUMCTX, Spsr.u64)         },
     204    { KVM_ARM64_REG_ELR_EL1,                                         CPUMCTX_EXTRN_ELR,              RT_UOFFSETOF(CPUMCTX, Elr.u64)          },
     205    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_SCTRL_EL1),      CPUMCTX_EXTRN_SCTLR_TCR_TTBR,   RT_UOFFSETOF(CPUMCTX, Sctlr.u64)        },
     206    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TCR_EL1),        CPUMCTX_EXTRN_SCTLR_TCR_TTBR,   RT_UOFFSETOF(CPUMCTX, Tcr.u64)          },
     207    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TTBR0_EL1),      CPUMCTX_EXTRN_SCTLR_TCR_TTBR,   RT_UOFFSETOF(CPUMCTX, Ttbr0.u64)        },
     208    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TTBR1_EL1),      CPUMCTX_EXTRN_SCTLR_TCR_TTBR,   RT_UOFFSETOF(CPUMCTX, Ttbr1.u64)        },
     209    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_VBAR_EL1),       CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, VBar.u64)         },
     210    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AFSR0_EL1),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Afsr0.u64)        },
     211    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AFSR1_EL1),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Afsr1.u64)        },
     212    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_AMAIR_EL1),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Amair.u64)        },
     213    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CNTKCTL_EL1),    CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, CntKCtl.u64)      },
     214    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CONTEXTIDR_EL1), CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, ContextIdr.u64)   },
     215    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CPACR_EL1),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Cpacr.u64)        },
     216    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_CSSELR_EL1),     CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Csselr.u64)       },
     217    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_ESR_EL1),        CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Esr.u64)          },
     218    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_FAR_EL1),        CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Far.u64)          },
     219    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_MAIR_EL1),       CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Mair.u64)         },
     220    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_PAR_EL1),        CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, Par.u64)          },
     221    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDRRO_EL0),    CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, TpIdrRoEl0.u64)   },
     222    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDR_EL0),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, aTpIdr[0].u64)    },
     223    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_TPIDR_EL1),      CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, aTpIdr[1].u64)    },
     224    { KVM_ARM64_REG_SYS_CREATE(ARMV8_AARCH64_SYSREG_MDCCINT_EL1),    CPUMCTX_EXTRN_SYSREG_MISC,      RT_UOFFSETOF(CPUMCTX, MDccInt.u64)      }
     225};
    91226/** ID registers. */
    92227static const struct
     
    480615
    481616
    482 DECL_FORCE_INLINE(int) nemR3LnxKvmSetQueryReg(PVMCPUCC pVCpu, bool fQuery, uint64_t idKvmReg, const uint64_t *pu64)
     617/**
     618 * Sets the given attribute in KVM to the given value.
     619 *
     620 * @returns VBox status code.
     621 * @param   pVM             The VM instance.
     622 * @param   u32Grp          The device attribute group being set.
     623 * @param   u32Attr         The actual attribute inside the group being set.
     624 * @param   pvAttrVal       Where the attribute value to set.
     625 * @param   pszAttribute    Attribute description for logging.
     626 * @param   pErrInfo        Optional error information.
     627 */
     628static int nemR3LnxSetAttribute(PVM pVM, uint32_t u32Grp, uint32_t u32Attr, const void *pvAttrVal, const char *pszAttribute,
     629                                PRTERRINFO pErrInfo)
     630{
     631    struct kvm_device_attr DevAttr;
     632
     633    DevAttr.flags = 0;
     634    DevAttr.group = u32Grp;
     635    DevAttr.attr  = u32Attr;
     636    DevAttr.addr  = (uintptr_t)pvAttrVal;
     637    int rcLnx = ioctl(pVM->nem.s.fdVm, KVM_HAS_DEVICE_ATTR, &DevAttr);
     638    if (rcLnx < 0)
     639        return RTErrInfoSetF(pErrInfo, RTErrConvertFromErrno(errno),
     640                             N_("KVM error: KVM doesn't support setting the attribute \"%s\" (%d)"),
     641                             pszAttribute, errno);
     642
     643    rcLnx = ioctl(pVM->nem.s.fdVm, KVM_SET_DEVICE_ATTR, &DevAttr);
     644    if (rcLnx < 0)
     645        return RTErrInfoSetF(pErrInfo, RTErrConvertFromErrno(errno),
     646                             N_("KVM error: Setting the attribute \"%s\" for KVM failed (%d)"),
     647                             pszAttribute, errno);
     648
     649    return VINF_SUCCESS;
     650}
     651
     652
     653DECL_FORCE_INLINE(int) nemR3LnxKvmSetQueryReg(PVMCPUCC pVCpu, bool fQuery, uint64_t idKvmReg, const void *pv)
    483654{
    484655    struct kvm_one_reg Reg;
    485656    Reg.id   = idKvmReg;
    486     Reg.addr = (uintptr_t)pu64;
     657    Reg.addr = (uintptr_t)pv;
    487658
    488659    /*
     
    497668}
    498669
    499 DECLINLINE(int) nemR3LnxKvmQueryReg(PVMCPUCC pVCpu, uint64_t idKvmReg, uint64_t *pu64)
     670DECLINLINE(int) nemR3LnxKvmQueryRegU64(PVMCPUCC pVCpu, uint64_t idKvmReg, uint64_t *pu64)
    500671{
    501672    return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pu64);
     
    503674
    504675
    505 DECLINLINE(int) nemR3LnxKvmSetReg(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint64_t *pu64)
     676DECLINLINE(int) nemR3LnxKvmQueryRegU32(PVMCPUCC pVCpu, uint64_t idKvmReg, uint32_t *pu32)
     677{
     678    return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pu32);
     679}
     680
     681
     682DECLINLINE(int) nemR3LnxKvmQueryRegPV(PVMCPUCC pVCpu, uint64_t idKvmReg, void *pv)
     683{
     684    return nemR3LnxKvmSetQueryReg(pVCpu, true /*fQuery*/, idKvmReg, pv);
     685}
     686
     687
     688DECLINLINE(int) nemR3LnxKvmSetRegU64(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint64_t *pu64)
    506689{
    507690    return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pu64);
     691}
     692
     693
     694DECLINLINE(int) nemR3LnxKvmSetRegU32(PVMCPUCC pVCpu, uint64_t idKvmReg, const uint32_t *pu32)
     695{
     696    return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pu32);
     697}
     698
     699
     700DECLINLINE(int) nemR3LnxKvmSetRegPV(PVMCPUCC pVCpu, uint64_t idKvmReg, const void *pv)
     701{
     702    return nemR3LnxKvmSetQueryReg(pVCpu, false /*fQuery*/, idKvmReg, pv);
    508703}
    509704
     
    563758            {
    564759                uint64_t *pu64 = (uint64_t *)((uint8_t *)&IdRegs + s_aIdRegs[i].offIdStruct);
    565                 rc = nemR3LnxKvmQueryReg(pVCpu, s_aIdRegs[i].idKvmReg, pu64);
     760                rc = nemR3LnxKvmQueryRegU64(pVCpu, s_aIdRegs[i].idKvmReg, pu64);
    566761                if (RT_FAILURE(rc))
    567762                    return VMSetError(pVM, VERR_NEM_VM_CREATE_FAILED, RT_SRC_POS,
     
    574769        }
    575770    }
     771
     772    /*
     773     * Setup the SMCCC filter to get exits for PSCI related
     774     * guest calls (to support SMP, power off and reset).
     775     */
     776    struct kvm_smccc_filter SmcccPsciFilter; RT_ZERO(SmcccPsciFilter);
     777    SmcccPsciFilter.base         = ARM_PSCI_FUNC_ID_CREATE_FAST_64(ARM_PSCI_FUNC_ID_PSCI_VERSION);
     778    SmcccPsciFilter.nr_functions = ARM_PSCI_FUNC_ID_CREATE_FAST_64(ARM_PSCI_FUNC_ID_SYSTEM_RESET) - SmcccPsciFilter.base + 1;
     779    SmcccPsciFilter.action       = KVM_SMCCC_FILTER_FWD_TO_USER;
     780    int rc = nemR3LnxSetAttribute(pVM, KVM_ARM_VM_SMCCC_CTRL, KVM_ARM_VM_SMCCC_FILTER, &SmcccPsciFilter,
     781                                  "KVM_ARM_VM_SMCCC_FILTER", pErrInfo);
     782    if (RT_FAILURE(rc))
     783        return rc;
     784
     785    SmcccPsciFilter.base         = ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_PSCI_VERSION);
     786    SmcccPsciFilter.nr_functions = ARM_PSCI_FUNC_ID_CREATE_FAST_32(ARM_PSCI_FUNC_ID_SYSTEM_RESET) - SmcccPsciFilter.base + 1;
     787    SmcccPsciFilter.action       = KVM_SMCCC_FILTER_FWD_TO_USER;
     788    rc = nemR3LnxSetAttribute(pVM, KVM_ARM_VM_SMCCC_CTRL, KVM_ARM_VM_SMCCC_FILTER, &SmcccPsciFilter,
     789                              "KVM_ARM_VM_SMCCC_FILTER", pErrInfo);
     790    if (RT_FAILURE(rc))
     791        return rc;
     792
    576793    return VINF_SUCCESS;
    577794}
     
    11761393
    11771394/**
     1395 * Sets the given general purpose register to the given value.
     1396 *
     1397 * @param   pVCpu           The cross context virtual CPU structure of the
     1398 *                          calling EMT.
     1399 * @param   uReg            The register index.
     1400 * @param   f64BitReg       Flag whether to operate on a 64-bit or 32-bit register.
     1401 * @param   fSignExtend     Flag whether to sign extend the value.
     1402 * @param   u64Val          The value.
     1403 */
     1404DECLINLINE(void) nemR3LnxSetGReg(PVMCPU pVCpu, uint8_t uReg, bool f64BitReg, bool fSignExtend, uint64_t u64Val)
     1405{
     1406    AssertReturnVoid(uReg < 31);
     1407
     1408    if (f64BitReg)
     1409        pVCpu->cpum.GstCtx.aGRegs[uReg].x = fSignExtend ? (int64_t)u64Val : u64Val;
     1410    else
     1411        pVCpu->cpum.GstCtx.aGRegs[uReg].w = fSignExtend ? (int32_t)u64Val : u64Val; /** @todo Does this clear the upper half on real hardware? */
     1412
     1413    /* Mark the register as not extern anymore. */
     1414    switch (uReg)
     1415    {
     1416        case 0:
     1417            pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X0;
     1418            break;
     1419        case 1:
     1420            pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X1;
     1421            break;
     1422        case 2:
     1423            pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X2;
     1424            break;
     1425        case 3:
     1426            pVCpu->cpum.GstCtx.fExtrn &= ~CPUMCTX_EXTRN_X3;
     1427            break;
     1428        default:
     1429            AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_X4_X28));
     1430            /** @todo We need to import all missing registers in order to clear this flag (or just set it in HV from here). */
     1431    }
     1432}
     1433
     1434
     1435/**
     1436 * Gets the given general purpose register and returns the value.
     1437 *
     1438 * @returns Value from the given register.
     1439 * @param   pVCpu           The cross context virtual CPU structure of the
     1440 *                          calling EMT.
     1441 * @param   uReg            The register index.
     1442 */
     1443DECLINLINE(uint64_t) nemR3LnxGetGReg(PVMCPU pVCpu, uint8_t uReg)
     1444{
     1445    AssertReturn(uReg <= ARMV8_AARCH64_REG_ZR, 0);
     1446
     1447    if (uReg == ARMV8_AARCH64_REG_ZR)
     1448        return 0;
     1449
     1450    /** @todo Import the register if extern. */
     1451    //AssertRelease(!(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_GPRS_MASK));
     1452
     1453    return pVCpu->cpum.GstCtx.aGRegs[uReg].x;
     1454}
     1455
     1456/**
    11781457 * Worker that imports selected state from KVM.
    11791458 */
    1180 static int nemHCLnxImportState(PVMCPUCC pVCpu, uint64_t fWhat, PCPUMCTX pCtx, struct kvm_run *pRun)
     1459static int nemHCLnxImportState(PVMCPUCC pVCpu, uint64_t fWhat, PCPUMCTX pCtx)
    11811460{
    11821461    fWhat &= pVCpu->cpum.GstCtx.fExtrn;
     
    11841463        return VINF_SUCCESS;
    11851464
    1186     RT_NOREF(pRun);
    1187 
    1188     /** @todo */
     1465#if 0
     1466    hv_return_t hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CTL_EL0, &pVCpu->cpum.GstCtx.CntvCtlEl0);
     1467    if (hrc == HV_SUCCESS)
     1468        hrc = hv_vcpu_get_sys_reg(pVCpu->nem.s.hVCpu, HV_SYS_REG_CNTV_CVAL_EL0, &pVCpu->cpum.GstCtx.CntvCValEl0);
     1469#endif
     1470
     1471    int rc = VINF_SUCCESS;
     1472    if (fWhat & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC))
     1473    {
     1474        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumRegs); i++)
     1475        {
     1476            if (s_aCpumRegs[i].fCpumExtrn & fWhat)
     1477            {
     1478                uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumRegs[i].offCpumCtx);
     1479                rc |= nemR3LnxKvmQueryRegU64(pVCpu, s_aCpumRegs[i].idKvmReg, pu64);
     1480            }
     1481        }
     1482    }
     1483
     1484    if (   rc == VINF_SUCCESS
     1485        && (fWhat & CPUMCTX_EXTRN_FPCR))
     1486    {
     1487        uint32_t u32Tmp;
     1488        rc |= nemR3LnxKvmQueryRegU32(pVCpu, KVM_ARM64_REG_FP_FPCR, &u32Tmp);
     1489        if (rc == VINF_SUCCESS)
     1490            pVCpu->cpum.GstCtx.fpcr = u32Tmp;
     1491    }
     1492
     1493    if (   rc == VINF_SUCCESS
     1494        && (fWhat & CPUMCTX_EXTRN_FPSR))
     1495    {
     1496        uint32_t u32Tmp;
     1497        rc |= nemR3LnxKvmQueryRegU32(pVCpu, KVM_ARM64_REG_FP_FPSR, &u32Tmp);
     1498        if (rc == VINF_SUCCESS)
     1499            pVCpu->cpum.GstCtx.fpsr = u32Tmp;
     1500    }
     1501
     1502    if (   rc == VINF_SUCCESS
     1503        && (fWhat & CPUMCTX_EXTRN_V0_V31))
     1504    {
     1505        /* SIMD/FP registers. */
     1506        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumFpRegs); i++)
     1507        {
     1508            void *pu128 = (void *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumFpRegs[i].offCpumCtx);
     1509            rc |= nemR3LnxKvmQueryRegPV(pVCpu, s_aCpumFpRegs[i].idKvmReg, pu128);
     1510        }
     1511    }
     1512
     1513    if (   rc == VINF_SUCCESS
     1514        && (fWhat & CPUMCTX_EXTRN_SYSREG_DEBUG))
     1515    {
     1516#if 0
     1517        /* Debug registers. */
     1518        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumDbgRegs); i++)
     1519        {
     1520            uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumDbgRegs[i].offCpumCtx);
     1521            rc |= nemR3LnxKvmQueryReg(pVCpu, s_aCpumDbgRegs[i].idKvmReg, pu64);
     1522        }
     1523#endif
     1524    }
     1525
     1526    if (   rc == VINF_SUCCESS
     1527        && (fWhat & CPUMCTX_EXTRN_SYSREG_PAUTH_KEYS))
     1528    {
     1529#if 0
     1530        /* PAuth registers. */
     1531        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumPAuthKeyRegs); i++)
     1532        {
     1533            uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumPAuthKeyRegs[i].offCpumCtx);
     1534            hrc |= nemR3LnxKvmQueryReg(pVCpu, s_aCpumPAuthKeyRegs[i].idKvmReg, pu64);
     1535        }
     1536#endif
     1537    }
     1538
     1539    if (   rc == VINF_SUCCESS
     1540        && (fWhat & (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC)))
     1541    {
     1542        /* System registers. */
     1543        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumSysRegs); i++)
     1544        {
     1545            if (s_aCpumSysRegs[i].fCpumExtrn & fWhat)
     1546            {
     1547                uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumSysRegs[i].offCpumCtx);
     1548                rc |= nemR3LnxKvmQueryRegU64(pVCpu, s_aCpumSysRegs[i].idKvmReg, pu64);
     1549            }
     1550        }
     1551    }
     1552
     1553    if (   rc == VINF_SUCCESS
     1554        && (fWhat & CPUMCTX_EXTRN_PSTATE))
     1555    {
     1556        uint64_t u64Tmp;
     1557        rc |= nemR3LnxKvmQueryRegU64(pVCpu, KVM_ARM64_REG_PSTATE, &u64Tmp);
     1558        if (rc == VINF_SUCCESS)
     1559            pVCpu->cpum.GstCtx.fPState = (uint32_t)u64Tmp;
     1560
     1561    }
    11891562
    11901563    /*
     
    12101583{
    12111584    STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatImportOnDemand);
    1212     return nemHCLnxImportState(pVCpu, fWhat, &pVCpu->cpum.GstCtx, pVCpu->nem.s.pRun);
     1585    return nemHCLnxImportState(pVCpu, fWhat, &pVCpu->cpum.GstCtx);
    12131586}
    12141587
     
    12171590 * Exports state to KVM.
    12181591 */
    1219 static int nemHCLnxExportState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, struct kvm_run *pRun)
     1592static int nemHCLnxExportState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
    12201593{
    12211594    uint64_t const fExtrn = ~pCtx->fExtrn & CPUMCTX_EXTRN_ALL;
    1222     Assert((~fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL);
    1223 
    1224     RT_NOREF(pVM, pVCpu, pCtx, pRun, fExtrn);
    1225     /** @todo */
     1595    Assert((~fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL); RT_NOREF(fExtrn);
     1596
     1597    RT_NOREF(pVM);
     1598    int rc = VINF_SUCCESS;
     1599    if (   (pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC))
     1600        !=                              (CPUMCTX_EXTRN_GPRS_MASK | CPUMCTX_EXTRN_FP | CPUMCTX_EXTRN_LR | CPUMCTX_EXTRN_PC))
     1601    {
     1602        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumRegs); i++)
     1603        {
     1604            if (!(s_aCpumRegs[i].fCpumExtrn & pVCpu->cpum.GstCtx.fExtrn))
     1605            {
     1606                const uint64_t *pu64 = (const uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumRegs[i].offCpumCtx);
     1607                rc |= nemR3LnxKvmSetRegU64(pVCpu, s_aCpumRegs[i].idKvmReg, pu64);
     1608            }
     1609        }
     1610    }
     1611
     1612    if (   rc == VINF_SUCCESS
     1613        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_FPCR))
     1614    {
     1615        uint32_t u32Tmp = pVCpu->cpum.GstCtx.fpcr;
     1616        rc |= nemR3LnxKvmSetRegU32(pVCpu, KVM_ARM64_REG_FP_FPCR, &u32Tmp);
     1617    }
     1618
     1619    if (   rc == VINF_SUCCESS
     1620        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_FPSR))
     1621    {
     1622        uint32_t u32Tmp = pVCpu->cpum.GstCtx.fpsr;
     1623        rc |= nemR3LnxKvmSetRegU32(pVCpu, KVM_ARM64_REG_FP_FPSR, &u32Tmp);
     1624    }
     1625
     1626    if (   rc == VINF_SUCCESS
     1627        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_V0_V31))
     1628    {
     1629        /* SIMD/FP registers. */
     1630        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumFpRegs); i++)
     1631        {
     1632            void *pu128 = (void *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumFpRegs[i].offCpumCtx);
     1633            rc |= nemR3LnxKvmSetRegPV(pVCpu, s_aCpumFpRegs[i].idKvmReg, pu128);
     1634        }
     1635    }
     1636
     1637    if (   rc == VINF_SUCCESS
     1638        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_SYSREG_DEBUG))
     1639    {
     1640#if 0
     1641        /* Debug registers. */
     1642        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumDbgRegs); i++)
     1643        {
     1644            uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumDbgRegs[i].offCpumCtx);
     1645            hrc |= hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, s_aCpumDbgRegs[i].enmHvReg, *pu64);
     1646        }
     1647#endif
     1648    }
     1649
     1650    if (   rc == VINF_SUCCESS
     1651        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_SYSREG_PAUTH_KEYS))
     1652    {
     1653#if 0
     1654        /* Debug registers. */
     1655        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumPAuthKeyRegs); i++)
     1656        {
     1657            uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumPAuthKeyRegs[i].offCpumCtx);
     1658            hrc |= hv_vcpu_set_sys_reg(pVCpu->nem.s.hVCpu, s_aCpumPAuthKeyRegs[i].enmHvReg, *pu64);
     1659        }
     1660#endif
     1661    }
     1662
     1663    if (   rc == VINF_SUCCESS
     1664        &&     (pVCpu->cpum.GstCtx.fExtrn & (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC))
     1665            !=                              (CPUMCTX_EXTRN_SPSR | CPUMCTX_EXTRN_ELR | CPUMCTX_EXTRN_SP | CPUMCTX_EXTRN_SCTLR_TCR_TTBR | CPUMCTX_EXTRN_SYSREG_MISC))
     1666    {
     1667        /* System registers. */
     1668        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCpumSysRegs); i++)
     1669        {
     1670            if (!(s_aCpumSysRegs[i].fCpumExtrn & pVCpu->cpum.GstCtx.fExtrn))
     1671            {
     1672                uint64_t *pu64 = (uint64_t *)((uint8_t *)&pVCpu->cpum.GstCtx + s_aCpumSysRegs[i].offCpumCtx);
     1673                rc |= nemR3LnxKvmSetRegU64(pVCpu, s_aCpumSysRegs[i].idKvmReg, pu64);
     1674            }
     1675        }
     1676    }
     1677
     1678    if (   rc == VINF_SUCCESS
     1679        && !(pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_PSTATE))
     1680    {
     1681        uint64_t u64Tmp = pVCpu->cpum.GstCtx.fPState;
     1682        rc = nemR3LnxKvmSetRegU64(pVCpu, KVM_ARM64_REG_PSTATE, &u64Tmp);
     1683    }
    12261684
    12271685    /*
     
    14791937
    14801938
     1939/**
     1940 * Handles KVM_EXIT_HYPERCALL.
     1941 */
     1942static VBOXSTRICTRC nemHCLnxHandleExitHypercall(PVMCC pVM, PVMCPUCC pVCpu, struct kvm_run *pRun)
     1943{
     1944#if 0
     1945    /*
     1946     * We cannot easily act on the exit history here, because the MMIO port
     1947     * exit is stateful and the instruction will be completed in the next
     1948     * KVM_RUN call.  There seems no way to circumvent this.
     1949     */
     1950    EMHistoryAddExit(pVCpu,
     1951                     pRun->mmio.is_write
     1952                     ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE)
     1953                     : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ),
     1954                     pRun->s.regs.regs.pc, ASMReadTSC());
     1955#else
     1956    RT_NOREF(pVCpu);
     1957#endif
     1958
     1959    /*
     1960     * Do the requested job.
     1961     */
     1962    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
     1963
     1964    /** @todo Raise exception to EL1 if PSCI not configured. */
     1965    /** @todo Need a generic mechanism here to pass this to, GIM maybe?. */
     1966    uint32_t uFunId = pRun->hypercall.nr;
     1967    bool fHvc64 = RT_BOOL(uFunId & ARM_SMCCC_FUNC_ID_64BIT); RT_NOREF(fHvc64);
     1968    uint32_t uEntity = ARM_SMCCC_FUNC_ID_ENTITY_GET(uFunId);
     1969    uint32_t uFunNum = ARM_SMCCC_FUNC_ID_NUM_GET(uFunId);
     1970    if (uEntity == ARM_SMCCC_FUNC_ID_ENTITY_STD_SEC_SERVICE)
     1971    {
     1972        rcStrict = nemHCLnxImportState(pVCpu, CPUMCTX_EXTRN_X0 | CPUMCTX_EXTRN_X1 | CPUMCTX_EXTRN_X2 | CPUMCTX_EXTRN_X3,
     1973                                       &pVCpu->cpum.GstCtx);
     1974        if (rcStrict != VINF_SUCCESS)
     1975            return rcStrict;
     1976
     1977        switch (uFunNum)
     1978        {
     1979            case ARM_PSCI_FUNC_ID_PSCI_VERSION:
     1980                nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_FUNC_ID_PSCI_VERSION_SET(1, 2));
     1981                break;
     1982            case ARM_PSCI_FUNC_ID_SYSTEM_OFF:
     1983                rcStrict = VMR3PowerOff(pVM->pUVM);
     1984                break;
     1985            case ARM_PSCI_FUNC_ID_SYSTEM_RESET:
     1986            case ARM_PSCI_FUNC_ID_SYSTEM_RESET2:
     1987            {
     1988                bool fHaltOnReset;
     1989                int rc = CFGMR3QueryBool(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "HaltOnReset", &fHaltOnReset);
     1990                if (RT_SUCCESS(rc) && fHaltOnReset)
     1991                {
     1992                    Log(("nemHCLnxHandleExitHypercall: Halt On Reset!\n"));
     1993                    rcStrict = VINF_EM_HALT;
     1994                }
     1995                else
     1996                {
     1997                    /** @todo pVM->pdm.s.fResetFlags = fFlags; */
     1998                    VM_FF_SET(pVM, VM_FF_RESET);
     1999                    rcStrict = VINF_EM_RESET;
     2000                }
     2001                break;
     2002            }
     2003            case ARM_PSCI_FUNC_ID_CPU_ON:
     2004            {
     2005                uint64_t u64TgtCpu      = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X1);
     2006                RTGCPHYS GCPhysExecAddr = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X2);
     2007                uint64_t u64CtxId       = nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X3);
     2008                VMMR3CpuOn(pVM, u64TgtCpu & 0xff, GCPhysExecAddr, u64CtxId);
     2009                nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, true /*f64BitReg*/, false /*fSignExtend*/, ARM_PSCI_STS_SUCCESS);
     2010                break;
     2011            }
     2012            case ARM_PSCI_FUNC_ID_PSCI_FEATURES:
     2013            {
     2014                uint32_t u32FunNum = (uint32_t)nemR3LnxGetGReg(pVCpu, ARMV8_AARCH64_REG_X1);
     2015                switch (u32FunNum)
     2016                {
     2017                    case ARM_PSCI_FUNC_ID_PSCI_VERSION:
     2018                    case ARM_PSCI_FUNC_ID_SYSTEM_OFF:
     2019                    case ARM_PSCI_FUNC_ID_SYSTEM_RESET:
     2020                    case ARM_PSCI_FUNC_ID_SYSTEM_RESET2:
     2021                    case ARM_PSCI_FUNC_ID_CPU_ON:
     2022                        nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0,
     2023                                        false /*f64BitReg*/, false /*fSignExtend*/,
     2024                                        (uint64_t)ARM_PSCI_STS_SUCCESS);
     2025                        break;
     2026                    default:
     2027                        nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0,
     2028                                        false /*f64BitReg*/, false /*fSignExtend*/,
     2029                                        (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
     2030                }
     2031                break;
     2032            }
     2033            default:
     2034                nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
     2035        }
     2036    }
     2037    else
     2038        nemR3LnxSetGReg(pVCpu, ARMV8_AARCH64_REG_X0, false /*f64BitReg*/, false /*fSignExtend*/, (uint64_t)ARM_PSCI_STS_NOT_SUPPORTED);
     2039
     2040
     2041    return rcStrict;
     2042}
     2043
     2044
    14812045static VBOXSTRICTRC nemHCLnxHandleExit(PVMCC pVM, PVMCPUCC pVCpu, struct kvm_run *pRun, bool *pfStatefulExit)
    14822046{
     
    15202084            return VINF_SUCCESS;
    15212085
    1522 #if 0
    15232086        case KVM_EXIT_HYPERCALL:
    15242087            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHypercall);
    1525             AssertFailed();
    1526             break;
    1527 
     2088            return nemHCLnxHandleExitHypercall(pVM, pVCpu, pRun);
     2089
     2090#if 0
    15282091        case KVM_EXIT_DEBUG:
    15292092            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitDebug);
     
    16432206        if ((pVCpu->cpum.GstCtx.fExtrn & CPUMCTX_EXTRN_ALL) != CPUMCTX_EXTRN_ALL)
    16442207        {
    1645             int rc2 = nemHCLnxExportState(pVM, pVCpu, &pVCpu->cpum.GstCtx, pRun);
     2208            int rc2 = nemHCLnxExportState(pVM, pVCpu, &pVCpu->cpum.GstCtx);
    16462209            AssertRCReturn(rc2, rc2);
    16472210        }
     
    18112374        if (pVCpu->cpum.GstCtx.fExtrn & fImport)
    18122375        {
    1813             int rc2 = nemHCLnxImportState(pVCpu, fImport, &pVCpu->cpum.GstCtx, pRun);
     2376            int rc2 = nemHCLnxImportState(pVCpu, fImport, &pVCpu->cpum.GstCtx);
    18142377            if (RT_SUCCESS(rc2))
    18152378                pVCpu->cpum.GstCtx.fExtrn &= ~fImport;
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