1a1477da3SAlexander Graf /* 2a1477da3SAlexander Graf * QEMU Hypervisor.framework support for Apple Silicon 3a1477da3SAlexander Graf 4a1477da3SAlexander Graf * Copyright 2020 Alexander Graf <agraf@csgraf.de> 5219c101fSPeter Collingbourne * Copyright 2020 Google LLC 6a1477da3SAlexander Graf * 7a1477da3SAlexander Graf * This work is licensed under the terms of the GNU GPL, version 2 or later. 8a1477da3SAlexander Graf * See the COPYING file in the top-level directory. 9a1477da3SAlexander Graf * 10a1477da3SAlexander Graf */ 11a1477da3SAlexander Graf 12a1477da3SAlexander Graf #include "qemu/osdep.h" 13a1477da3SAlexander Graf #include "qemu/error-report.h" 14a1477da3SAlexander Graf 15a1477da3SAlexander Graf #include "sysemu/runstate.h" 16a1477da3SAlexander Graf #include "sysemu/hvf.h" 17a1477da3SAlexander Graf #include "sysemu/hvf_int.h" 18a1477da3SAlexander Graf #include "sysemu/hw_accel.h" 19585df85eSPeter Maydell #include "hvf_arm.h" 20b5fb359cSPhilippe Mathieu-Daudé #include "cpregs.h" 21a1477da3SAlexander Graf 22a1477da3SAlexander Graf #include <mach/mach_time.h> 23a1477da3SAlexander Graf 24a1477da3SAlexander Graf #include "exec/address-spaces.h" 25a1477da3SAlexander Graf #include "hw/irq.h" 26a1477da3SAlexander Graf #include "qemu/main-loop.h" 27a1477da3SAlexander Graf #include "sysemu/cpus.h" 282c9c0bf9SAlexander Graf #include "arm-powerctl.h" 29a1477da3SAlexander Graf #include "target/arm/cpu.h" 30a1477da3SAlexander Graf #include "target/arm/internals.h" 31a1477da3SAlexander Graf #include "trace/trace-target_arm_hvf.h" 32a1477da3SAlexander Graf #include "migration/vmstate.h" 33a1477da3SAlexander Graf 34a1477da3SAlexander Graf #define HVF_SYSREG(crn, crm, op0, op1, op2) \ 35a1477da3SAlexander Graf ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2) 36a1477da3SAlexander Graf #define PL1_WRITE_MASK 0x4 37a1477da3SAlexander Graf 38ad99f64fSAlexander Graf #define SYSREG_OP0_SHIFT 20 39ad99f64fSAlexander Graf #define SYSREG_OP0_MASK 0x3 40ad99f64fSAlexander Graf #define SYSREG_OP0(sysreg) ((sysreg >> SYSREG_OP0_SHIFT) & SYSREG_OP0_MASK) 41ad99f64fSAlexander Graf #define SYSREG_OP1_SHIFT 14 42ad99f64fSAlexander Graf #define SYSREG_OP1_MASK 0x7 43ad99f64fSAlexander Graf #define SYSREG_OP1(sysreg) ((sysreg >> SYSREG_OP1_SHIFT) & SYSREG_OP1_MASK) 44ad99f64fSAlexander Graf #define SYSREG_CRN_SHIFT 10 45ad99f64fSAlexander Graf #define SYSREG_CRN_MASK 0xf 46ad99f64fSAlexander Graf #define SYSREG_CRN(sysreg) ((sysreg >> SYSREG_CRN_SHIFT) & SYSREG_CRN_MASK) 47ad99f64fSAlexander Graf #define SYSREG_CRM_SHIFT 1 48ad99f64fSAlexander Graf #define SYSREG_CRM_MASK 0xf 49ad99f64fSAlexander Graf #define SYSREG_CRM(sysreg) ((sysreg >> SYSREG_CRM_SHIFT) & SYSREG_CRM_MASK) 50ad99f64fSAlexander Graf #define SYSREG_OP2_SHIFT 17 51ad99f64fSAlexander Graf #define SYSREG_OP2_MASK 0x7 52ad99f64fSAlexander Graf #define SYSREG_OP2(sysreg) ((sysreg >> SYSREG_OP2_SHIFT) & SYSREG_OP2_MASK) 53ad99f64fSAlexander Graf 54a1477da3SAlexander Graf #define SYSREG(op0, op1, crn, crm, op2) \ 55ad99f64fSAlexander Graf ((op0 << SYSREG_OP0_SHIFT) | \ 56ad99f64fSAlexander Graf (op1 << SYSREG_OP1_SHIFT) | \ 57ad99f64fSAlexander Graf (crn << SYSREG_CRN_SHIFT) | \ 58ad99f64fSAlexander Graf (crm << SYSREG_CRM_SHIFT) | \ 59ad99f64fSAlexander Graf (op2 << SYSREG_OP2_SHIFT)) 60ad99f64fSAlexander Graf #define SYSREG_MASK \ 61ad99f64fSAlexander Graf SYSREG(SYSREG_OP0_MASK, \ 62ad99f64fSAlexander Graf SYSREG_OP1_MASK, \ 63ad99f64fSAlexander Graf SYSREG_CRN_MASK, \ 64ad99f64fSAlexander Graf SYSREG_CRM_MASK, \ 65ad99f64fSAlexander Graf SYSREG_OP2_MASK) 66a1477da3SAlexander Graf #define SYSREG_OSLAR_EL1 SYSREG(2, 0, 1, 0, 4) 67a1477da3SAlexander Graf #define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4) 68a1477da3SAlexander Graf #define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4) 69a1477da3SAlexander Graf #define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1) 70dd43ac07SAlexander Graf #define SYSREG_PMCR_EL0 SYSREG(3, 3, 9, 12, 0) 71dd43ac07SAlexander Graf #define SYSREG_PMUSERENR_EL0 SYSREG(3, 3, 9, 14, 0) 72dd43ac07SAlexander Graf #define SYSREG_PMCNTENSET_EL0 SYSREG(3, 3, 9, 12, 1) 73dd43ac07SAlexander Graf #define SYSREG_PMCNTENCLR_EL0 SYSREG(3, 3, 9, 12, 2) 74dd43ac07SAlexander Graf #define SYSREG_PMINTENCLR_EL1 SYSREG(3, 0, 9, 14, 2) 75dd43ac07SAlexander Graf #define SYSREG_PMOVSCLR_EL0 SYSREG(3, 3, 9, 12, 3) 76dd43ac07SAlexander Graf #define SYSREG_PMSWINC_EL0 SYSREG(3, 3, 9, 12, 4) 77dd43ac07SAlexander Graf #define SYSREG_PMSELR_EL0 SYSREG(3, 3, 9, 12, 5) 78dd43ac07SAlexander Graf #define SYSREG_PMCEID0_EL0 SYSREG(3, 3, 9, 12, 6) 79dd43ac07SAlexander Graf #define SYSREG_PMCEID1_EL0 SYSREG(3, 3, 9, 12, 7) 80dd43ac07SAlexander Graf #define SYSREG_PMCCNTR_EL0 SYSREG(3, 3, 9, 13, 0) 81dd43ac07SAlexander Graf #define SYSREG_PMCCFILTR_EL0 SYSREG(3, 3, 14, 15, 7) 82a1477da3SAlexander Graf 83a1477da3SAlexander Graf #define WFX_IS_WFE (1 << 0) 84a1477da3SAlexander Graf 85a1477da3SAlexander Graf #define TMR_CTL_ENABLE (1 << 0) 86a1477da3SAlexander Graf #define TMR_CTL_IMASK (1 << 1) 87a1477da3SAlexander Graf #define TMR_CTL_ISTATUS (1 << 2) 88a1477da3SAlexander Graf 892c9c0bf9SAlexander Graf static void hvf_wfi(CPUState *cpu); 902c9c0bf9SAlexander Graf 91a1477da3SAlexander Graf typedef struct HVFVTimer { 92a1477da3SAlexander Graf /* Vtimer value during migration and paused state */ 93a1477da3SAlexander Graf uint64_t vtimer_val; 94a1477da3SAlexander Graf } HVFVTimer; 95a1477da3SAlexander Graf 96a1477da3SAlexander Graf static HVFVTimer vtimer; 97a1477da3SAlexander Graf 98585df85eSPeter Maydell typedef struct ARMHostCPUFeatures { 99585df85eSPeter Maydell ARMISARegisters isar; 100585df85eSPeter Maydell uint64_t features; 101585df85eSPeter Maydell uint64_t midr; 102585df85eSPeter Maydell uint32_t reset_sctlr; 103585df85eSPeter Maydell const char *dtb_compatible; 104585df85eSPeter Maydell } ARMHostCPUFeatures; 105585df85eSPeter Maydell 106585df85eSPeter Maydell static ARMHostCPUFeatures arm_host_cpu_features; 107585df85eSPeter Maydell 108a1477da3SAlexander Graf struct hvf_reg_match { 109a1477da3SAlexander Graf int reg; 110a1477da3SAlexander Graf uint64_t offset; 111a1477da3SAlexander Graf }; 112a1477da3SAlexander Graf 113a1477da3SAlexander Graf static const struct hvf_reg_match hvf_reg_match[] = { 114a1477da3SAlexander Graf { HV_REG_X0, offsetof(CPUARMState, xregs[0]) }, 115a1477da3SAlexander Graf { HV_REG_X1, offsetof(CPUARMState, xregs[1]) }, 116a1477da3SAlexander Graf { HV_REG_X2, offsetof(CPUARMState, xregs[2]) }, 117a1477da3SAlexander Graf { HV_REG_X3, offsetof(CPUARMState, xregs[3]) }, 118a1477da3SAlexander Graf { HV_REG_X4, offsetof(CPUARMState, xregs[4]) }, 119a1477da3SAlexander Graf { HV_REG_X5, offsetof(CPUARMState, xregs[5]) }, 120a1477da3SAlexander Graf { HV_REG_X6, offsetof(CPUARMState, xregs[6]) }, 121a1477da3SAlexander Graf { HV_REG_X7, offsetof(CPUARMState, xregs[7]) }, 122a1477da3SAlexander Graf { HV_REG_X8, offsetof(CPUARMState, xregs[8]) }, 123a1477da3SAlexander Graf { HV_REG_X9, offsetof(CPUARMState, xregs[9]) }, 124a1477da3SAlexander Graf { HV_REG_X10, offsetof(CPUARMState, xregs[10]) }, 125a1477da3SAlexander Graf { HV_REG_X11, offsetof(CPUARMState, xregs[11]) }, 126a1477da3SAlexander Graf { HV_REG_X12, offsetof(CPUARMState, xregs[12]) }, 127a1477da3SAlexander Graf { HV_REG_X13, offsetof(CPUARMState, xregs[13]) }, 128a1477da3SAlexander Graf { HV_REG_X14, offsetof(CPUARMState, xregs[14]) }, 129a1477da3SAlexander Graf { HV_REG_X15, offsetof(CPUARMState, xregs[15]) }, 130a1477da3SAlexander Graf { HV_REG_X16, offsetof(CPUARMState, xregs[16]) }, 131a1477da3SAlexander Graf { HV_REG_X17, offsetof(CPUARMState, xregs[17]) }, 132a1477da3SAlexander Graf { HV_REG_X18, offsetof(CPUARMState, xregs[18]) }, 133a1477da3SAlexander Graf { HV_REG_X19, offsetof(CPUARMState, xregs[19]) }, 134a1477da3SAlexander Graf { HV_REG_X20, offsetof(CPUARMState, xregs[20]) }, 135a1477da3SAlexander Graf { HV_REG_X21, offsetof(CPUARMState, xregs[21]) }, 136a1477da3SAlexander Graf { HV_REG_X22, offsetof(CPUARMState, xregs[22]) }, 137a1477da3SAlexander Graf { HV_REG_X23, offsetof(CPUARMState, xregs[23]) }, 138a1477da3SAlexander Graf { HV_REG_X24, offsetof(CPUARMState, xregs[24]) }, 139a1477da3SAlexander Graf { HV_REG_X25, offsetof(CPUARMState, xregs[25]) }, 140a1477da3SAlexander Graf { HV_REG_X26, offsetof(CPUARMState, xregs[26]) }, 141a1477da3SAlexander Graf { HV_REG_X27, offsetof(CPUARMState, xregs[27]) }, 142a1477da3SAlexander Graf { HV_REG_X28, offsetof(CPUARMState, xregs[28]) }, 143a1477da3SAlexander Graf { HV_REG_X29, offsetof(CPUARMState, xregs[29]) }, 144a1477da3SAlexander Graf { HV_REG_X30, offsetof(CPUARMState, xregs[30]) }, 145a1477da3SAlexander Graf { HV_REG_PC, offsetof(CPUARMState, pc) }, 146a1477da3SAlexander Graf }; 147a1477da3SAlexander Graf 148a1477da3SAlexander Graf static const struct hvf_reg_match hvf_fpreg_match[] = { 149a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q0, offsetof(CPUARMState, vfp.zregs[0]) }, 150a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q1, offsetof(CPUARMState, vfp.zregs[1]) }, 151a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q2, offsetof(CPUARMState, vfp.zregs[2]) }, 152a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q3, offsetof(CPUARMState, vfp.zregs[3]) }, 153a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q4, offsetof(CPUARMState, vfp.zregs[4]) }, 154a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q5, offsetof(CPUARMState, vfp.zregs[5]) }, 155a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q6, offsetof(CPUARMState, vfp.zregs[6]) }, 156a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q7, offsetof(CPUARMState, vfp.zregs[7]) }, 157a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q8, offsetof(CPUARMState, vfp.zregs[8]) }, 158a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q9, offsetof(CPUARMState, vfp.zregs[9]) }, 159a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q10, offsetof(CPUARMState, vfp.zregs[10]) }, 160a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q11, offsetof(CPUARMState, vfp.zregs[11]) }, 161a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q12, offsetof(CPUARMState, vfp.zregs[12]) }, 162a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q13, offsetof(CPUARMState, vfp.zregs[13]) }, 163a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q14, offsetof(CPUARMState, vfp.zregs[14]) }, 164a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q15, offsetof(CPUARMState, vfp.zregs[15]) }, 165a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q16, offsetof(CPUARMState, vfp.zregs[16]) }, 166a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q17, offsetof(CPUARMState, vfp.zregs[17]) }, 167a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q18, offsetof(CPUARMState, vfp.zregs[18]) }, 168a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q19, offsetof(CPUARMState, vfp.zregs[19]) }, 169a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q20, offsetof(CPUARMState, vfp.zregs[20]) }, 170a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q21, offsetof(CPUARMState, vfp.zregs[21]) }, 171a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q22, offsetof(CPUARMState, vfp.zregs[22]) }, 172a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q23, offsetof(CPUARMState, vfp.zregs[23]) }, 173a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q24, offsetof(CPUARMState, vfp.zregs[24]) }, 174a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q25, offsetof(CPUARMState, vfp.zregs[25]) }, 175a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q26, offsetof(CPUARMState, vfp.zregs[26]) }, 176a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q27, offsetof(CPUARMState, vfp.zregs[27]) }, 177a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q28, offsetof(CPUARMState, vfp.zregs[28]) }, 178a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q29, offsetof(CPUARMState, vfp.zregs[29]) }, 179a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q30, offsetof(CPUARMState, vfp.zregs[30]) }, 180a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q31, offsetof(CPUARMState, vfp.zregs[31]) }, 181a1477da3SAlexander Graf }; 182a1477da3SAlexander Graf 183a1477da3SAlexander Graf struct hvf_sreg_match { 184a1477da3SAlexander Graf int reg; 185a1477da3SAlexander Graf uint32_t key; 186a1477da3SAlexander Graf uint32_t cp_idx; 187a1477da3SAlexander Graf }; 188a1477da3SAlexander Graf 189a1477da3SAlexander Graf static struct hvf_sreg_match hvf_sreg_match[] = { 190a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) }, 191a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) }, 192a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) }, 193a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) }, 194a1477da3SAlexander Graf 195a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) }, 196a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) }, 197a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) }, 198a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) }, 199a1477da3SAlexander Graf 200a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) }, 201a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) }, 202a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) }, 203a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) }, 204a1477da3SAlexander Graf 205a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) }, 206a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) }, 207a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) }, 208a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) }, 209a1477da3SAlexander Graf 210a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) }, 211a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) }, 212a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) }, 213a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) }, 214a1477da3SAlexander Graf 215a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) }, 216a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) }, 217a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) }, 218a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) }, 219a1477da3SAlexander Graf 220a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) }, 221a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) }, 222a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) }, 223a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) }, 224a1477da3SAlexander Graf 225a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) }, 226a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) }, 227a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) }, 228a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) }, 229a1477da3SAlexander Graf 230a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) }, 231a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) }, 232a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) }, 233a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) }, 234a1477da3SAlexander Graf 235a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) }, 236a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) }, 237a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) }, 238a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) }, 239a1477da3SAlexander Graf 240a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) }, 241a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) }, 242a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) }, 243a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) }, 244a1477da3SAlexander Graf 245a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) }, 246a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) }, 247a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) }, 248a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) }, 249a1477da3SAlexander Graf 250a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) }, 251a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) }, 252a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) }, 253a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) }, 254a1477da3SAlexander Graf 255a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) }, 256a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) }, 257a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) }, 258a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) }, 259a1477da3SAlexander Graf 260a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) }, 261a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) }, 262a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) }, 263a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) }, 264a1477da3SAlexander Graf 265a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) }, 266a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) }, 267a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) }, 268a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) }, 269a1477da3SAlexander Graf 270a1477da3SAlexander Graf #ifdef SYNC_NO_RAW_REGS 271a1477da3SAlexander Graf /* 272a1477da3SAlexander Graf * The registers below are manually synced on init because they are 273a1477da3SAlexander Graf * marked as NO_RAW. We still list them to make number space sync easier. 274a1477da3SAlexander Graf */ 275a1477da3SAlexander Graf { HV_SYS_REG_MDCCINT_EL1, HVF_SYSREG(0, 2, 2, 0, 0) }, 276a1477da3SAlexander Graf { HV_SYS_REG_MIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 0) }, 277a1477da3SAlexander Graf { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) }, 278a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) }, 279a1477da3SAlexander Graf #endif 280a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) }, 281a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) }, 282a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) }, 283a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) }, 284a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR1_EL1, HVF_SYSREG(0, 6, 3, 0, 1) }, 285a1477da3SAlexander Graf #ifdef SYNC_NO_MMFR0 286a1477da3SAlexander Graf /* We keep the hardware MMFR0 around. HW limits are there anyway */ 287a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR0_EL1, HVF_SYSREG(0, 7, 3, 0, 0) }, 288a1477da3SAlexander Graf #endif 289a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) }, 290a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) }, 291a1477da3SAlexander Graf 292a1477da3SAlexander Graf { HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) }, 293a1477da3SAlexander Graf { HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) }, 294a1477da3SAlexander Graf { HV_SYS_REG_CPACR_EL1, HVF_SYSREG(1, 0, 3, 0, 2) }, 295a1477da3SAlexander Graf { HV_SYS_REG_TTBR0_EL1, HVF_SYSREG(2, 0, 3, 0, 0) }, 296a1477da3SAlexander Graf { HV_SYS_REG_TTBR1_EL1, HVF_SYSREG(2, 0, 3, 0, 1) }, 297a1477da3SAlexander Graf { HV_SYS_REG_TCR_EL1, HVF_SYSREG(2, 0, 3, 0, 2) }, 298a1477da3SAlexander Graf 299a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 0) }, 300a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 1) }, 301a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 2) }, 302a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 3) }, 303a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 0) }, 304a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 1) }, 305a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 2) }, 306a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 3) }, 307a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYLO_EL1, HVF_SYSREG(2, 3, 3, 0, 0) }, 308a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYHI_EL1, HVF_SYSREG(2, 3, 3, 0, 1) }, 309a1477da3SAlexander Graf 310a1477da3SAlexander Graf { HV_SYS_REG_SPSR_EL1, HVF_SYSREG(4, 0, 3, 0, 0) }, 311a1477da3SAlexander Graf { HV_SYS_REG_ELR_EL1, HVF_SYSREG(4, 0, 3, 0, 1) }, 312a1477da3SAlexander Graf { HV_SYS_REG_SP_EL0, HVF_SYSREG(4, 1, 3, 0, 0) }, 313a1477da3SAlexander Graf { HV_SYS_REG_AFSR0_EL1, HVF_SYSREG(5, 1, 3, 0, 0) }, 314a1477da3SAlexander Graf { HV_SYS_REG_AFSR1_EL1, HVF_SYSREG(5, 1, 3, 0, 1) }, 315a1477da3SAlexander Graf { HV_SYS_REG_ESR_EL1, HVF_SYSREG(5, 2, 3, 0, 0) }, 316a1477da3SAlexander Graf { HV_SYS_REG_FAR_EL1, HVF_SYSREG(6, 0, 3, 0, 0) }, 317a1477da3SAlexander Graf { HV_SYS_REG_PAR_EL1, HVF_SYSREG(7, 4, 3, 0, 0) }, 318a1477da3SAlexander Graf { HV_SYS_REG_MAIR_EL1, HVF_SYSREG(10, 2, 3, 0, 0) }, 319a1477da3SAlexander Graf { HV_SYS_REG_AMAIR_EL1, HVF_SYSREG(10, 3, 3, 0, 0) }, 320a1477da3SAlexander Graf { HV_SYS_REG_VBAR_EL1, HVF_SYSREG(12, 0, 3, 0, 0) }, 321a1477da3SAlexander Graf { HV_SYS_REG_CONTEXTIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 1) }, 322a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 4) }, 323a1477da3SAlexander Graf { HV_SYS_REG_CNTKCTL_EL1, HVF_SYSREG(14, 1, 3, 0, 0) }, 324a1477da3SAlexander Graf { HV_SYS_REG_CSSELR_EL1, HVF_SYSREG(0, 0, 3, 2, 0) }, 325a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL0, HVF_SYSREG(13, 0, 3, 3, 2) }, 326a1477da3SAlexander Graf { HV_SYS_REG_TPIDRRO_EL0, HVF_SYSREG(13, 0, 3, 3, 3) }, 327a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CTL_EL0, HVF_SYSREG(14, 3, 3, 3, 1) }, 328a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CVAL_EL0, HVF_SYSREG(14, 3, 3, 3, 2) }, 329a1477da3SAlexander Graf { HV_SYS_REG_SP_EL1, HVF_SYSREG(4, 1, 3, 4, 0) }, 330a1477da3SAlexander Graf }; 331a1477da3SAlexander Graf 332a1477da3SAlexander Graf int hvf_get_registers(CPUState *cpu) 333a1477da3SAlexander Graf { 334a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 335a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 336a1477da3SAlexander Graf hv_return_t ret; 337a1477da3SAlexander Graf uint64_t val; 338a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 339a1477da3SAlexander Graf int i; 340a1477da3SAlexander Graf 341a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 342a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, hvf_reg_match[i].reg, &val); 343a1477da3SAlexander Graf *(uint64_t *)((void *)env + hvf_reg_match[i].offset) = val; 344a1477da3SAlexander Graf assert_hvf_ok(ret); 345a1477da3SAlexander Graf } 346a1477da3SAlexander Graf 347a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 348a1477da3SAlexander Graf ret = hv_vcpu_get_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 349a1477da3SAlexander Graf &fpval); 350a1477da3SAlexander Graf memcpy((void *)env + hvf_fpreg_match[i].offset, &fpval, sizeof(fpval)); 351a1477da3SAlexander Graf assert_hvf_ok(ret); 352a1477da3SAlexander Graf } 353a1477da3SAlexander Graf 354a1477da3SAlexander Graf val = 0; 355a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPCR, &val); 356a1477da3SAlexander Graf assert_hvf_ok(ret); 357a1477da3SAlexander Graf vfp_set_fpcr(env, val); 358a1477da3SAlexander Graf 359a1477da3SAlexander Graf val = 0; 360a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPSR, &val); 361a1477da3SAlexander Graf assert_hvf_ok(ret); 362a1477da3SAlexander Graf vfp_set_fpsr(env, val); 363a1477da3SAlexander Graf 364a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_CPSR, &val); 365a1477da3SAlexander Graf assert_hvf_ok(ret); 366a1477da3SAlexander Graf pstate_write(env, val); 367a1477da3SAlexander Graf 368a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 369a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 370a1477da3SAlexander Graf continue; 371a1477da3SAlexander Graf } 372a1477da3SAlexander Graf 373a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, &val); 374a1477da3SAlexander Graf assert_hvf_ok(ret); 375a1477da3SAlexander Graf 376a1477da3SAlexander Graf arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx] = val; 377a1477da3SAlexander Graf } 378a1477da3SAlexander Graf assert(write_list_to_cpustate(arm_cpu)); 379a1477da3SAlexander Graf 380a1477da3SAlexander Graf aarch64_restore_sp(env, arm_current_el(env)); 381a1477da3SAlexander Graf 382a1477da3SAlexander Graf return 0; 383a1477da3SAlexander Graf } 384a1477da3SAlexander Graf 385a1477da3SAlexander Graf int hvf_put_registers(CPUState *cpu) 386a1477da3SAlexander Graf { 387a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 388a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 389a1477da3SAlexander Graf hv_return_t ret; 390a1477da3SAlexander Graf uint64_t val; 391a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 392a1477da3SAlexander Graf int i; 393a1477da3SAlexander Graf 394a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 395a1477da3SAlexander Graf val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset); 396a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, hvf_reg_match[i].reg, val); 397a1477da3SAlexander Graf assert_hvf_ok(ret); 398a1477da3SAlexander Graf } 399a1477da3SAlexander Graf 400a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 401a1477da3SAlexander Graf memcpy(&fpval, (void *)env + hvf_fpreg_match[i].offset, sizeof(fpval)); 402a1477da3SAlexander Graf ret = hv_vcpu_set_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 403a1477da3SAlexander Graf fpval); 404a1477da3SAlexander Graf assert_hvf_ok(ret); 405a1477da3SAlexander Graf } 406a1477da3SAlexander Graf 407a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPCR, vfp_get_fpcr(env)); 408a1477da3SAlexander Graf assert_hvf_ok(ret); 409a1477da3SAlexander Graf 410a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPSR, vfp_get_fpsr(env)); 411a1477da3SAlexander Graf assert_hvf_ok(ret); 412a1477da3SAlexander Graf 413a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_CPSR, pstate_read(env)); 414a1477da3SAlexander Graf assert_hvf_ok(ret); 415a1477da3SAlexander Graf 416a1477da3SAlexander Graf aarch64_save_sp(env, arm_current_el(env)); 417a1477da3SAlexander Graf 418a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 419a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 420a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 421a1477da3SAlexander Graf continue; 422a1477da3SAlexander Graf } 423a1477da3SAlexander Graf 424a1477da3SAlexander Graf val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx]; 425a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val); 426a1477da3SAlexander Graf assert_hvf_ok(ret); 427a1477da3SAlexander Graf } 428a1477da3SAlexander Graf 429a1477da3SAlexander Graf ret = hv_vcpu_set_vtimer_offset(cpu->hvf->fd, hvf_state->vtimer_offset); 430a1477da3SAlexander Graf assert_hvf_ok(ret); 431a1477da3SAlexander Graf 432a1477da3SAlexander Graf return 0; 433a1477da3SAlexander Graf } 434a1477da3SAlexander Graf 435a1477da3SAlexander Graf static void flush_cpu_state(CPUState *cpu) 436a1477da3SAlexander Graf { 437a1477da3SAlexander Graf if (cpu->vcpu_dirty) { 438a1477da3SAlexander Graf hvf_put_registers(cpu); 439a1477da3SAlexander Graf cpu->vcpu_dirty = false; 440a1477da3SAlexander Graf } 441a1477da3SAlexander Graf } 442a1477da3SAlexander Graf 443a1477da3SAlexander Graf static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val) 444a1477da3SAlexander Graf { 445a1477da3SAlexander Graf hv_return_t r; 446a1477da3SAlexander Graf 447a1477da3SAlexander Graf flush_cpu_state(cpu); 448a1477da3SAlexander Graf 449a1477da3SAlexander Graf if (rt < 31) { 450a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_X0 + rt, val); 451a1477da3SAlexander Graf assert_hvf_ok(r); 452a1477da3SAlexander Graf } 453a1477da3SAlexander Graf } 454a1477da3SAlexander Graf 455a1477da3SAlexander Graf static uint64_t hvf_get_reg(CPUState *cpu, int rt) 456a1477da3SAlexander Graf { 457a1477da3SAlexander Graf uint64_t val = 0; 458a1477da3SAlexander Graf hv_return_t r; 459a1477da3SAlexander Graf 460a1477da3SAlexander Graf flush_cpu_state(cpu); 461a1477da3SAlexander Graf 462a1477da3SAlexander Graf if (rt < 31) { 463a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_X0 + rt, &val); 464a1477da3SAlexander Graf assert_hvf_ok(r); 465a1477da3SAlexander Graf } 466a1477da3SAlexander Graf 467a1477da3SAlexander Graf return val; 468a1477da3SAlexander Graf } 469a1477da3SAlexander Graf 470585df85eSPeter Maydell static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 471585df85eSPeter Maydell { 472585df85eSPeter Maydell ARMISARegisters host_isar = {}; 473585df85eSPeter Maydell const struct isar_regs { 474585df85eSPeter Maydell int reg; 475585df85eSPeter Maydell uint64_t *val; 476585df85eSPeter Maydell } regs[] = { 477585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, 478585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, 479585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, 480585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, 481585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, 482585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, 483585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, 484585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, 485585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, 486585df85eSPeter Maydell }; 487585df85eSPeter Maydell hv_vcpu_t fd; 488585df85eSPeter Maydell hv_return_t r = HV_SUCCESS; 489585df85eSPeter Maydell hv_vcpu_exit_t *exit; 490585df85eSPeter Maydell int i; 491585df85eSPeter Maydell 492585df85eSPeter Maydell ahcf->dtb_compatible = "arm,arm-v8"; 493585df85eSPeter Maydell ahcf->features = (1ULL << ARM_FEATURE_V8) | 494585df85eSPeter Maydell (1ULL << ARM_FEATURE_NEON) | 495585df85eSPeter Maydell (1ULL << ARM_FEATURE_AARCH64) | 496585df85eSPeter Maydell (1ULL << ARM_FEATURE_PMU) | 497585df85eSPeter Maydell (1ULL << ARM_FEATURE_GENERIC_TIMER); 498585df85eSPeter Maydell 499585df85eSPeter Maydell /* We set up a small vcpu to extract host registers */ 500585df85eSPeter Maydell 501585df85eSPeter Maydell if (hv_vcpu_create(&fd, &exit, NULL) != HV_SUCCESS) { 502585df85eSPeter Maydell return false; 503585df85eSPeter Maydell } 504585df85eSPeter Maydell 505585df85eSPeter Maydell for (i = 0; i < ARRAY_SIZE(regs); i++) { 506585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val); 507585df85eSPeter Maydell } 508585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr); 509585df85eSPeter Maydell r |= hv_vcpu_destroy(fd); 510585df85eSPeter Maydell 511585df85eSPeter Maydell ahcf->isar = host_isar; 512585df85eSPeter Maydell 513585df85eSPeter Maydell /* 514585df85eSPeter Maydell * A scratch vCPU returns SCTLR 0, so let's fill our default with the M1 515585df85eSPeter Maydell * boot SCTLR from https://github.com/AsahiLinux/m1n1/issues/97 516585df85eSPeter Maydell */ 517585df85eSPeter Maydell ahcf->reset_sctlr = 0x30100180; 518585df85eSPeter Maydell /* 519585df85eSPeter Maydell * SPAN is disabled by default when SCTLR.SPAN=1. To improve compatibility, 520585df85eSPeter Maydell * let's disable it on boot and then allow guest software to turn it on by 521585df85eSPeter Maydell * setting it to 0. 522585df85eSPeter Maydell */ 523585df85eSPeter Maydell ahcf->reset_sctlr |= 0x00800000; 524585df85eSPeter Maydell 525585df85eSPeter Maydell /* Make sure we don't advertise AArch32 support for EL0/EL1 */ 526585df85eSPeter Maydell if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) { 527585df85eSPeter Maydell return false; 528585df85eSPeter Maydell } 529585df85eSPeter Maydell 530585df85eSPeter Maydell return r == HV_SUCCESS; 531585df85eSPeter Maydell } 532585df85eSPeter Maydell 533585df85eSPeter Maydell void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu) 534585df85eSPeter Maydell { 535585df85eSPeter Maydell if (!arm_host_cpu_features.dtb_compatible) { 536585df85eSPeter Maydell if (!hvf_enabled() || 537585df85eSPeter Maydell !hvf_arm_get_host_cpu_features(&arm_host_cpu_features)) { 538585df85eSPeter Maydell /* 539585df85eSPeter Maydell * We can't report this error yet, so flag that we need to 540585df85eSPeter Maydell * in arm_cpu_realizefn(). 541585df85eSPeter Maydell */ 542585df85eSPeter Maydell cpu->host_cpu_probe_failed = true; 543585df85eSPeter Maydell return; 544585df85eSPeter Maydell } 545585df85eSPeter Maydell } 546585df85eSPeter Maydell 547585df85eSPeter Maydell cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 548585df85eSPeter Maydell cpu->isar = arm_host_cpu_features.isar; 549585df85eSPeter Maydell cpu->env.features = arm_host_cpu_features.features; 550585df85eSPeter Maydell cpu->midr = arm_host_cpu_features.midr; 551585df85eSPeter Maydell cpu->reset_sctlr = arm_host_cpu_features.reset_sctlr; 552585df85eSPeter Maydell } 553585df85eSPeter Maydell 554a1477da3SAlexander Graf void hvf_arch_vcpu_destroy(CPUState *cpu) 555a1477da3SAlexander Graf { 556a1477da3SAlexander Graf } 557a1477da3SAlexander Graf 558a1477da3SAlexander Graf int hvf_arch_init_vcpu(CPUState *cpu) 559a1477da3SAlexander Graf { 560a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 561a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 562a1477da3SAlexander Graf uint32_t sregs_match_len = ARRAY_SIZE(hvf_sreg_match); 563a1477da3SAlexander Graf uint32_t sregs_cnt = 0; 564a1477da3SAlexander Graf uint64_t pfr; 565a1477da3SAlexander Graf hv_return_t ret; 566a1477da3SAlexander Graf int i; 567a1477da3SAlexander Graf 56853221552SRichard Henderson env->aarch64 = true; 569a1477da3SAlexander Graf asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz)); 570a1477da3SAlexander Graf 571a1477da3SAlexander Graf /* Allocate enough space for our sysreg sync */ 572a1477da3SAlexander Graf arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes, 573a1477da3SAlexander Graf sregs_match_len); 574a1477da3SAlexander Graf arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values, 575a1477da3SAlexander Graf sregs_match_len); 576a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t, 577a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes, 578a1477da3SAlexander Graf sregs_match_len); 579a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values = g_renew(uint64_t, 580a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values, 581a1477da3SAlexander Graf sregs_match_len); 582a1477da3SAlexander Graf 583a1477da3SAlexander Graf memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t)); 584a1477da3SAlexander Graf 585a1477da3SAlexander Graf /* Populate cp list for all known sysregs */ 586a1477da3SAlexander Graf for (i = 0; i < sregs_match_len; i++) { 587a1477da3SAlexander Graf const ARMCPRegInfo *ri; 588a1477da3SAlexander Graf uint32_t key = hvf_sreg_match[i].key; 589a1477da3SAlexander Graf 590a1477da3SAlexander Graf ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key); 591a1477da3SAlexander Graf if (ri) { 592a1477da3SAlexander Graf assert(!(ri->type & ARM_CP_NO_RAW)); 593a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = sregs_cnt; 594a1477da3SAlexander Graf arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key); 595a1477da3SAlexander Graf } else { 596a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = -1; 597a1477da3SAlexander Graf } 598a1477da3SAlexander Graf } 599a1477da3SAlexander Graf arm_cpu->cpreg_array_len = sregs_cnt; 600a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_array_len = sregs_cnt; 601a1477da3SAlexander Graf 602a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 603a1477da3SAlexander Graf 604a1477da3SAlexander Graf /* Set CP_NO_RAW system registers on init */ 605a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MIDR_EL1, 606a1477da3SAlexander Graf arm_cpu->midr); 607a1477da3SAlexander Graf assert_hvf_ok(ret); 608a1477da3SAlexander Graf 609a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MPIDR_EL1, 610a1477da3SAlexander Graf arm_cpu->mp_affinity); 611a1477da3SAlexander Graf assert_hvf_ok(ret); 612a1477da3SAlexander Graf 613a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, &pfr); 614a1477da3SAlexander Graf assert_hvf_ok(ret); 615a1477da3SAlexander Graf pfr |= env->gicv3state ? (1 << 24) : 0; 616a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, pfr); 617a1477da3SAlexander Graf assert_hvf_ok(ret); 618a1477da3SAlexander Graf 619a1477da3SAlexander Graf /* We're limited to underlying hardware caps, override internal versions */ 620a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, 621a1477da3SAlexander Graf &arm_cpu->isar.id_aa64mmfr0); 622a1477da3SAlexander Graf assert_hvf_ok(ret); 623a1477da3SAlexander Graf 624a1477da3SAlexander Graf return 0; 625a1477da3SAlexander Graf } 626a1477da3SAlexander Graf 627a1477da3SAlexander Graf void hvf_kick_vcpu_thread(CPUState *cpu) 628a1477da3SAlexander Graf { 629219c101fSPeter Collingbourne cpus_kick_thread(cpu); 630a1477da3SAlexander Graf hv_vcpus_exit(&cpu->hvf->fd, 1); 631a1477da3SAlexander Graf } 632a1477da3SAlexander Graf 633a1477da3SAlexander Graf static void hvf_raise_exception(CPUState *cpu, uint32_t excp, 634a1477da3SAlexander Graf uint32_t syndrome) 635a1477da3SAlexander Graf { 636a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 637a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 638a1477da3SAlexander Graf 639a1477da3SAlexander Graf cpu->exception_index = excp; 640a1477da3SAlexander Graf env->exception.target_el = 1; 641a1477da3SAlexander Graf env->exception.syndrome = syndrome; 642a1477da3SAlexander Graf 643a1477da3SAlexander Graf arm_cpu_do_interrupt(cpu); 644a1477da3SAlexander Graf } 645a1477da3SAlexander Graf 6462c9c0bf9SAlexander Graf static void hvf_psci_cpu_off(ARMCPU *arm_cpu) 6472c9c0bf9SAlexander Graf { 6482c9c0bf9SAlexander Graf int32_t ret = arm_set_cpu_off(arm_cpu->mp_affinity); 6492c9c0bf9SAlexander Graf assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS); 6502c9c0bf9SAlexander Graf } 6512c9c0bf9SAlexander Graf 6522c9c0bf9SAlexander Graf /* 6532c9c0bf9SAlexander Graf * Handle a PSCI call. 6542c9c0bf9SAlexander Graf * 6552c9c0bf9SAlexander Graf * Returns 0 on success 6562c9c0bf9SAlexander Graf * -1 when the PSCI call is unknown, 6572c9c0bf9SAlexander Graf */ 6582c9c0bf9SAlexander Graf static bool hvf_handle_psci_call(CPUState *cpu) 6592c9c0bf9SAlexander Graf { 6602c9c0bf9SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 6612c9c0bf9SAlexander Graf CPUARMState *env = &arm_cpu->env; 6622c9c0bf9SAlexander Graf uint64_t param[4] = { 6632c9c0bf9SAlexander Graf env->xregs[0], 6642c9c0bf9SAlexander Graf env->xregs[1], 6652c9c0bf9SAlexander Graf env->xregs[2], 6662c9c0bf9SAlexander Graf env->xregs[3] 6672c9c0bf9SAlexander Graf }; 6682c9c0bf9SAlexander Graf uint64_t context_id, mpidr; 6692c9c0bf9SAlexander Graf bool target_aarch64 = true; 6702c9c0bf9SAlexander Graf CPUState *target_cpu_state; 6712c9c0bf9SAlexander Graf ARMCPU *target_cpu; 6722c9c0bf9SAlexander Graf target_ulong entry; 6732c9c0bf9SAlexander Graf int target_el = 1; 6742c9c0bf9SAlexander Graf int32_t ret = 0; 6752c9c0bf9SAlexander Graf 6762c9c0bf9SAlexander Graf trace_hvf_psci_call(param[0], param[1], param[2], param[3], 6772c9c0bf9SAlexander Graf arm_cpu->mp_affinity); 6782c9c0bf9SAlexander Graf 6792c9c0bf9SAlexander Graf switch (param[0]) { 6802c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_PSCI_VERSION: 6810dc71c70SAkihiko Odaki ret = QEMU_PSCI_VERSION_1_1; 6822c9c0bf9SAlexander Graf break; 6832c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 6842c9c0bf9SAlexander Graf ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ 6852c9c0bf9SAlexander Graf break; 6862c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 6872c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 6882c9c0bf9SAlexander Graf mpidr = param[1]; 6892c9c0bf9SAlexander Graf 6902c9c0bf9SAlexander Graf switch (param[2]) { 6912c9c0bf9SAlexander Graf case 0: 6922c9c0bf9SAlexander Graf target_cpu_state = arm_get_cpu_by_id(mpidr); 6932c9c0bf9SAlexander Graf if (!target_cpu_state) { 6942c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 6952c9c0bf9SAlexander Graf break; 6962c9c0bf9SAlexander Graf } 6972c9c0bf9SAlexander Graf target_cpu = ARM_CPU(target_cpu_state); 6982c9c0bf9SAlexander Graf 6992c9c0bf9SAlexander Graf ret = target_cpu->power_state; 7002c9c0bf9SAlexander Graf break; 7012c9c0bf9SAlexander Graf default: 7022c9c0bf9SAlexander Graf /* Everything above affinity level 0 is always on. */ 7032c9c0bf9SAlexander Graf ret = 0; 7042c9c0bf9SAlexander Graf } 7052c9c0bf9SAlexander Graf break; 7062c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 7072c9c0bf9SAlexander Graf qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 7082c9c0bf9SAlexander Graf /* 7092c9c0bf9SAlexander Graf * QEMU reset and shutdown are async requests, but PSCI 7102c9c0bf9SAlexander Graf * mandates that we never return from the reset/shutdown 7112c9c0bf9SAlexander Graf * call, so power the CPU off now so it doesn't execute 7122c9c0bf9SAlexander Graf * anything further. 7132c9c0bf9SAlexander Graf */ 7142c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 7152c9c0bf9SAlexander Graf break; 7162c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 7172c9c0bf9SAlexander Graf qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 7182c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 7192c9c0bf9SAlexander Graf break; 7202c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_ON: 7212c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_ON: 7222c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_ON: 7232c9c0bf9SAlexander Graf mpidr = param[1]; 7242c9c0bf9SAlexander Graf entry = param[2]; 7252c9c0bf9SAlexander Graf context_id = param[3]; 7262c9c0bf9SAlexander Graf ret = arm_set_cpu_on(mpidr, entry, context_id, 7272c9c0bf9SAlexander Graf target_el, target_aarch64); 7282c9c0bf9SAlexander Graf break; 7292c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_OFF: 7302c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_OFF: 7312c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 7322c9c0bf9SAlexander Graf break; 7332c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 7342c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 7352c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 7362c9c0bf9SAlexander Graf /* Affinity levels are not supported in QEMU */ 7372c9c0bf9SAlexander Graf if (param[1] & 0xfffe0000) { 7382c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 7392c9c0bf9SAlexander Graf break; 7402c9c0bf9SAlexander Graf } 7412c9c0bf9SAlexander Graf /* Powerdown is not supported, we always go into WFI */ 7422c9c0bf9SAlexander Graf env->xregs[0] = 0; 7432c9c0bf9SAlexander Graf hvf_wfi(cpu); 7442c9c0bf9SAlexander Graf break; 7452c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_MIGRATE: 7462c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE: 7472c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_NOT_SUPPORTED; 7482c9c0bf9SAlexander Graf break; 7490dc71c70SAkihiko Odaki case QEMU_PSCI_1_0_FN_PSCI_FEATURES: 7500dc71c70SAkihiko Odaki switch (param[1]) { 7510dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_PSCI_VERSION: 7520dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 7530dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 7540dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 7550dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 7560dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 7570dc71c70SAkihiko Odaki case QEMU_PSCI_0_1_FN_CPU_ON: 7580dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_CPU_ON: 7590dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN64_CPU_ON: 7600dc71c70SAkihiko Odaki case QEMU_PSCI_0_1_FN_CPU_OFF: 7610dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_CPU_OFF: 7620dc71c70SAkihiko Odaki case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 7630dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 7640dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 7650dc71c70SAkihiko Odaki case QEMU_PSCI_1_0_FN_PSCI_FEATURES: 7660dc71c70SAkihiko Odaki ret = 0; 7670dc71c70SAkihiko Odaki break; 7680dc71c70SAkihiko Odaki case QEMU_PSCI_0_1_FN_MIGRATE: 7690dc71c70SAkihiko Odaki case QEMU_PSCI_0_2_FN_MIGRATE: 7700dc71c70SAkihiko Odaki default: 7710dc71c70SAkihiko Odaki ret = QEMU_PSCI_RET_NOT_SUPPORTED; 7720dc71c70SAkihiko Odaki } 7730dc71c70SAkihiko Odaki break; 7742c9c0bf9SAlexander Graf default: 7752c9c0bf9SAlexander Graf return false; 7762c9c0bf9SAlexander Graf } 7772c9c0bf9SAlexander Graf 7782c9c0bf9SAlexander Graf env->xregs[0] = ret; 7792c9c0bf9SAlexander Graf return true; 7802c9c0bf9SAlexander Graf } 7812c9c0bf9SAlexander Graf 7827f6c295cSAlexander Graf static bool is_id_sysreg(uint32_t reg) 7837f6c295cSAlexander Graf { 7847f6c295cSAlexander Graf return SYSREG_OP0(reg) == 3 && 7857f6c295cSAlexander Graf SYSREG_OP1(reg) == 0 && 7867f6c295cSAlexander Graf SYSREG_CRN(reg) == 0 && 7877f6c295cSAlexander Graf SYSREG_CRM(reg) >= 1 && 7887f6c295cSAlexander Graf SYSREG_CRM(reg) < 8; 7897f6c295cSAlexander Graf } 7907f6c295cSAlexander Graf 791a1477da3SAlexander Graf static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt) 792a1477da3SAlexander Graf { 793a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 794a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 795a1477da3SAlexander Graf uint64_t val = 0; 796a1477da3SAlexander Graf 797a1477da3SAlexander Graf switch (reg) { 798a1477da3SAlexander Graf case SYSREG_CNTPCT_EL0: 799a1477da3SAlexander Graf val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 800a1477da3SAlexander Graf gt_cntfrq_period_ns(arm_cpu); 801a1477da3SAlexander Graf break; 802dd43ac07SAlexander Graf case SYSREG_PMCR_EL0: 803dd43ac07SAlexander Graf val = env->cp15.c9_pmcr; 804dd43ac07SAlexander Graf break; 805dd43ac07SAlexander Graf case SYSREG_PMCCNTR_EL0: 806dd43ac07SAlexander Graf pmu_op_start(env); 807dd43ac07SAlexander Graf val = env->cp15.c15_ccnt; 808dd43ac07SAlexander Graf pmu_op_finish(env); 809dd43ac07SAlexander Graf break; 810dd43ac07SAlexander Graf case SYSREG_PMCNTENCLR_EL0: 811dd43ac07SAlexander Graf val = env->cp15.c9_pmcnten; 812dd43ac07SAlexander Graf break; 813dd43ac07SAlexander Graf case SYSREG_PMOVSCLR_EL0: 814dd43ac07SAlexander Graf val = env->cp15.c9_pmovsr; 815dd43ac07SAlexander Graf break; 816dd43ac07SAlexander Graf case SYSREG_PMSELR_EL0: 817dd43ac07SAlexander Graf val = env->cp15.c9_pmselr; 818dd43ac07SAlexander Graf break; 819dd43ac07SAlexander Graf case SYSREG_PMINTENCLR_EL1: 820dd43ac07SAlexander Graf val = env->cp15.c9_pminten; 821dd43ac07SAlexander Graf break; 822dd43ac07SAlexander Graf case SYSREG_PMCCFILTR_EL0: 823dd43ac07SAlexander Graf val = env->cp15.pmccfiltr_el0; 824dd43ac07SAlexander Graf break; 825dd43ac07SAlexander Graf case SYSREG_PMCNTENSET_EL0: 826dd43ac07SAlexander Graf val = env->cp15.c9_pmcnten; 827dd43ac07SAlexander Graf break; 828dd43ac07SAlexander Graf case SYSREG_PMUSERENR_EL0: 829dd43ac07SAlexander Graf val = env->cp15.c9_pmuserenr; 830dd43ac07SAlexander Graf break; 831dd43ac07SAlexander Graf case SYSREG_PMCEID0_EL0: 832dd43ac07SAlexander Graf case SYSREG_PMCEID1_EL0: 833dd43ac07SAlexander Graf /* We can't really count anything yet, declare all events invalid */ 834dd43ac07SAlexander Graf val = 0; 835dd43ac07SAlexander Graf break; 836a1477da3SAlexander Graf case SYSREG_OSLSR_EL1: 837a1477da3SAlexander Graf val = env->cp15.oslsr_el1; 838a1477da3SAlexander Graf break; 839a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 840a1477da3SAlexander Graf /* Dummy register */ 841a1477da3SAlexander Graf break; 842a1477da3SAlexander Graf default: 8437f6c295cSAlexander Graf if (is_id_sysreg(reg)) { 8447f6c295cSAlexander Graf /* ID system registers read as RES0 */ 8457f6c295cSAlexander Graf val = 0; 8467f6c295cSAlexander Graf break; 8477f6c295cSAlexander Graf } 848a1477da3SAlexander Graf cpu_synchronize_state(cpu); 849a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_read(env->pc, reg, 850ad99f64fSAlexander Graf SYSREG_OP0(reg), 851ad99f64fSAlexander Graf SYSREG_OP1(reg), 852ad99f64fSAlexander Graf SYSREG_CRN(reg), 853ad99f64fSAlexander Graf SYSREG_CRM(reg), 854ad99f64fSAlexander Graf SYSREG_OP2(reg)); 855a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 856a1477da3SAlexander Graf return 1; 857a1477da3SAlexander Graf } 858a1477da3SAlexander Graf 859a1477da3SAlexander Graf trace_hvf_sysreg_read(reg, 860ad99f64fSAlexander Graf SYSREG_OP0(reg), 861ad99f64fSAlexander Graf SYSREG_OP1(reg), 862ad99f64fSAlexander Graf SYSREG_CRN(reg), 863ad99f64fSAlexander Graf SYSREG_CRM(reg), 864ad99f64fSAlexander Graf SYSREG_OP2(reg), 865a1477da3SAlexander Graf val); 866a1477da3SAlexander Graf hvf_set_reg(cpu, rt, val); 867a1477da3SAlexander Graf 868a1477da3SAlexander Graf return 0; 869a1477da3SAlexander Graf } 870a1477da3SAlexander Graf 871dd43ac07SAlexander Graf static void pmu_update_irq(CPUARMState *env) 872dd43ac07SAlexander Graf { 873dd43ac07SAlexander Graf ARMCPU *cpu = env_archcpu(env); 874dd43ac07SAlexander Graf qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) && 875dd43ac07SAlexander Graf (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); 876dd43ac07SAlexander Graf } 877dd43ac07SAlexander Graf 878dd43ac07SAlexander Graf static bool pmu_event_supported(uint16_t number) 879dd43ac07SAlexander Graf { 880dd43ac07SAlexander Graf return false; 881dd43ac07SAlexander Graf } 882dd43ac07SAlexander Graf 883dd43ac07SAlexander Graf /* Returns true if the counter (pass 31 for PMCCNTR) should count events using 884dd43ac07SAlexander Graf * the current EL, security state, and register configuration. 885dd43ac07SAlexander Graf */ 886dd43ac07SAlexander Graf static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) 887dd43ac07SAlexander Graf { 888dd43ac07SAlexander Graf uint64_t filter; 889dd43ac07SAlexander Graf bool enabled, filtered = true; 890dd43ac07SAlexander Graf int el = arm_current_el(env); 891dd43ac07SAlexander Graf 892dd43ac07SAlexander Graf enabled = (env->cp15.c9_pmcr & PMCRE) && 893dd43ac07SAlexander Graf (env->cp15.c9_pmcnten & (1 << counter)); 894dd43ac07SAlexander Graf 895dd43ac07SAlexander Graf if (counter == 31) { 896dd43ac07SAlexander Graf filter = env->cp15.pmccfiltr_el0; 897dd43ac07SAlexander Graf } else { 898dd43ac07SAlexander Graf filter = env->cp15.c14_pmevtyper[counter]; 899dd43ac07SAlexander Graf } 900dd43ac07SAlexander Graf 901dd43ac07SAlexander Graf if (el == 0) { 902dd43ac07SAlexander Graf filtered = filter & PMXEVTYPER_U; 903dd43ac07SAlexander Graf } else if (el == 1) { 904dd43ac07SAlexander Graf filtered = filter & PMXEVTYPER_P; 905dd43ac07SAlexander Graf } 906dd43ac07SAlexander Graf 907dd43ac07SAlexander Graf if (counter != 31) { 908dd43ac07SAlexander Graf /* 909dd43ac07SAlexander Graf * If not checking PMCCNTR, ensure the counter is setup to an event we 910dd43ac07SAlexander Graf * support 911dd43ac07SAlexander Graf */ 912dd43ac07SAlexander Graf uint16_t event = filter & PMXEVTYPER_EVTCOUNT; 913dd43ac07SAlexander Graf if (!pmu_event_supported(event)) { 914dd43ac07SAlexander Graf return false; 915dd43ac07SAlexander Graf } 916dd43ac07SAlexander Graf } 917dd43ac07SAlexander Graf 918dd43ac07SAlexander Graf return enabled && !filtered; 919dd43ac07SAlexander Graf } 920dd43ac07SAlexander Graf 921dd43ac07SAlexander Graf static void pmswinc_write(CPUARMState *env, uint64_t value) 922dd43ac07SAlexander Graf { 923dd43ac07SAlexander Graf unsigned int i; 924dd43ac07SAlexander Graf for (i = 0; i < pmu_num_counters(env); i++) { 925dd43ac07SAlexander Graf /* Increment a counter's count iff: */ 926dd43ac07SAlexander Graf if ((value & (1 << i)) && /* counter's bit is set */ 927dd43ac07SAlexander Graf /* counter is enabled and not filtered */ 928dd43ac07SAlexander Graf pmu_counter_enabled(env, i) && 929dd43ac07SAlexander Graf /* counter is SW_INCR */ 930dd43ac07SAlexander Graf (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) { 931dd43ac07SAlexander Graf /* 932dd43ac07SAlexander Graf * Detect if this write causes an overflow since we can't predict 933dd43ac07SAlexander Graf * PMSWINC overflows like we can for other events 934dd43ac07SAlexander Graf */ 935dd43ac07SAlexander Graf uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1; 936dd43ac07SAlexander Graf 937dd43ac07SAlexander Graf if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) { 938dd43ac07SAlexander Graf env->cp15.c9_pmovsr |= (1 << i); 939dd43ac07SAlexander Graf pmu_update_irq(env); 940dd43ac07SAlexander Graf } 941dd43ac07SAlexander Graf 942dd43ac07SAlexander Graf env->cp15.c14_pmevcntr[i] = new_pmswinc; 943dd43ac07SAlexander Graf } 944dd43ac07SAlexander Graf } 945dd43ac07SAlexander Graf } 946dd43ac07SAlexander Graf 947a1477da3SAlexander Graf static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) 948a1477da3SAlexander Graf { 949a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 950a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 951a1477da3SAlexander Graf 952a1477da3SAlexander Graf trace_hvf_sysreg_write(reg, 953ad99f64fSAlexander Graf SYSREG_OP0(reg), 954ad99f64fSAlexander Graf SYSREG_OP1(reg), 955ad99f64fSAlexander Graf SYSREG_CRN(reg), 956ad99f64fSAlexander Graf SYSREG_CRM(reg), 957ad99f64fSAlexander Graf SYSREG_OP2(reg), 958a1477da3SAlexander Graf val); 959a1477da3SAlexander Graf 960a1477da3SAlexander Graf switch (reg) { 961dd43ac07SAlexander Graf case SYSREG_PMCCNTR_EL0: 962dd43ac07SAlexander Graf pmu_op_start(env); 963dd43ac07SAlexander Graf env->cp15.c15_ccnt = val; 964dd43ac07SAlexander Graf pmu_op_finish(env); 965dd43ac07SAlexander Graf break; 966dd43ac07SAlexander Graf case SYSREG_PMCR_EL0: 967dd43ac07SAlexander Graf pmu_op_start(env); 968dd43ac07SAlexander Graf 969dd43ac07SAlexander Graf if (val & PMCRC) { 970dd43ac07SAlexander Graf /* The counter has been reset */ 971dd43ac07SAlexander Graf env->cp15.c15_ccnt = 0; 972dd43ac07SAlexander Graf } 973dd43ac07SAlexander Graf 974dd43ac07SAlexander Graf if (val & PMCRP) { 975dd43ac07SAlexander Graf unsigned int i; 976dd43ac07SAlexander Graf for (i = 0; i < pmu_num_counters(env); i++) { 977dd43ac07SAlexander Graf env->cp15.c14_pmevcntr[i] = 0; 978dd43ac07SAlexander Graf } 979dd43ac07SAlexander Graf } 980dd43ac07SAlexander Graf 981*9323e79fSPeter Maydell env->cp15.c9_pmcr &= ~PMCR_WRITABLE_MASK; 982*9323e79fSPeter Maydell env->cp15.c9_pmcr |= (val & PMCR_WRITABLE_MASK); 983dd43ac07SAlexander Graf 984dd43ac07SAlexander Graf pmu_op_finish(env); 985dd43ac07SAlexander Graf break; 986dd43ac07SAlexander Graf case SYSREG_PMUSERENR_EL0: 987dd43ac07SAlexander Graf env->cp15.c9_pmuserenr = val & 0xf; 988dd43ac07SAlexander Graf break; 989dd43ac07SAlexander Graf case SYSREG_PMCNTENSET_EL0: 990dd43ac07SAlexander Graf env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env)); 991dd43ac07SAlexander Graf break; 992dd43ac07SAlexander Graf case SYSREG_PMCNTENCLR_EL0: 993dd43ac07SAlexander Graf env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env)); 994dd43ac07SAlexander Graf break; 995dd43ac07SAlexander Graf case SYSREG_PMINTENCLR_EL1: 996dd43ac07SAlexander Graf pmu_op_start(env); 997dd43ac07SAlexander Graf env->cp15.c9_pminten |= val; 998dd43ac07SAlexander Graf pmu_op_finish(env); 999dd43ac07SAlexander Graf break; 1000dd43ac07SAlexander Graf case SYSREG_PMOVSCLR_EL0: 1001dd43ac07SAlexander Graf pmu_op_start(env); 1002dd43ac07SAlexander Graf env->cp15.c9_pmovsr &= ~val; 1003dd43ac07SAlexander Graf pmu_op_finish(env); 1004dd43ac07SAlexander Graf break; 1005dd43ac07SAlexander Graf case SYSREG_PMSWINC_EL0: 1006dd43ac07SAlexander Graf pmu_op_start(env); 1007dd43ac07SAlexander Graf pmswinc_write(env, val); 1008dd43ac07SAlexander Graf pmu_op_finish(env); 1009dd43ac07SAlexander Graf break; 1010dd43ac07SAlexander Graf case SYSREG_PMSELR_EL0: 1011dd43ac07SAlexander Graf env->cp15.c9_pmselr = val & 0x1f; 1012dd43ac07SAlexander Graf break; 1013dd43ac07SAlexander Graf case SYSREG_PMCCFILTR_EL0: 1014dd43ac07SAlexander Graf pmu_op_start(env); 1015dd43ac07SAlexander Graf env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0; 1016dd43ac07SAlexander Graf pmu_op_finish(env); 1017dd43ac07SAlexander Graf break; 1018a1477da3SAlexander Graf case SYSREG_OSLAR_EL1: 1019a1477da3SAlexander Graf env->cp15.oslsr_el1 = val & 1; 1020a1477da3SAlexander Graf break; 1021a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 1022a1477da3SAlexander Graf /* Dummy register */ 1023a1477da3SAlexander Graf break; 1024a1477da3SAlexander Graf default: 1025a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1026a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_write(env->pc, reg, 1027ad99f64fSAlexander Graf SYSREG_OP0(reg), 1028ad99f64fSAlexander Graf SYSREG_OP1(reg), 1029ad99f64fSAlexander Graf SYSREG_CRN(reg), 1030ad99f64fSAlexander Graf SYSREG_CRM(reg), 1031ad99f64fSAlexander Graf SYSREG_OP2(reg)); 1032a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 1033a1477da3SAlexander Graf return 1; 1034a1477da3SAlexander Graf } 1035a1477da3SAlexander Graf 1036a1477da3SAlexander Graf return 0; 1037a1477da3SAlexander Graf } 1038a1477da3SAlexander Graf 1039a1477da3SAlexander Graf static int hvf_inject_interrupts(CPUState *cpu) 1040a1477da3SAlexander Graf { 1041a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_FIQ) { 1042a1477da3SAlexander Graf trace_hvf_inject_fiq(); 1043a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_FIQ, 1044a1477da3SAlexander Graf true); 1045a1477da3SAlexander Graf } 1046a1477da3SAlexander Graf 1047a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { 1048a1477da3SAlexander Graf trace_hvf_inject_irq(); 1049a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_IRQ, 1050a1477da3SAlexander Graf true); 1051a1477da3SAlexander Graf } 1052a1477da3SAlexander Graf 1053a1477da3SAlexander Graf return 0; 1054a1477da3SAlexander Graf } 1055a1477da3SAlexander Graf 1056a1477da3SAlexander Graf static uint64_t hvf_vtimer_val_raw(void) 1057a1477da3SAlexander Graf { 1058a1477da3SAlexander Graf /* 1059a1477da3SAlexander Graf * mach_absolute_time() returns the vtimer value without the VM 1060a1477da3SAlexander Graf * offset that we define. Add our own offset on top. 1061a1477da3SAlexander Graf */ 1062a1477da3SAlexander Graf return mach_absolute_time() - hvf_state->vtimer_offset; 1063a1477da3SAlexander Graf } 1064a1477da3SAlexander Graf 1065219c101fSPeter Collingbourne static uint64_t hvf_vtimer_val(void) 1066219c101fSPeter Collingbourne { 1067219c101fSPeter Collingbourne if (!runstate_is_running()) { 1068219c101fSPeter Collingbourne /* VM is paused, the vtimer value is in vtimer.vtimer_val */ 1069219c101fSPeter Collingbourne return vtimer.vtimer_val; 1070219c101fSPeter Collingbourne } 1071219c101fSPeter Collingbourne 1072219c101fSPeter Collingbourne return hvf_vtimer_val_raw(); 1073219c101fSPeter Collingbourne } 1074219c101fSPeter Collingbourne 1075219c101fSPeter Collingbourne static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) 1076219c101fSPeter Collingbourne { 1077219c101fSPeter Collingbourne /* 1078219c101fSPeter Collingbourne * Use pselect to sleep so that other threads can IPI us while we're 1079219c101fSPeter Collingbourne * sleeping. 1080219c101fSPeter Collingbourne */ 1081219c101fSPeter Collingbourne qatomic_mb_set(&cpu->thread_kicked, false); 1082219c101fSPeter Collingbourne qemu_mutex_unlock_iothread(); 1083219c101fSPeter Collingbourne pselect(0, 0, 0, 0, ts, &cpu->hvf->unblock_ipi_mask); 1084219c101fSPeter Collingbourne qemu_mutex_lock_iothread(); 1085219c101fSPeter Collingbourne } 1086219c101fSPeter Collingbourne 1087219c101fSPeter Collingbourne static void hvf_wfi(CPUState *cpu) 1088219c101fSPeter Collingbourne { 1089219c101fSPeter Collingbourne ARMCPU *arm_cpu = ARM_CPU(cpu); 1090219c101fSPeter Collingbourne struct timespec ts; 1091219c101fSPeter Collingbourne hv_return_t r; 1092219c101fSPeter Collingbourne uint64_t ctl; 1093219c101fSPeter Collingbourne uint64_t cval; 1094219c101fSPeter Collingbourne int64_t ticks_to_sleep; 1095219c101fSPeter Collingbourne uint64_t seconds; 1096219c101fSPeter Collingbourne uint64_t nanos; 1097219c101fSPeter Collingbourne uint32_t cntfrq; 1098219c101fSPeter Collingbourne 1099219c101fSPeter Collingbourne if (cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) { 1100219c101fSPeter Collingbourne /* Interrupt pending, no need to wait */ 1101219c101fSPeter Collingbourne return; 1102219c101fSPeter Collingbourne } 1103219c101fSPeter Collingbourne 1104219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 1105219c101fSPeter Collingbourne assert_hvf_ok(r); 1106219c101fSPeter Collingbourne 1107219c101fSPeter Collingbourne if (!(ctl & 1) || (ctl & 2)) { 1108219c101fSPeter Collingbourne /* Timer disabled or masked, just wait for an IPI. */ 1109219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, NULL); 1110219c101fSPeter Collingbourne return; 1111219c101fSPeter Collingbourne } 1112219c101fSPeter Collingbourne 1113219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval); 1114219c101fSPeter Collingbourne assert_hvf_ok(r); 1115219c101fSPeter Collingbourne 1116219c101fSPeter Collingbourne ticks_to_sleep = cval - hvf_vtimer_val(); 1117219c101fSPeter Collingbourne if (ticks_to_sleep < 0) { 1118219c101fSPeter Collingbourne return; 1119219c101fSPeter Collingbourne } 1120219c101fSPeter Collingbourne 1121219c101fSPeter Collingbourne cntfrq = gt_cntfrq_period_ns(arm_cpu); 1122219c101fSPeter Collingbourne seconds = muldiv64(ticks_to_sleep, cntfrq, NANOSECONDS_PER_SECOND); 1123219c101fSPeter Collingbourne ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq); 1124219c101fSPeter Collingbourne nanos = ticks_to_sleep * cntfrq; 1125219c101fSPeter Collingbourne 1126219c101fSPeter Collingbourne /* 1127219c101fSPeter Collingbourne * Don't sleep for less than the time a context switch would take, 1128219c101fSPeter Collingbourne * so that we can satisfy fast timer requests on the same CPU. 1129219c101fSPeter Collingbourne * Measurements on M1 show the sweet spot to be ~2ms. 1130219c101fSPeter Collingbourne */ 1131219c101fSPeter Collingbourne if (!seconds && nanos < (2 * SCALE_MS)) { 1132219c101fSPeter Collingbourne return; 1133219c101fSPeter Collingbourne } 1134219c101fSPeter Collingbourne 1135219c101fSPeter Collingbourne ts = (struct timespec) { seconds, nanos }; 1136219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, &ts); 1137219c101fSPeter Collingbourne } 1138219c101fSPeter Collingbourne 1139a1477da3SAlexander Graf static void hvf_sync_vtimer(CPUState *cpu) 1140a1477da3SAlexander Graf { 1141a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 1142a1477da3SAlexander Graf hv_return_t r; 1143a1477da3SAlexander Graf uint64_t ctl; 1144a1477da3SAlexander Graf bool irq_state; 1145a1477da3SAlexander Graf 1146a1477da3SAlexander Graf if (!cpu->hvf->vtimer_masked) { 1147a1477da3SAlexander Graf /* We will get notified on vtimer changes by hvf, nothing to do */ 1148a1477da3SAlexander Graf return; 1149a1477da3SAlexander Graf } 1150a1477da3SAlexander Graf 1151a1477da3SAlexander Graf r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 1152a1477da3SAlexander Graf assert_hvf_ok(r); 1153a1477da3SAlexander Graf 1154a1477da3SAlexander Graf irq_state = (ctl & (TMR_CTL_ENABLE | TMR_CTL_IMASK | TMR_CTL_ISTATUS)) == 1155a1477da3SAlexander Graf (TMR_CTL_ENABLE | TMR_CTL_ISTATUS); 1156a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], irq_state); 1157a1477da3SAlexander Graf 1158a1477da3SAlexander Graf if (!irq_state) { 1159a1477da3SAlexander Graf /* Timer no longer asserting, we can unmask it */ 1160a1477da3SAlexander Graf hv_vcpu_set_vtimer_mask(cpu->hvf->fd, false); 1161a1477da3SAlexander Graf cpu->hvf->vtimer_masked = false; 1162a1477da3SAlexander Graf } 1163a1477da3SAlexander Graf } 1164a1477da3SAlexander Graf 1165a1477da3SAlexander Graf int hvf_vcpu_exec(CPUState *cpu) 1166a1477da3SAlexander Graf { 1167a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 1168a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 1169a1477da3SAlexander Graf hv_vcpu_exit_t *hvf_exit = cpu->hvf->exit; 1170a1477da3SAlexander Graf hv_return_t r; 1171a1477da3SAlexander Graf bool advance_pc = false; 1172a1477da3SAlexander Graf 1173a1477da3SAlexander Graf if (hvf_inject_interrupts(cpu)) { 1174a1477da3SAlexander Graf return EXCP_INTERRUPT; 1175a1477da3SAlexander Graf } 1176a1477da3SAlexander Graf 1177a1477da3SAlexander Graf if (cpu->halted) { 1178a1477da3SAlexander Graf return EXCP_HLT; 1179a1477da3SAlexander Graf } 1180a1477da3SAlexander Graf 1181a1477da3SAlexander Graf flush_cpu_state(cpu); 1182a1477da3SAlexander Graf 1183a1477da3SAlexander Graf qemu_mutex_unlock_iothread(); 1184a1477da3SAlexander Graf assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); 1185a1477da3SAlexander Graf 1186a1477da3SAlexander Graf /* handle VMEXIT */ 1187a1477da3SAlexander Graf uint64_t exit_reason = hvf_exit->reason; 1188a1477da3SAlexander Graf uint64_t syndrome = hvf_exit->exception.syndrome; 1189a1477da3SAlexander Graf uint32_t ec = syn_get_ec(syndrome); 1190a1477da3SAlexander Graf 1191a1477da3SAlexander Graf qemu_mutex_lock_iothread(); 1192a1477da3SAlexander Graf switch (exit_reason) { 1193a1477da3SAlexander Graf case HV_EXIT_REASON_EXCEPTION: 1194a1477da3SAlexander Graf /* This is the main one, handle below. */ 1195a1477da3SAlexander Graf break; 1196a1477da3SAlexander Graf case HV_EXIT_REASON_VTIMER_ACTIVATED: 1197a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); 1198a1477da3SAlexander Graf cpu->hvf->vtimer_masked = true; 1199a1477da3SAlexander Graf return 0; 1200a1477da3SAlexander Graf case HV_EXIT_REASON_CANCELED: 1201a1477da3SAlexander Graf /* we got kicked, no exit to process */ 1202a1477da3SAlexander Graf return 0; 1203a1477da3SAlexander Graf default: 1204d385a605SRichard Henderson g_assert_not_reached(); 1205a1477da3SAlexander Graf } 1206a1477da3SAlexander Graf 1207a1477da3SAlexander Graf hvf_sync_vtimer(cpu); 1208a1477da3SAlexander Graf 1209a1477da3SAlexander Graf switch (ec) { 1210a1477da3SAlexander Graf case EC_DATAABORT: { 1211a1477da3SAlexander Graf bool isv = syndrome & ARM_EL_ISV; 1212a1477da3SAlexander Graf bool iswrite = (syndrome >> 6) & 1; 1213a1477da3SAlexander Graf bool s1ptw = (syndrome >> 7) & 1; 1214a1477da3SAlexander Graf uint32_t sas = (syndrome >> 22) & 3; 1215a1477da3SAlexander Graf uint32_t len = 1 << sas; 1216a1477da3SAlexander Graf uint32_t srt = (syndrome >> 16) & 0x1f; 12175fd6a3e2SAlexander Graf uint32_t cm = (syndrome >> 8) & 0x1; 1218a1477da3SAlexander Graf uint64_t val = 0; 1219a1477da3SAlexander Graf 1220a1477da3SAlexander Graf trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address, 1221a1477da3SAlexander Graf hvf_exit->exception.physical_address, isv, 1222a1477da3SAlexander Graf iswrite, s1ptw, len, srt); 1223a1477da3SAlexander Graf 12245fd6a3e2SAlexander Graf if (cm) { 12255fd6a3e2SAlexander Graf /* We don't cache MMIO regions */ 12265fd6a3e2SAlexander Graf advance_pc = true; 12275fd6a3e2SAlexander Graf break; 12285fd6a3e2SAlexander Graf } 12295fd6a3e2SAlexander Graf 1230a1477da3SAlexander Graf assert(isv); 1231a1477da3SAlexander Graf 1232a1477da3SAlexander Graf if (iswrite) { 1233a1477da3SAlexander Graf val = hvf_get_reg(cpu, srt); 1234a1477da3SAlexander Graf address_space_write(&address_space_memory, 1235a1477da3SAlexander Graf hvf_exit->exception.physical_address, 1236a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 1237a1477da3SAlexander Graf } else { 1238a1477da3SAlexander Graf address_space_read(&address_space_memory, 1239a1477da3SAlexander Graf hvf_exit->exception.physical_address, 1240a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 1241a1477da3SAlexander Graf hvf_set_reg(cpu, srt, val); 1242a1477da3SAlexander Graf } 1243a1477da3SAlexander Graf 1244a1477da3SAlexander Graf advance_pc = true; 1245a1477da3SAlexander Graf break; 1246a1477da3SAlexander Graf } 1247a1477da3SAlexander Graf case EC_SYSTEMREGISTERTRAP: { 1248a1477da3SAlexander Graf bool isread = (syndrome >> 0) & 1; 1249a1477da3SAlexander Graf uint32_t rt = (syndrome >> 5) & 0x1f; 1250a1477da3SAlexander Graf uint32_t reg = syndrome & SYSREG_MASK; 1251a1477da3SAlexander Graf uint64_t val; 1252a1477da3SAlexander Graf int ret = 0; 1253a1477da3SAlexander Graf 1254a1477da3SAlexander Graf if (isread) { 1255a1477da3SAlexander Graf ret = hvf_sysreg_read(cpu, reg, rt); 1256a1477da3SAlexander Graf } else { 1257a1477da3SAlexander Graf val = hvf_get_reg(cpu, rt); 1258a1477da3SAlexander Graf ret = hvf_sysreg_write(cpu, reg, val); 1259a1477da3SAlexander Graf } 1260a1477da3SAlexander Graf 1261a1477da3SAlexander Graf advance_pc = !ret; 1262a1477da3SAlexander Graf break; 1263a1477da3SAlexander Graf } 1264a1477da3SAlexander Graf case EC_WFX_TRAP: 1265a1477da3SAlexander Graf advance_pc = true; 1266219c101fSPeter Collingbourne if (!(syndrome & WFX_IS_WFE)) { 1267219c101fSPeter Collingbourne hvf_wfi(cpu); 1268219c101fSPeter Collingbourne } 1269a1477da3SAlexander Graf break; 1270a1477da3SAlexander Graf case EC_AA64_HVC: 1271a1477da3SAlexander Graf cpu_synchronize_state(cpu); 12722c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) { 12732c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 1274a1477da3SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 1275a1477da3SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 1276a1477da3SAlexander Graf env->xregs[0] = -1; 12772c9c0bf9SAlexander Graf } 12782c9c0bf9SAlexander Graf } else { 12792c9c0bf9SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 12802c9c0bf9SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 12812c9c0bf9SAlexander Graf } 1282a1477da3SAlexander Graf break; 1283a1477da3SAlexander Graf case EC_AA64_SMC: 1284a1477da3SAlexander Graf cpu_synchronize_state(cpu); 12852c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) { 12862c9c0bf9SAlexander Graf advance_pc = true; 12872c9c0bf9SAlexander Graf 12882c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 12892c9c0bf9SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 12902c9c0bf9SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 12912c9c0bf9SAlexander Graf env->xregs[0] = -1; 12922c9c0bf9SAlexander Graf } 12932c9c0bf9SAlexander Graf } else { 1294a1477da3SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 1295a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 12962c9c0bf9SAlexander Graf } 1297a1477da3SAlexander Graf break; 1298a1477da3SAlexander Graf default: 1299a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1300a1477da3SAlexander Graf trace_hvf_exit(syndrome, ec, env->pc); 1301a1477da3SAlexander Graf error_report("0x%llx: unhandled exception ec=0x%x", env->pc, ec); 1302a1477da3SAlexander Graf } 1303a1477da3SAlexander Graf 1304a1477da3SAlexander Graf if (advance_pc) { 1305a1477da3SAlexander Graf uint64_t pc; 1306a1477da3SAlexander Graf 1307a1477da3SAlexander Graf flush_cpu_state(cpu); 1308a1477da3SAlexander Graf 1309a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_PC, &pc); 1310a1477da3SAlexander Graf assert_hvf_ok(r); 1311a1477da3SAlexander Graf pc += 4; 1312a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_PC, pc); 1313a1477da3SAlexander Graf assert_hvf_ok(r); 1314a1477da3SAlexander Graf } 1315a1477da3SAlexander Graf 1316a1477da3SAlexander Graf return 0; 1317a1477da3SAlexander Graf } 1318a1477da3SAlexander Graf 1319a1477da3SAlexander Graf static const VMStateDescription vmstate_hvf_vtimer = { 1320a1477da3SAlexander Graf .name = "hvf-vtimer", 1321a1477da3SAlexander Graf .version_id = 1, 1322a1477da3SAlexander Graf .minimum_version_id = 1, 1323a1477da3SAlexander Graf .fields = (VMStateField[]) { 1324a1477da3SAlexander Graf VMSTATE_UINT64(vtimer_val, HVFVTimer), 1325a1477da3SAlexander Graf VMSTATE_END_OF_LIST() 1326a1477da3SAlexander Graf }, 1327a1477da3SAlexander Graf }; 1328a1477da3SAlexander Graf 1329a1477da3SAlexander Graf static void hvf_vm_state_change(void *opaque, bool running, RunState state) 1330a1477da3SAlexander Graf { 1331a1477da3SAlexander Graf HVFVTimer *s = opaque; 1332a1477da3SAlexander Graf 1333a1477da3SAlexander Graf if (running) { 1334a1477da3SAlexander Graf /* Update vtimer offset on all CPUs */ 1335a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time() - s->vtimer_val; 1336a1477da3SAlexander Graf cpu_synchronize_all_states(); 1337a1477da3SAlexander Graf } else { 1338a1477da3SAlexander Graf /* Remember vtimer value on every pause */ 1339a1477da3SAlexander Graf s->vtimer_val = hvf_vtimer_val_raw(); 1340a1477da3SAlexander Graf } 1341a1477da3SAlexander Graf } 1342a1477da3SAlexander Graf 1343a1477da3SAlexander Graf int hvf_arch_init(void) 1344a1477da3SAlexander Graf { 1345a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time(); 1346a1477da3SAlexander Graf vmstate_register(NULL, 0, &vmstate_hvf_vtimer, &vtimer); 1347a1477da3SAlexander Graf qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer); 1348a1477da3SAlexander Graf return 0; 1349a1477da3SAlexander Graf } 1350