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-common.h" 14a1477da3SAlexander Graf #include "qemu/error-report.h" 15a1477da3SAlexander Graf 16a1477da3SAlexander Graf #include "sysemu/runstate.h" 17a1477da3SAlexander Graf #include "sysemu/hvf.h" 18a1477da3SAlexander Graf #include "sysemu/hvf_int.h" 19a1477da3SAlexander Graf #include "sysemu/hw_accel.h" 20585df85eSPeter Maydell #include "hvf_arm.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 38a1477da3SAlexander Graf #define SYSREG(op0, op1, crn, crm, op2) \ 39a1477da3SAlexander Graf ((op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (crm << 1)) 40a1477da3SAlexander Graf #define SYSREG_MASK SYSREG(0x3, 0x7, 0xf, 0xf, 0x7) 41a1477da3SAlexander Graf #define SYSREG_OSLAR_EL1 SYSREG(2, 0, 1, 0, 4) 42a1477da3SAlexander Graf #define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4) 43a1477da3SAlexander Graf #define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4) 44a1477da3SAlexander Graf #define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1) 45*dd43ac07SAlexander Graf #define SYSREG_PMCR_EL0 SYSREG(3, 3, 9, 12, 0) 46*dd43ac07SAlexander Graf #define SYSREG_PMUSERENR_EL0 SYSREG(3, 3, 9, 14, 0) 47*dd43ac07SAlexander Graf #define SYSREG_PMCNTENSET_EL0 SYSREG(3, 3, 9, 12, 1) 48*dd43ac07SAlexander Graf #define SYSREG_PMCNTENCLR_EL0 SYSREG(3, 3, 9, 12, 2) 49*dd43ac07SAlexander Graf #define SYSREG_PMINTENCLR_EL1 SYSREG(3, 0, 9, 14, 2) 50*dd43ac07SAlexander Graf #define SYSREG_PMOVSCLR_EL0 SYSREG(3, 3, 9, 12, 3) 51*dd43ac07SAlexander Graf #define SYSREG_PMSWINC_EL0 SYSREG(3, 3, 9, 12, 4) 52*dd43ac07SAlexander Graf #define SYSREG_PMSELR_EL0 SYSREG(3, 3, 9, 12, 5) 53*dd43ac07SAlexander Graf #define SYSREG_PMCEID0_EL0 SYSREG(3, 3, 9, 12, 6) 54*dd43ac07SAlexander Graf #define SYSREG_PMCEID1_EL0 SYSREG(3, 3, 9, 12, 7) 55*dd43ac07SAlexander Graf #define SYSREG_PMCCNTR_EL0 SYSREG(3, 3, 9, 13, 0) 56*dd43ac07SAlexander Graf #define SYSREG_PMCCFILTR_EL0 SYSREG(3, 3, 14, 15, 7) 57a1477da3SAlexander Graf 58a1477da3SAlexander Graf #define WFX_IS_WFE (1 << 0) 59a1477da3SAlexander Graf 60a1477da3SAlexander Graf #define TMR_CTL_ENABLE (1 << 0) 61a1477da3SAlexander Graf #define TMR_CTL_IMASK (1 << 1) 62a1477da3SAlexander Graf #define TMR_CTL_ISTATUS (1 << 2) 63a1477da3SAlexander Graf 642c9c0bf9SAlexander Graf static void hvf_wfi(CPUState *cpu); 652c9c0bf9SAlexander Graf 66a1477da3SAlexander Graf typedef struct HVFVTimer { 67a1477da3SAlexander Graf /* Vtimer value during migration and paused state */ 68a1477da3SAlexander Graf uint64_t vtimer_val; 69a1477da3SAlexander Graf } HVFVTimer; 70a1477da3SAlexander Graf 71a1477da3SAlexander Graf static HVFVTimer vtimer; 72a1477da3SAlexander Graf 73585df85eSPeter Maydell typedef struct ARMHostCPUFeatures { 74585df85eSPeter Maydell ARMISARegisters isar; 75585df85eSPeter Maydell uint64_t features; 76585df85eSPeter Maydell uint64_t midr; 77585df85eSPeter Maydell uint32_t reset_sctlr; 78585df85eSPeter Maydell const char *dtb_compatible; 79585df85eSPeter Maydell } ARMHostCPUFeatures; 80585df85eSPeter Maydell 81585df85eSPeter Maydell static ARMHostCPUFeatures arm_host_cpu_features; 82585df85eSPeter Maydell 83a1477da3SAlexander Graf struct hvf_reg_match { 84a1477da3SAlexander Graf int reg; 85a1477da3SAlexander Graf uint64_t offset; 86a1477da3SAlexander Graf }; 87a1477da3SAlexander Graf 88a1477da3SAlexander Graf static const struct hvf_reg_match hvf_reg_match[] = { 89a1477da3SAlexander Graf { HV_REG_X0, offsetof(CPUARMState, xregs[0]) }, 90a1477da3SAlexander Graf { HV_REG_X1, offsetof(CPUARMState, xregs[1]) }, 91a1477da3SAlexander Graf { HV_REG_X2, offsetof(CPUARMState, xregs[2]) }, 92a1477da3SAlexander Graf { HV_REG_X3, offsetof(CPUARMState, xregs[3]) }, 93a1477da3SAlexander Graf { HV_REG_X4, offsetof(CPUARMState, xregs[4]) }, 94a1477da3SAlexander Graf { HV_REG_X5, offsetof(CPUARMState, xregs[5]) }, 95a1477da3SAlexander Graf { HV_REG_X6, offsetof(CPUARMState, xregs[6]) }, 96a1477da3SAlexander Graf { HV_REG_X7, offsetof(CPUARMState, xregs[7]) }, 97a1477da3SAlexander Graf { HV_REG_X8, offsetof(CPUARMState, xregs[8]) }, 98a1477da3SAlexander Graf { HV_REG_X9, offsetof(CPUARMState, xregs[9]) }, 99a1477da3SAlexander Graf { HV_REG_X10, offsetof(CPUARMState, xregs[10]) }, 100a1477da3SAlexander Graf { HV_REG_X11, offsetof(CPUARMState, xregs[11]) }, 101a1477da3SAlexander Graf { HV_REG_X12, offsetof(CPUARMState, xregs[12]) }, 102a1477da3SAlexander Graf { HV_REG_X13, offsetof(CPUARMState, xregs[13]) }, 103a1477da3SAlexander Graf { HV_REG_X14, offsetof(CPUARMState, xregs[14]) }, 104a1477da3SAlexander Graf { HV_REG_X15, offsetof(CPUARMState, xregs[15]) }, 105a1477da3SAlexander Graf { HV_REG_X16, offsetof(CPUARMState, xregs[16]) }, 106a1477da3SAlexander Graf { HV_REG_X17, offsetof(CPUARMState, xregs[17]) }, 107a1477da3SAlexander Graf { HV_REG_X18, offsetof(CPUARMState, xregs[18]) }, 108a1477da3SAlexander Graf { HV_REG_X19, offsetof(CPUARMState, xregs[19]) }, 109a1477da3SAlexander Graf { HV_REG_X20, offsetof(CPUARMState, xregs[20]) }, 110a1477da3SAlexander Graf { HV_REG_X21, offsetof(CPUARMState, xregs[21]) }, 111a1477da3SAlexander Graf { HV_REG_X22, offsetof(CPUARMState, xregs[22]) }, 112a1477da3SAlexander Graf { HV_REG_X23, offsetof(CPUARMState, xregs[23]) }, 113a1477da3SAlexander Graf { HV_REG_X24, offsetof(CPUARMState, xregs[24]) }, 114a1477da3SAlexander Graf { HV_REG_X25, offsetof(CPUARMState, xregs[25]) }, 115a1477da3SAlexander Graf { HV_REG_X26, offsetof(CPUARMState, xregs[26]) }, 116a1477da3SAlexander Graf { HV_REG_X27, offsetof(CPUARMState, xregs[27]) }, 117a1477da3SAlexander Graf { HV_REG_X28, offsetof(CPUARMState, xregs[28]) }, 118a1477da3SAlexander Graf { HV_REG_X29, offsetof(CPUARMState, xregs[29]) }, 119a1477da3SAlexander Graf { HV_REG_X30, offsetof(CPUARMState, xregs[30]) }, 120a1477da3SAlexander Graf { HV_REG_PC, offsetof(CPUARMState, pc) }, 121a1477da3SAlexander Graf }; 122a1477da3SAlexander Graf 123a1477da3SAlexander Graf static const struct hvf_reg_match hvf_fpreg_match[] = { 124a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q0, offsetof(CPUARMState, vfp.zregs[0]) }, 125a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q1, offsetof(CPUARMState, vfp.zregs[1]) }, 126a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q2, offsetof(CPUARMState, vfp.zregs[2]) }, 127a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q3, offsetof(CPUARMState, vfp.zregs[3]) }, 128a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q4, offsetof(CPUARMState, vfp.zregs[4]) }, 129a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q5, offsetof(CPUARMState, vfp.zregs[5]) }, 130a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q6, offsetof(CPUARMState, vfp.zregs[6]) }, 131a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q7, offsetof(CPUARMState, vfp.zregs[7]) }, 132a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q8, offsetof(CPUARMState, vfp.zregs[8]) }, 133a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q9, offsetof(CPUARMState, vfp.zregs[9]) }, 134a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q10, offsetof(CPUARMState, vfp.zregs[10]) }, 135a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q11, offsetof(CPUARMState, vfp.zregs[11]) }, 136a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q12, offsetof(CPUARMState, vfp.zregs[12]) }, 137a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q13, offsetof(CPUARMState, vfp.zregs[13]) }, 138a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q14, offsetof(CPUARMState, vfp.zregs[14]) }, 139a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q15, offsetof(CPUARMState, vfp.zregs[15]) }, 140a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q16, offsetof(CPUARMState, vfp.zregs[16]) }, 141a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q17, offsetof(CPUARMState, vfp.zregs[17]) }, 142a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q18, offsetof(CPUARMState, vfp.zregs[18]) }, 143a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q19, offsetof(CPUARMState, vfp.zregs[19]) }, 144a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q20, offsetof(CPUARMState, vfp.zregs[20]) }, 145a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q21, offsetof(CPUARMState, vfp.zregs[21]) }, 146a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q22, offsetof(CPUARMState, vfp.zregs[22]) }, 147a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q23, offsetof(CPUARMState, vfp.zregs[23]) }, 148a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q24, offsetof(CPUARMState, vfp.zregs[24]) }, 149a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q25, offsetof(CPUARMState, vfp.zregs[25]) }, 150a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q26, offsetof(CPUARMState, vfp.zregs[26]) }, 151a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q27, offsetof(CPUARMState, vfp.zregs[27]) }, 152a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q28, offsetof(CPUARMState, vfp.zregs[28]) }, 153a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q29, offsetof(CPUARMState, vfp.zregs[29]) }, 154a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q30, offsetof(CPUARMState, vfp.zregs[30]) }, 155a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q31, offsetof(CPUARMState, vfp.zregs[31]) }, 156a1477da3SAlexander Graf }; 157a1477da3SAlexander Graf 158a1477da3SAlexander Graf struct hvf_sreg_match { 159a1477da3SAlexander Graf int reg; 160a1477da3SAlexander Graf uint32_t key; 161a1477da3SAlexander Graf uint32_t cp_idx; 162a1477da3SAlexander Graf }; 163a1477da3SAlexander Graf 164a1477da3SAlexander Graf static struct hvf_sreg_match hvf_sreg_match[] = { 165a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) }, 166a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) }, 167a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) }, 168a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) }, 169a1477da3SAlexander Graf 170a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) }, 171a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) }, 172a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) }, 173a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) }, 174a1477da3SAlexander Graf 175a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) }, 176a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) }, 177a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) }, 178a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) }, 179a1477da3SAlexander Graf 180a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) }, 181a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) }, 182a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) }, 183a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) }, 184a1477da3SAlexander Graf 185a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) }, 186a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) }, 187a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) }, 188a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) }, 189a1477da3SAlexander Graf 190a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) }, 191a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) }, 192a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) }, 193a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) }, 194a1477da3SAlexander Graf 195a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) }, 196a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) }, 197a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) }, 198a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) }, 199a1477da3SAlexander Graf 200a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) }, 201a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) }, 202a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) }, 203a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) }, 204a1477da3SAlexander Graf 205a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) }, 206a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) }, 207a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) }, 208a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) }, 209a1477da3SAlexander Graf 210a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) }, 211a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) }, 212a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) }, 213a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) }, 214a1477da3SAlexander Graf 215a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) }, 216a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) }, 217a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) }, 218a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) }, 219a1477da3SAlexander Graf 220a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) }, 221a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) }, 222a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) }, 223a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) }, 224a1477da3SAlexander Graf 225a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) }, 226a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) }, 227a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) }, 228a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) }, 229a1477da3SAlexander Graf 230a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) }, 231a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) }, 232a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) }, 233a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) }, 234a1477da3SAlexander Graf 235a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) }, 236a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) }, 237a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) }, 238a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) }, 239a1477da3SAlexander Graf 240a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) }, 241a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) }, 242a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) }, 243a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) }, 244a1477da3SAlexander Graf 245a1477da3SAlexander Graf #ifdef SYNC_NO_RAW_REGS 246a1477da3SAlexander Graf /* 247a1477da3SAlexander Graf * The registers below are manually synced on init because they are 248a1477da3SAlexander Graf * marked as NO_RAW. We still list them to make number space sync easier. 249a1477da3SAlexander Graf */ 250a1477da3SAlexander Graf { HV_SYS_REG_MDCCINT_EL1, HVF_SYSREG(0, 2, 2, 0, 0) }, 251a1477da3SAlexander Graf { HV_SYS_REG_MIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 0) }, 252a1477da3SAlexander Graf { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) }, 253a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) }, 254a1477da3SAlexander Graf #endif 255a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) }, 256a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) }, 257a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) }, 258a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) }, 259a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR1_EL1, HVF_SYSREG(0, 6, 3, 0, 1) }, 260a1477da3SAlexander Graf #ifdef SYNC_NO_MMFR0 261a1477da3SAlexander Graf /* We keep the hardware MMFR0 around. HW limits are there anyway */ 262a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR0_EL1, HVF_SYSREG(0, 7, 3, 0, 0) }, 263a1477da3SAlexander Graf #endif 264a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) }, 265a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) }, 266a1477da3SAlexander Graf 267a1477da3SAlexander Graf { HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) }, 268a1477da3SAlexander Graf { HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) }, 269a1477da3SAlexander Graf { HV_SYS_REG_CPACR_EL1, HVF_SYSREG(1, 0, 3, 0, 2) }, 270a1477da3SAlexander Graf { HV_SYS_REG_TTBR0_EL1, HVF_SYSREG(2, 0, 3, 0, 0) }, 271a1477da3SAlexander Graf { HV_SYS_REG_TTBR1_EL1, HVF_SYSREG(2, 0, 3, 0, 1) }, 272a1477da3SAlexander Graf { HV_SYS_REG_TCR_EL1, HVF_SYSREG(2, 0, 3, 0, 2) }, 273a1477da3SAlexander Graf 274a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 0) }, 275a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 1) }, 276a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 2) }, 277a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 3) }, 278a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 0) }, 279a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 1) }, 280a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 2) }, 281a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 3) }, 282a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYLO_EL1, HVF_SYSREG(2, 3, 3, 0, 0) }, 283a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYHI_EL1, HVF_SYSREG(2, 3, 3, 0, 1) }, 284a1477da3SAlexander Graf 285a1477da3SAlexander Graf { HV_SYS_REG_SPSR_EL1, HVF_SYSREG(4, 0, 3, 0, 0) }, 286a1477da3SAlexander Graf { HV_SYS_REG_ELR_EL1, HVF_SYSREG(4, 0, 3, 0, 1) }, 287a1477da3SAlexander Graf { HV_SYS_REG_SP_EL0, HVF_SYSREG(4, 1, 3, 0, 0) }, 288a1477da3SAlexander Graf { HV_SYS_REG_AFSR0_EL1, HVF_SYSREG(5, 1, 3, 0, 0) }, 289a1477da3SAlexander Graf { HV_SYS_REG_AFSR1_EL1, HVF_SYSREG(5, 1, 3, 0, 1) }, 290a1477da3SAlexander Graf { HV_SYS_REG_ESR_EL1, HVF_SYSREG(5, 2, 3, 0, 0) }, 291a1477da3SAlexander Graf { HV_SYS_REG_FAR_EL1, HVF_SYSREG(6, 0, 3, 0, 0) }, 292a1477da3SAlexander Graf { HV_SYS_REG_PAR_EL1, HVF_SYSREG(7, 4, 3, 0, 0) }, 293a1477da3SAlexander Graf { HV_SYS_REG_MAIR_EL1, HVF_SYSREG(10, 2, 3, 0, 0) }, 294a1477da3SAlexander Graf { HV_SYS_REG_AMAIR_EL1, HVF_SYSREG(10, 3, 3, 0, 0) }, 295a1477da3SAlexander Graf { HV_SYS_REG_VBAR_EL1, HVF_SYSREG(12, 0, 3, 0, 0) }, 296a1477da3SAlexander Graf { HV_SYS_REG_CONTEXTIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 1) }, 297a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 4) }, 298a1477da3SAlexander Graf { HV_SYS_REG_CNTKCTL_EL1, HVF_SYSREG(14, 1, 3, 0, 0) }, 299a1477da3SAlexander Graf { HV_SYS_REG_CSSELR_EL1, HVF_SYSREG(0, 0, 3, 2, 0) }, 300a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL0, HVF_SYSREG(13, 0, 3, 3, 2) }, 301a1477da3SAlexander Graf { HV_SYS_REG_TPIDRRO_EL0, HVF_SYSREG(13, 0, 3, 3, 3) }, 302a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CTL_EL0, HVF_SYSREG(14, 3, 3, 3, 1) }, 303a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CVAL_EL0, HVF_SYSREG(14, 3, 3, 3, 2) }, 304a1477da3SAlexander Graf { HV_SYS_REG_SP_EL1, HVF_SYSREG(4, 1, 3, 4, 0) }, 305a1477da3SAlexander Graf }; 306a1477da3SAlexander Graf 307a1477da3SAlexander Graf int hvf_get_registers(CPUState *cpu) 308a1477da3SAlexander Graf { 309a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 310a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 311a1477da3SAlexander Graf hv_return_t ret; 312a1477da3SAlexander Graf uint64_t val; 313a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 314a1477da3SAlexander Graf int i; 315a1477da3SAlexander Graf 316a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 317a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, hvf_reg_match[i].reg, &val); 318a1477da3SAlexander Graf *(uint64_t *)((void *)env + hvf_reg_match[i].offset) = val; 319a1477da3SAlexander Graf assert_hvf_ok(ret); 320a1477da3SAlexander Graf } 321a1477da3SAlexander Graf 322a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 323a1477da3SAlexander Graf ret = hv_vcpu_get_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 324a1477da3SAlexander Graf &fpval); 325a1477da3SAlexander Graf memcpy((void *)env + hvf_fpreg_match[i].offset, &fpval, sizeof(fpval)); 326a1477da3SAlexander Graf assert_hvf_ok(ret); 327a1477da3SAlexander Graf } 328a1477da3SAlexander Graf 329a1477da3SAlexander Graf val = 0; 330a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPCR, &val); 331a1477da3SAlexander Graf assert_hvf_ok(ret); 332a1477da3SAlexander Graf vfp_set_fpcr(env, val); 333a1477da3SAlexander Graf 334a1477da3SAlexander Graf val = 0; 335a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPSR, &val); 336a1477da3SAlexander Graf assert_hvf_ok(ret); 337a1477da3SAlexander Graf vfp_set_fpsr(env, val); 338a1477da3SAlexander Graf 339a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_CPSR, &val); 340a1477da3SAlexander Graf assert_hvf_ok(ret); 341a1477da3SAlexander Graf pstate_write(env, val); 342a1477da3SAlexander Graf 343a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 344a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 345a1477da3SAlexander Graf continue; 346a1477da3SAlexander Graf } 347a1477da3SAlexander Graf 348a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, &val); 349a1477da3SAlexander Graf assert_hvf_ok(ret); 350a1477da3SAlexander Graf 351a1477da3SAlexander Graf arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx] = val; 352a1477da3SAlexander Graf } 353a1477da3SAlexander Graf assert(write_list_to_cpustate(arm_cpu)); 354a1477da3SAlexander Graf 355a1477da3SAlexander Graf aarch64_restore_sp(env, arm_current_el(env)); 356a1477da3SAlexander Graf 357a1477da3SAlexander Graf return 0; 358a1477da3SAlexander Graf } 359a1477da3SAlexander Graf 360a1477da3SAlexander Graf int hvf_put_registers(CPUState *cpu) 361a1477da3SAlexander Graf { 362a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 363a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 364a1477da3SAlexander Graf hv_return_t ret; 365a1477da3SAlexander Graf uint64_t val; 366a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 367a1477da3SAlexander Graf int i; 368a1477da3SAlexander Graf 369a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 370a1477da3SAlexander Graf val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset); 371a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, hvf_reg_match[i].reg, val); 372a1477da3SAlexander Graf assert_hvf_ok(ret); 373a1477da3SAlexander Graf } 374a1477da3SAlexander Graf 375a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 376a1477da3SAlexander Graf memcpy(&fpval, (void *)env + hvf_fpreg_match[i].offset, sizeof(fpval)); 377a1477da3SAlexander Graf ret = hv_vcpu_set_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 378a1477da3SAlexander Graf fpval); 379a1477da3SAlexander Graf assert_hvf_ok(ret); 380a1477da3SAlexander Graf } 381a1477da3SAlexander Graf 382a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPCR, vfp_get_fpcr(env)); 383a1477da3SAlexander Graf assert_hvf_ok(ret); 384a1477da3SAlexander Graf 385a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPSR, vfp_get_fpsr(env)); 386a1477da3SAlexander Graf assert_hvf_ok(ret); 387a1477da3SAlexander Graf 388a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_CPSR, pstate_read(env)); 389a1477da3SAlexander Graf assert_hvf_ok(ret); 390a1477da3SAlexander Graf 391a1477da3SAlexander Graf aarch64_save_sp(env, arm_current_el(env)); 392a1477da3SAlexander Graf 393a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 394a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 395a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 396a1477da3SAlexander Graf continue; 397a1477da3SAlexander Graf } 398a1477da3SAlexander Graf 399a1477da3SAlexander Graf val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx]; 400a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val); 401a1477da3SAlexander Graf assert_hvf_ok(ret); 402a1477da3SAlexander Graf } 403a1477da3SAlexander Graf 404a1477da3SAlexander Graf ret = hv_vcpu_set_vtimer_offset(cpu->hvf->fd, hvf_state->vtimer_offset); 405a1477da3SAlexander Graf assert_hvf_ok(ret); 406a1477da3SAlexander Graf 407a1477da3SAlexander Graf return 0; 408a1477da3SAlexander Graf } 409a1477da3SAlexander Graf 410a1477da3SAlexander Graf static void flush_cpu_state(CPUState *cpu) 411a1477da3SAlexander Graf { 412a1477da3SAlexander Graf if (cpu->vcpu_dirty) { 413a1477da3SAlexander Graf hvf_put_registers(cpu); 414a1477da3SAlexander Graf cpu->vcpu_dirty = false; 415a1477da3SAlexander Graf } 416a1477da3SAlexander Graf } 417a1477da3SAlexander Graf 418a1477da3SAlexander Graf static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val) 419a1477da3SAlexander Graf { 420a1477da3SAlexander Graf hv_return_t r; 421a1477da3SAlexander Graf 422a1477da3SAlexander Graf flush_cpu_state(cpu); 423a1477da3SAlexander Graf 424a1477da3SAlexander Graf if (rt < 31) { 425a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_X0 + rt, val); 426a1477da3SAlexander Graf assert_hvf_ok(r); 427a1477da3SAlexander Graf } 428a1477da3SAlexander Graf } 429a1477da3SAlexander Graf 430a1477da3SAlexander Graf static uint64_t hvf_get_reg(CPUState *cpu, int rt) 431a1477da3SAlexander Graf { 432a1477da3SAlexander Graf uint64_t val = 0; 433a1477da3SAlexander Graf hv_return_t r; 434a1477da3SAlexander Graf 435a1477da3SAlexander Graf flush_cpu_state(cpu); 436a1477da3SAlexander Graf 437a1477da3SAlexander Graf if (rt < 31) { 438a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_X0 + rt, &val); 439a1477da3SAlexander Graf assert_hvf_ok(r); 440a1477da3SAlexander Graf } 441a1477da3SAlexander Graf 442a1477da3SAlexander Graf return val; 443a1477da3SAlexander Graf } 444a1477da3SAlexander Graf 445585df85eSPeter Maydell static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 446585df85eSPeter Maydell { 447585df85eSPeter Maydell ARMISARegisters host_isar = {}; 448585df85eSPeter Maydell const struct isar_regs { 449585df85eSPeter Maydell int reg; 450585df85eSPeter Maydell uint64_t *val; 451585df85eSPeter Maydell } regs[] = { 452585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, 453585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, 454585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, 455585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, 456585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, 457585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, 458585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, 459585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, 460585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, 461585df85eSPeter Maydell }; 462585df85eSPeter Maydell hv_vcpu_t fd; 463585df85eSPeter Maydell hv_return_t r = HV_SUCCESS; 464585df85eSPeter Maydell hv_vcpu_exit_t *exit; 465585df85eSPeter Maydell int i; 466585df85eSPeter Maydell 467585df85eSPeter Maydell ahcf->dtb_compatible = "arm,arm-v8"; 468585df85eSPeter Maydell ahcf->features = (1ULL << ARM_FEATURE_V8) | 469585df85eSPeter Maydell (1ULL << ARM_FEATURE_NEON) | 470585df85eSPeter Maydell (1ULL << ARM_FEATURE_AARCH64) | 471585df85eSPeter Maydell (1ULL << ARM_FEATURE_PMU) | 472585df85eSPeter Maydell (1ULL << ARM_FEATURE_GENERIC_TIMER); 473585df85eSPeter Maydell 474585df85eSPeter Maydell /* We set up a small vcpu to extract host registers */ 475585df85eSPeter Maydell 476585df85eSPeter Maydell if (hv_vcpu_create(&fd, &exit, NULL) != HV_SUCCESS) { 477585df85eSPeter Maydell return false; 478585df85eSPeter Maydell } 479585df85eSPeter Maydell 480585df85eSPeter Maydell for (i = 0; i < ARRAY_SIZE(regs); i++) { 481585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val); 482585df85eSPeter Maydell } 483585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr); 484585df85eSPeter Maydell r |= hv_vcpu_destroy(fd); 485585df85eSPeter Maydell 486585df85eSPeter Maydell ahcf->isar = host_isar; 487585df85eSPeter Maydell 488585df85eSPeter Maydell /* 489585df85eSPeter Maydell * A scratch vCPU returns SCTLR 0, so let's fill our default with the M1 490585df85eSPeter Maydell * boot SCTLR from https://github.com/AsahiLinux/m1n1/issues/97 491585df85eSPeter Maydell */ 492585df85eSPeter Maydell ahcf->reset_sctlr = 0x30100180; 493585df85eSPeter Maydell /* 494585df85eSPeter Maydell * SPAN is disabled by default when SCTLR.SPAN=1. To improve compatibility, 495585df85eSPeter Maydell * let's disable it on boot and then allow guest software to turn it on by 496585df85eSPeter Maydell * setting it to 0. 497585df85eSPeter Maydell */ 498585df85eSPeter Maydell ahcf->reset_sctlr |= 0x00800000; 499585df85eSPeter Maydell 500585df85eSPeter Maydell /* Make sure we don't advertise AArch32 support for EL0/EL1 */ 501585df85eSPeter Maydell if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) { 502585df85eSPeter Maydell return false; 503585df85eSPeter Maydell } 504585df85eSPeter Maydell 505585df85eSPeter Maydell return r == HV_SUCCESS; 506585df85eSPeter Maydell } 507585df85eSPeter Maydell 508585df85eSPeter Maydell void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu) 509585df85eSPeter Maydell { 510585df85eSPeter Maydell if (!arm_host_cpu_features.dtb_compatible) { 511585df85eSPeter Maydell if (!hvf_enabled() || 512585df85eSPeter Maydell !hvf_arm_get_host_cpu_features(&arm_host_cpu_features)) { 513585df85eSPeter Maydell /* 514585df85eSPeter Maydell * We can't report this error yet, so flag that we need to 515585df85eSPeter Maydell * in arm_cpu_realizefn(). 516585df85eSPeter Maydell */ 517585df85eSPeter Maydell cpu->host_cpu_probe_failed = true; 518585df85eSPeter Maydell return; 519585df85eSPeter Maydell } 520585df85eSPeter Maydell } 521585df85eSPeter Maydell 522585df85eSPeter Maydell cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 523585df85eSPeter Maydell cpu->isar = arm_host_cpu_features.isar; 524585df85eSPeter Maydell cpu->env.features = arm_host_cpu_features.features; 525585df85eSPeter Maydell cpu->midr = arm_host_cpu_features.midr; 526585df85eSPeter Maydell cpu->reset_sctlr = arm_host_cpu_features.reset_sctlr; 527585df85eSPeter Maydell } 528585df85eSPeter Maydell 529a1477da3SAlexander Graf void hvf_arch_vcpu_destroy(CPUState *cpu) 530a1477da3SAlexander Graf { 531a1477da3SAlexander Graf } 532a1477da3SAlexander Graf 533a1477da3SAlexander Graf int hvf_arch_init_vcpu(CPUState *cpu) 534a1477da3SAlexander Graf { 535a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 536a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 537a1477da3SAlexander Graf uint32_t sregs_match_len = ARRAY_SIZE(hvf_sreg_match); 538a1477da3SAlexander Graf uint32_t sregs_cnt = 0; 539a1477da3SAlexander Graf uint64_t pfr; 540a1477da3SAlexander Graf hv_return_t ret; 541a1477da3SAlexander Graf int i; 542a1477da3SAlexander Graf 543a1477da3SAlexander Graf env->aarch64 = 1; 544a1477da3SAlexander Graf asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz)); 545a1477da3SAlexander Graf 546a1477da3SAlexander Graf /* Allocate enough space for our sysreg sync */ 547a1477da3SAlexander Graf arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes, 548a1477da3SAlexander Graf sregs_match_len); 549a1477da3SAlexander Graf arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values, 550a1477da3SAlexander Graf sregs_match_len); 551a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t, 552a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes, 553a1477da3SAlexander Graf sregs_match_len); 554a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values = g_renew(uint64_t, 555a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values, 556a1477da3SAlexander Graf sregs_match_len); 557a1477da3SAlexander Graf 558a1477da3SAlexander Graf memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t)); 559a1477da3SAlexander Graf 560a1477da3SAlexander Graf /* Populate cp list for all known sysregs */ 561a1477da3SAlexander Graf for (i = 0; i < sregs_match_len; i++) { 562a1477da3SAlexander Graf const ARMCPRegInfo *ri; 563a1477da3SAlexander Graf uint32_t key = hvf_sreg_match[i].key; 564a1477da3SAlexander Graf 565a1477da3SAlexander Graf ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key); 566a1477da3SAlexander Graf if (ri) { 567a1477da3SAlexander Graf assert(!(ri->type & ARM_CP_NO_RAW)); 568a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = sregs_cnt; 569a1477da3SAlexander Graf arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key); 570a1477da3SAlexander Graf } else { 571a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = -1; 572a1477da3SAlexander Graf } 573a1477da3SAlexander Graf } 574a1477da3SAlexander Graf arm_cpu->cpreg_array_len = sregs_cnt; 575a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_array_len = sregs_cnt; 576a1477da3SAlexander Graf 577a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 578a1477da3SAlexander Graf 579a1477da3SAlexander Graf /* Set CP_NO_RAW system registers on init */ 580a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MIDR_EL1, 581a1477da3SAlexander Graf arm_cpu->midr); 582a1477da3SAlexander Graf assert_hvf_ok(ret); 583a1477da3SAlexander Graf 584a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MPIDR_EL1, 585a1477da3SAlexander Graf arm_cpu->mp_affinity); 586a1477da3SAlexander Graf assert_hvf_ok(ret); 587a1477da3SAlexander Graf 588a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, &pfr); 589a1477da3SAlexander Graf assert_hvf_ok(ret); 590a1477da3SAlexander Graf pfr |= env->gicv3state ? (1 << 24) : 0; 591a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, pfr); 592a1477da3SAlexander Graf assert_hvf_ok(ret); 593a1477da3SAlexander Graf 594a1477da3SAlexander Graf /* We're limited to underlying hardware caps, override internal versions */ 595a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, 596a1477da3SAlexander Graf &arm_cpu->isar.id_aa64mmfr0); 597a1477da3SAlexander Graf assert_hvf_ok(ret); 598a1477da3SAlexander Graf 599a1477da3SAlexander Graf return 0; 600a1477da3SAlexander Graf } 601a1477da3SAlexander Graf 602a1477da3SAlexander Graf void hvf_kick_vcpu_thread(CPUState *cpu) 603a1477da3SAlexander Graf { 604219c101fSPeter Collingbourne cpus_kick_thread(cpu); 605a1477da3SAlexander Graf hv_vcpus_exit(&cpu->hvf->fd, 1); 606a1477da3SAlexander Graf } 607a1477da3SAlexander Graf 608a1477da3SAlexander Graf static void hvf_raise_exception(CPUState *cpu, uint32_t excp, 609a1477da3SAlexander Graf uint32_t syndrome) 610a1477da3SAlexander Graf { 611a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 612a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 613a1477da3SAlexander Graf 614a1477da3SAlexander Graf cpu->exception_index = excp; 615a1477da3SAlexander Graf env->exception.target_el = 1; 616a1477da3SAlexander Graf env->exception.syndrome = syndrome; 617a1477da3SAlexander Graf 618a1477da3SAlexander Graf arm_cpu_do_interrupt(cpu); 619a1477da3SAlexander Graf } 620a1477da3SAlexander Graf 6212c9c0bf9SAlexander Graf static void hvf_psci_cpu_off(ARMCPU *arm_cpu) 6222c9c0bf9SAlexander Graf { 6232c9c0bf9SAlexander Graf int32_t ret = arm_set_cpu_off(arm_cpu->mp_affinity); 6242c9c0bf9SAlexander Graf assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS); 6252c9c0bf9SAlexander Graf } 6262c9c0bf9SAlexander Graf 6272c9c0bf9SAlexander Graf /* 6282c9c0bf9SAlexander Graf * Handle a PSCI call. 6292c9c0bf9SAlexander Graf * 6302c9c0bf9SAlexander Graf * Returns 0 on success 6312c9c0bf9SAlexander Graf * -1 when the PSCI call is unknown, 6322c9c0bf9SAlexander Graf */ 6332c9c0bf9SAlexander Graf static bool hvf_handle_psci_call(CPUState *cpu) 6342c9c0bf9SAlexander Graf { 6352c9c0bf9SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 6362c9c0bf9SAlexander Graf CPUARMState *env = &arm_cpu->env; 6372c9c0bf9SAlexander Graf uint64_t param[4] = { 6382c9c0bf9SAlexander Graf env->xregs[0], 6392c9c0bf9SAlexander Graf env->xregs[1], 6402c9c0bf9SAlexander Graf env->xregs[2], 6412c9c0bf9SAlexander Graf env->xregs[3] 6422c9c0bf9SAlexander Graf }; 6432c9c0bf9SAlexander Graf uint64_t context_id, mpidr; 6442c9c0bf9SAlexander Graf bool target_aarch64 = true; 6452c9c0bf9SAlexander Graf CPUState *target_cpu_state; 6462c9c0bf9SAlexander Graf ARMCPU *target_cpu; 6472c9c0bf9SAlexander Graf target_ulong entry; 6482c9c0bf9SAlexander Graf int target_el = 1; 6492c9c0bf9SAlexander Graf int32_t ret = 0; 6502c9c0bf9SAlexander Graf 6512c9c0bf9SAlexander Graf trace_hvf_psci_call(param[0], param[1], param[2], param[3], 6522c9c0bf9SAlexander Graf arm_cpu->mp_affinity); 6532c9c0bf9SAlexander Graf 6542c9c0bf9SAlexander Graf switch (param[0]) { 6552c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_PSCI_VERSION: 6562c9c0bf9SAlexander Graf ret = QEMU_PSCI_0_2_RET_VERSION_0_2; 6572c9c0bf9SAlexander Graf break; 6582c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 6592c9c0bf9SAlexander Graf ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ 6602c9c0bf9SAlexander Graf break; 6612c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 6622c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 6632c9c0bf9SAlexander Graf mpidr = param[1]; 6642c9c0bf9SAlexander Graf 6652c9c0bf9SAlexander Graf switch (param[2]) { 6662c9c0bf9SAlexander Graf case 0: 6672c9c0bf9SAlexander Graf target_cpu_state = arm_get_cpu_by_id(mpidr); 6682c9c0bf9SAlexander Graf if (!target_cpu_state) { 6692c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 6702c9c0bf9SAlexander Graf break; 6712c9c0bf9SAlexander Graf } 6722c9c0bf9SAlexander Graf target_cpu = ARM_CPU(target_cpu_state); 6732c9c0bf9SAlexander Graf 6742c9c0bf9SAlexander Graf ret = target_cpu->power_state; 6752c9c0bf9SAlexander Graf break; 6762c9c0bf9SAlexander Graf default: 6772c9c0bf9SAlexander Graf /* Everything above affinity level 0 is always on. */ 6782c9c0bf9SAlexander Graf ret = 0; 6792c9c0bf9SAlexander Graf } 6802c9c0bf9SAlexander Graf break; 6812c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 6822c9c0bf9SAlexander Graf qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 6832c9c0bf9SAlexander Graf /* 6842c9c0bf9SAlexander Graf * QEMU reset and shutdown are async requests, but PSCI 6852c9c0bf9SAlexander Graf * mandates that we never return from the reset/shutdown 6862c9c0bf9SAlexander Graf * call, so power the CPU off now so it doesn't execute 6872c9c0bf9SAlexander Graf * anything further. 6882c9c0bf9SAlexander Graf */ 6892c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 6902c9c0bf9SAlexander Graf break; 6912c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 6922c9c0bf9SAlexander Graf qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 6932c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 6942c9c0bf9SAlexander Graf break; 6952c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_ON: 6962c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_ON: 6972c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_ON: 6982c9c0bf9SAlexander Graf mpidr = param[1]; 6992c9c0bf9SAlexander Graf entry = param[2]; 7002c9c0bf9SAlexander Graf context_id = param[3]; 7012c9c0bf9SAlexander Graf ret = arm_set_cpu_on(mpidr, entry, context_id, 7022c9c0bf9SAlexander Graf target_el, target_aarch64); 7032c9c0bf9SAlexander Graf break; 7042c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_OFF: 7052c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_OFF: 7062c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 7072c9c0bf9SAlexander Graf break; 7082c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 7092c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 7102c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 7112c9c0bf9SAlexander Graf /* Affinity levels are not supported in QEMU */ 7122c9c0bf9SAlexander Graf if (param[1] & 0xfffe0000) { 7132c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 7142c9c0bf9SAlexander Graf break; 7152c9c0bf9SAlexander Graf } 7162c9c0bf9SAlexander Graf /* Powerdown is not supported, we always go into WFI */ 7172c9c0bf9SAlexander Graf env->xregs[0] = 0; 7182c9c0bf9SAlexander Graf hvf_wfi(cpu); 7192c9c0bf9SAlexander Graf break; 7202c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_MIGRATE: 7212c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE: 7222c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_NOT_SUPPORTED; 7232c9c0bf9SAlexander Graf break; 7242c9c0bf9SAlexander Graf default: 7252c9c0bf9SAlexander Graf return false; 7262c9c0bf9SAlexander Graf } 7272c9c0bf9SAlexander Graf 7282c9c0bf9SAlexander Graf env->xregs[0] = ret; 7292c9c0bf9SAlexander Graf return true; 7302c9c0bf9SAlexander Graf } 7312c9c0bf9SAlexander Graf 732a1477da3SAlexander Graf static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt) 733a1477da3SAlexander Graf { 734a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 735a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 736a1477da3SAlexander Graf uint64_t val = 0; 737a1477da3SAlexander Graf 738a1477da3SAlexander Graf switch (reg) { 739a1477da3SAlexander Graf case SYSREG_CNTPCT_EL0: 740a1477da3SAlexander Graf val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 741a1477da3SAlexander Graf gt_cntfrq_period_ns(arm_cpu); 742a1477da3SAlexander Graf break; 743*dd43ac07SAlexander Graf case SYSREG_PMCR_EL0: 744*dd43ac07SAlexander Graf val = env->cp15.c9_pmcr; 745*dd43ac07SAlexander Graf break; 746*dd43ac07SAlexander Graf case SYSREG_PMCCNTR_EL0: 747*dd43ac07SAlexander Graf pmu_op_start(env); 748*dd43ac07SAlexander Graf val = env->cp15.c15_ccnt; 749*dd43ac07SAlexander Graf pmu_op_finish(env); 750*dd43ac07SAlexander Graf break; 751*dd43ac07SAlexander Graf case SYSREG_PMCNTENCLR_EL0: 752*dd43ac07SAlexander Graf val = env->cp15.c9_pmcnten; 753*dd43ac07SAlexander Graf break; 754*dd43ac07SAlexander Graf case SYSREG_PMOVSCLR_EL0: 755*dd43ac07SAlexander Graf val = env->cp15.c9_pmovsr; 756*dd43ac07SAlexander Graf break; 757*dd43ac07SAlexander Graf case SYSREG_PMSELR_EL0: 758*dd43ac07SAlexander Graf val = env->cp15.c9_pmselr; 759*dd43ac07SAlexander Graf break; 760*dd43ac07SAlexander Graf case SYSREG_PMINTENCLR_EL1: 761*dd43ac07SAlexander Graf val = env->cp15.c9_pminten; 762*dd43ac07SAlexander Graf break; 763*dd43ac07SAlexander Graf case SYSREG_PMCCFILTR_EL0: 764*dd43ac07SAlexander Graf val = env->cp15.pmccfiltr_el0; 765*dd43ac07SAlexander Graf break; 766*dd43ac07SAlexander Graf case SYSREG_PMCNTENSET_EL0: 767*dd43ac07SAlexander Graf val = env->cp15.c9_pmcnten; 768*dd43ac07SAlexander Graf break; 769*dd43ac07SAlexander Graf case SYSREG_PMUSERENR_EL0: 770*dd43ac07SAlexander Graf val = env->cp15.c9_pmuserenr; 771*dd43ac07SAlexander Graf break; 772*dd43ac07SAlexander Graf case SYSREG_PMCEID0_EL0: 773*dd43ac07SAlexander Graf case SYSREG_PMCEID1_EL0: 774*dd43ac07SAlexander Graf /* We can't really count anything yet, declare all events invalid */ 775*dd43ac07SAlexander Graf val = 0; 776*dd43ac07SAlexander Graf break; 777a1477da3SAlexander Graf case SYSREG_OSLSR_EL1: 778a1477da3SAlexander Graf val = env->cp15.oslsr_el1; 779a1477da3SAlexander Graf break; 780a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 781a1477da3SAlexander Graf /* Dummy register */ 782a1477da3SAlexander Graf break; 783a1477da3SAlexander Graf default: 784a1477da3SAlexander Graf cpu_synchronize_state(cpu); 785a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_read(env->pc, reg, 786a1477da3SAlexander Graf (reg >> 20) & 0x3, 787a1477da3SAlexander Graf (reg >> 14) & 0x7, 788a1477da3SAlexander Graf (reg >> 10) & 0xf, 789a1477da3SAlexander Graf (reg >> 1) & 0xf, 790a1477da3SAlexander Graf (reg >> 17) & 0x7); 791a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 792a1477da3SAlexander Graf return 1; 793a1477da3SAlexander Graf } 794a1477da3SAlexander Graf 795a1477da3SAlexander Graf trace_hvf_sysreg_read(reg, 796a1477da3SAlexander Graf (reg >> 20) & 0x3, 797a1477da3SAlexander Graf (reg >> 14) & 0x7, 798a1477da3SAlexander Graf (reg >> 10) & 0xf, 799a1477da3SAlexander Graf (reg >> 1) & 0xf, 800a1477da3SAlexander Graf (reg >> 17) & 0x7, 801a1477da3SAlexander Graf val); 802a1477da3SAlexander Graf hvf_set_reg(cpu, rt, val); 803a1477da3SAlexander Graf 804a1477da3SAlexander Graf return 0; 805a1477da3SAlexander Graf } 806a1477da3SAlexander Graf 807*dd43ac07SAlexander Graf static void pmu_update_irq(CPUARMState *env) 808*dd43ac07SAlexander Graf { 809*dd43ac07SAlexander Graf ARMCPU *cpu = env_archcpu(env); 810*dd43ac07SAlexander Graf qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) && 811*dd43ac07SAlexander Graf (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); 812*dd43ac07SAlexander Graf } 813*dd43ac07SAlexander Graf 814*dd43ac07SAlexander Graf static bool pmu_event_supported(uint16_t number) 815*dd43ac07SAlexander Graf { 816*dd43ac07SAlexander Graf return false; 817*dd43ac07SAlexander Graf } 818*dd43ac07SAlexander Graf 819*dd43ac07SAlexander Graf /* Returns true if the counter (pass 31 for PMCCNTR) should count events using 820*dd43ac07SAlexander Graf * the current EL, security state, and register configuration. 821*dd43ac07SAlexander Graf */ 822*dd43ac07SAlexander Graf static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) 823*dd43ac07SAlexander Graf { 824*dd43ac07SAlexander Graf uint64_t filter; 825*dd43ac07SAlexander Graf bool enabled, filtered = true; 826*dd43ac07SAlexander Graf int el = arm_current_el(env); 827*dd43ac07SAlexander Graf 828*dd43ac07SAlexander Graf enabled = (env->cp15.c9_pmcr & PMCRE) && 829*dd43ac07SAlexander Graf (env->cp15.c9_pmcnten & (1 << counter)); 830*dd43ac07SAlexander Graf 831*dd43ac07SAlexander Graf if (counter == 31) { 832*dd43ac07SAlexander Graf filter = env->cp15.pmccfiltr_el0; 833*dd43ac07SAlexander Graf } else { 834*dd43ac07SAlexander Graf filter = env->cp15.c14_pmevtyper[counter]; 835*dd43ac07SAlexander Graf } 836*dd43ac07SAlexander Graf 837*dd43ac07SAlexander Graf if (el == 0) { 838*dd43ac07SAlexander Graf filtered = filter & PMXEVTYPER_U; 839*dd43ac07SAlexander Graf } else if (el == 1) { 840*dd43ac07SAlexander Graf filtered = filter & PMXEVTYPER_P; 841*dd43ac07SAlexander Graf } 842*dd43ac07SAlexander Graf 843*dd43ac07SAlexander Graf if (counter != 31) { 844*dd43ac07SAlexander Graf /* 845*dd43ac07SAlexander Graf * If not checking PMCCNTR, ensure the counter is setup to an event we 846*dd43ac07SAlexander Graf * support 847*dd43ac07SAlexander Graf */ 848*dd43ac07SAlexander Graf uint16_t event = filter & PMXEVTYPER_EVTCOUNT; 849*dd43ac07SAlexander Graf if (!pmu_event_supported(event)) { 850*dd43ac07SAlexander Graf return false; 851*dd43ac07SAlexander Graf } 852*dd43ac07SAlexander Graf } 853*dd43ac07SAlexander Graf 854*dd43ac07SAlexander Graf return enabled && !filtered; 855*dd43ac07SAlexander Graf } 856*dd43ac07SAlexander Graf 857*dd43ac07SAlexander Graf static void pmswinc_write(CPUARMState *env, uint64_t value) 858*dd43ac07SAlexander Graf { 859*dd43ac07SAlexander Graf unsigned int i; 860*dd43ac07SAlexander Graf for (i = 0; i < pmu_num_counters(env); i++) { 861*dd43ac07SAlexander Graf /* Increment a counter's count iff: */ 862*dd43ac07SAlexander Graf if ((value & (1 << i)) && /* counter's bit is set */ 863*dd43ac07SAlexander Graf /* counter is enabled and not filtered */ 864*dd43ac07SAlexander Graf pmu_counter_enabled(env, i) && 865*dd43ac07SAlexander Graf /* counter is SW_INCR */ 866*dd43ac07SAlexander Graf (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) == 0x0) { 867*dd43ac07SAlexander Graf /* 868*dd43ac07SAlexander Graf * Detect if this write causes an overflow since we can't predict 869*dd43ac07SAlexander Graf * PMSWINC overflows like we can for other events 870*dd43ac07SAlexander Graf */ 871*dd43ac07SAlexander Graf uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1; 872*dd43ac07SAlexander Graf 873*dd43ac07SAlexander Graf if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) { 874*dd43ac07SAlexander Graf env->cp15.c9_pmovsr |= (1 << i); 875*dd43ac07SAlexander Graf pmu_update_irq(env); 876*dd43ac07SAlexander Graf } 877*dd43ac07SAlexander Graf 878*dd43ac07SAlexander Graf env->cp15.c14_pmevcntr[i] = new_pmswinc; 879*dd43ac07SAlexander Graf } 880*dd43ac07SAlexander Graf } 881*dd43ac07SAlexander Graf } 882*dd43ac07SAlexander Graf 883a1477da3SAlexander Graf static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) 884a1477da3SAlexander Graf { 885a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 886a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 887a1477da3SAlexander Graf 888a1477da3SAlexander Graf trace_hvf_sysreg_write(reg, 889a1477da3SAlexander Graf (reg >> 20) & 0x3, 890a1477da3SAlexander Graf (reg >> 14) & 0x7, 891a1477da3SAlexander Graf (reg >> 10) & 0xf, 892a1477da3SAlexander Graf (reg >> 1) & 0xf, 893a1477da3SAlexander Graf (reg >> 17) & 0x7, 894a1477da3SAlexander Graf val); 895a1477da3SAlexander Graf 896a1477da3SAlexander Graf switch (reg) { 897*dd43ac07SAlexander Graf case SYSREG_PMCCNTR_EL0: 898*dd43ac07SAlexander Graf pmu_op_start(env); 899*dd43ac07SAlexander Graf env->cp15.c15_ccnt = val; 900*dd43ac07SAlexander Graf pmu_op_finish(env); 901*dd43ac07SAlexander Graf break; 902*dd43ac07SAlexander Graf case SYSREG_PMCR_EL0: 903*dd43ac07SAlexander Graf pmu_op_start(env); 904*dd43ac07SAlexander Graf 905*dd43ac07SAlexander Graf if (val & PMCRC) { 906*dd43ac07SAlexander Graf /* The counter has been reset */ 907*dd43ac07SAlexander Graf env->cp15.c15_ccnt = 0; 908*dd43ac07SAlexander Graf } 909*dd43ac07SAlexander Graf 910*dd43ac07SAlexander Graf if (val & PMCRP) { 911*dd43ac07SAlexander Graf unsigned int i; 912*dd43ac07SAlexander Graf for (i = 0; i < pmu_num_counters(env); i++) { 913*dd43ac07SAlexander Graf env->cp15.c14_pmevcntr[i] = 0; 914*dd43ac07SAlexander Graf } 915*dd43ac07SAlexander Graf } 916*dd43ac07SAlexander Graf 917*dd43ac07SAlexander Graf env->cp15.c9_pmcr &= ~PMCR_WRITEABLE_MASK; 918*dd43ac07SAlexander Graf env->cp15.c9_pmcr |= (val & PMCR_WRITEABLE_MASK); 919*dd43ac07SAlexander Graf 920*dd43ac07SAlexander Graf pmu_op_finish(env); 921*dd43ac07SAlexander Graf break; 922*dd43ac07SAlexander Graf case SYSREG_PMUSERENR_EL0: 923*dd43ac07SAlexander Graf env->cp15.c9_pmuserenr = val & 0xf; 924*dd43ac07SAlexander Graf break; 925*dd43ac07SAlexander Graf case SYSREG_PMCNTENSET_EL0: 926*dd43ac07SAlexander Graf env->cp15.c9_pmcnten |= (val & pmu_counter_mask(env)); 927*dd43ac07SAlexander Graf break; 928*dd43ac07SAlexander Graf case SYSREG_PMCNTENCLR_EL0: 929*dd43ac07SAlexander Graf env->cp15.c9_pmcnten &= ~(val & pmu_counter_mask(env)); 930*dd43ac07SAlexander Graf break; 931*dd43ac07SAlexander Graf case SYSREG_PMINTENCLR_EL1: 932*dd43ac07SAlexander Graf pmu_op_start(env); 933*dd43ac07SAlexander Graf env->cp15.c9_pminten |= val; 934*dd43ac07SAlexander Graf pmu_op_finish(env); 935*dd43ac07SAlexander Graf break; 936*dd43ac07SAlexander Graf case SYSREG_PMOVSCLR_EL0: 937*dd43ac07SAlexander Graf pmu_op_start(env); 938*dd43ac07SAlexander Graf env->cp15.c9_pmovsr &= ~val; 939*dd43ac07SAlexander Graf pmu_op_finish(env); 940*dd43ac07SAlexander Graf break; 941*dd43ac07SAlexander Graf case SYSREG_PMSWINC_EL0: 942*dd43ac07SAlexander Graf pmu_op_start(env); 943*dd43ac07SAlexander Graf pmswinc_write(env, val); 944*dd43ac07SAlexander Graf pmu_op_finish(env); 945*dd43ac07SAlexander Graf break; 946*dd43ac07SAlexander Graf case SYSREG_PMSELR_EL0: 947*dd43ac07SAlexander Graf env->cp15.c9_pmselr = val & 0x1f; 948*dd43ac07SAlexander Graf break; 949*dd43ac07SAlexander Graf case SYSREG_PMCCFILTR_EL0: 950*dd43ac07SAlexander Graf pmu_op_start(env); 951*dd43ac07SAlexander Graf env->cp15.pmccfiltr_el0 = val & PMCCFILTR_EL0; 952*dd43ac07SAlexander Graf pmu_op_finish(env); 953*dd43ac07SAlexander Graf break; 954a1477da3SAlexander Graf case SYSREG_OSLAR_EL1: 955a1477da3SAlexander Graf env->cp15.oslsr_el1 = val & 1; 956a1477da3SAlexander Graf break; 957a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 958a1477da3SAlexander Graf /* Dummy register */ 959a1477da3SAlexander Graf break; 960a1477da3SAlexander Graf default: 961a1477da3SAlexander Graf cpu_synchronize_state(cpu); 962a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_write(env->pc, reg, 963a1477da3SAlexander Graf (reg >> 20) & 0x3, 964a1477da3SAlexander Graf (reg >> 14) & 0x7, 965a1477da3SAlexander Graf (reg >> 10) & 0xf, 966a1477da3SAlexander Graf (reg >> 1) & 0xf, 967a1477da3SAlexander Graf (reg >> 17) & 0x7); 968a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 969a1477da3SAlexander Graf return 1; 970a1477da3SAlexander Graf } 971a1477da3SAlexander Graf 972a1477da3SAlexander Graf return 0; 973a1477da3SAlexander Graf } 974a1477da3SAlexander Graf 975a1477da3SAlexander Graf static int hvf_inject_interrupts(CPUState *cpu) 976a1477da3SAlexander Graf { 977a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_FIQ) { 978a1477da3SAlexander Graf trace_hvf_inject_fiq(); 979a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_FIQ, 980a1477da3SAlexander Graf true); 981a1477da3SAlexander Graf } 982a1477da3SAlexander Graf 983a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { 984a1477da3SAlexander Graf trace_hvf_inject_irq(); 985a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_IRQ, 986a1477da3SAlexander Graf true); 987a1477da3SAlexander Graf } 988a1477da3SAlexander Graf 989a1477da3SAlexander Graf return 0; 990a1477da3SAlexander Graf } 991a1477da3SAlexander Graf 992a1477da3SAlexander Graf static uint64_t hvf_vtimer_val_raw(void) 993a1477da3SAlexander Graf { 994a1477da3SAlexander Graf /* 995a1477da3SAlexander Graf * mach_absolute_time() returns the vtimer value without the VM 996a1477da3SAlexander Graf * offset that we define. Add our own offset on top. 997a1477da3SAlexander Graf */ 998a1477da3SAlexander Graf return mach_absolute_time() - hvf_state->vtimer_offset; 999a1477da3SAlexander Graf } 1000a1477da3SAlexander Graf 1001219c101fSPeter Collingbourne static uint64_t hvf_vtimer_val(void) 1002219c101fSPeter Collingbourne { 1003219c101fSPeter Collingbourne if (!runstate_is_running()) { 1004219c101fSPeter Collingbourne /* VM is paused, the vtimer value is in vtimer.vtimer_val */ 1005219c101fSPeter Collingbourne return vtimer.vtimer_val; 1006219c101fSPeter Collingbourne } 1007219c101fSPeter Collingbourne 1008219c101fSPeter Collingbourne return hvf_vtimer_val_raw(); 1009219c101fSPeter Collingbourne } 1010219c101fSPeter Collingbourne 1011219c101fSPeter Collingbourne static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) 1012219c101fSPeter Collingbourne { 1013219c101fSPeter Collingbourne /* 1014219c101fSPeter Collingbourne * Use pselect to sleep so that other threads can IPI us while we're 1015219c101fSPeter Collingbourne * sleeping. 1016219c101fSPeter Collingbourne */ 1017219c101fSPeter Collingbourne qatomic_mb_set(&cpu->thread_kicked, false); 1018219c101fSPeter Collingbourne qemu_mutex_unlock_iothread(); 1019219c101fSPeter Collingbourne pselect(0, 0, 0, 0, ts, &cpu->hvf->unblock_ipi_mask); 1020219c101fSPeter Collingbourne qemu_mutex_lock_iothread(); 1021219c101fSPeter Collingbourne } 1022219c101fSPeter Collingbourne 1023219c101fSPeter Collingbourne static void hvf_wfi(CPUState *cpu) 1024219c101fSPeter Collingbourne { 1025219c101fSPeter Collingbourne ARMCPU *arm_cpu = ARM_CPU(cpu); 1026219c101fSPeter Collingbourne struct timespec ts; 1027219c101fSPeter Collingbourne hv_return_t r; 1028219c101fSPeter Collingbourne uint64_t ctl; 1029219c101fSPeter Collingbourne uint64_t cval; 1030219c101fSPeter Collingbourne int64_t ticks_to_sleep; 1031219c101fSPeter Collingbourne uint64_t seconds; 1032219c101fSPeter Collingbourne uint64_t nanos; 1033219c101fSPeter Collingbourne uint32_t cntfrq; 1034219c101fSPeter Collingbourne 1035219c101fSPeter Collingbourne if (cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) { 1036219c101fSPeter Collingbourne /* Interrupt pending, no need to wait */ 1037219c101fSPeter Collingbourne return; 1038219c101fSPeter Collingbourne } 1039219c101fSPeter Collingbourne 1040219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 1041219c101fSPeter Collingbourne assert_hvf_ok(r); 1042219c101fSPeter Collingbourne 1043219c101fSPeter Collingbourne if (!(ctl & 1) || (ctl & 2)) { 1044219c101fSPeter Collingbourne /* Timer disabled or masked, just wait for an IPI. */ 1045219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, NULL); 1046219c101fSPeter Collingbourne return; 1047219c101fSPeter Collingbourne } 1048219c101fSPeter Collingbourne 1049219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval); 1050219c101fSPeter Collingbourne assert_hvf_ok(r); 1051219c101fSPeter Collingbourne 1052219c101fSPeter Collingbourne ticks_to_sleep = cval - hvf_vtimer_val(); 1053219c101fSPeter Collingbourne if (ticks_to_sleep < 0) { 1054219c101fSPeter Collingbourne return; 1055219c101fSPeter Collingbourne } 1056219c101fSPeter Collingbourne 1057219c101fSPeter Collingbourne cntfrq = gt_cntfrq_period_ns(arm_cpu); 1058219c101fSPeter Collingbourne seconds = muldiv64(ticks_to_sleep, cntfrq, NANOSECONDS_PER_SECOND); 1059219c101fSPeter Collingbourne ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq); 1060219c101fSPeter Collingbourne nanos = ticks_to_sleep * cntfrq; 1061219c101fSPeter Collingbourne 1062219c101fSPeter Collingbourne /* 1063219c101fSPeter Collingbourne * Don't sleep for less than the time a context switch would take, 1064219c101fSPeter Collingbourne * so that we can satisfy fast timer requests on the same CPU. 1065219c101fSPeter Collingbourne * Measurements on M1 show the sweet spot to be ~2ms. 1066219c101fSPeter Collingbourne */ 1067219c101fSPeter Collingbourne if (!seconds && nanos < (2 * SCALE_MS)) { 1068219c101fSPeter Collingbourne return; 1069219c101fSPeter Collingbourne } 1070219c101fSPeter Collingbourne 1071219c101fSPeter Collingbourne ts = (struct timespec) { seconds, nanos }; 1072219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, &ts); 1073219c101fSPeter Collingbourne } 1074219c101fSPeter Collingbourne 1075a1477da3SAlexander Graf static void hvf_sync_vtimer(CPUState *cpu) 1076a1477da3SAlexander Graf { 1077a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 1078a1477da3SAlexander Graf hv_return_t r; 1079a1477da3SAlexander Graf uint64_t ctl; 1080a1477da3SAlexander Graf bool irq_state; 1081a1477da3SAlexander Graf 1082a1477da3SAlexander Graf if (!cpu->hvf->vtimer_masked) { 1083a1477da3SAlexander Graf /* We will get notified on vtimer changes by hvf, nothing to do */ 1084a1477da3SAlexander Graf return; 1085a1477da3SAlexander Graf } 1086a1477da3SAlexander Graf 1087a1477da3SAlexander Graf r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 1088a1477da3SAlexander Graf assert_hvf_ok(r); 1089a1477da3SAlexander Graf 1090a1477da3SAlexander Graf irq_state = (ctl & (TMR_CTL_ENABLE | TMR_CTL_IMASK | TMR_CTL_ISTATUS)) == 1091a1477da3SAlexander Graf (TMR_CTL_ENABLE | TMR_CTL_ISTATUS); 1092a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], irq_state); 1093a1477da3SAlexander Graf 1094a1477da3SAlexander Graf if (!irq_state) { 1095a1477da3SAlexander Graf /* Timer no longer asserting, we can unmask it */ 1096a1477da3SAlexander Graf hv_vcpu_set_vtimer_mask(cpu->hvf->fd, false); 1097a1477da3SAlexander Graf cpu->hvf->vtimer_masked = false; 1098a1477da3SAlexander Graf } 1099a1477da3SAlexander Graf } 1100a1477da3SAlexander Graf 1101a1477da3SAlexander Graf int hvf_vcpu_exec(CPUState *cpu) 1102a1477da3SAlexander Graf { 1103a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 1104a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 1105a1477da3SAlexander Graf hv_vcpu_exit_t *hvf_exit = cpu->hvf->exit; 1106a1477da3SAlexander Graf hv_return_t r; 1107a1477da3SAlexander Graf bool advance_pc = false; 1108a1477da3SAlexander Graf 1109a1477da3SAlexander Graf if (hvf_inject_interrupts(cpu)) { 1110a1477da3SAlexander Graf return EXCP_INTERRUPT; 1111a1477da3SAlexander Graf } 1112a1477da3SAlexander Graf 1113a1477da3SAlexander Graf if (cpu->halted) { 1114a1477da3SAlexander Graf return EXCP_HLT; 1115a1477da3SAlexander Graf } 1116a1477da3SAlexander Graf 1117a1477da3SAlexander Graf flush_cpu_state(cpu); 1118a1477da3SAlexander Graf 1119a1477da3SAlexander Graf qemu_mutex_unlock_iothread(); 1120a1477da3SAlexander Graf assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); 1121a1477da3SAlexander Graf 1122a1477da3SAlexander Graf /* handle VMEXIT */ 1123a1477da3SAlexander Graf uint64_t exit_reason = hvf_exit->reason; 1124a1477da3SAlexander Graf uint64_t syndrome = hvf_exit->exception.syndrome; 1125a1477da3SAlexander Graf uint32_t ec = syn_get_ec(syndrome); 1126a1477da3SAlexander Graf 1127a1477da3SAlexander Graf qemu_mutex_lock_iothread(); 1128a1477da3SAlexander Graf switch (exit_reason) { 1129a1477da3SAlexander Graf case HV_EXIT_REASON_EXCEPTION: 1130a1477da3SAlexander Graf /* This is the main one, handle below. */ 1131a1477da3SAlexander Graf break; 1132a1477da3SAlexander Graf case HV_EXIT_REASON_VTIMER_ACTIVATED: 1133a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); 1134a1477da3SAlexander Graf cpu->hvf->vtimer_masked = true; 1135a1477da3SAlexander Graf return 0; 1136a1477da3SAlexander Graf case HV_EXIT_REASON_CANCELED: 1137a1477da3SAlexander Graf /* we got kicked, no exit to process */ 1138a1477da3SAlexander Graf return 0; 1139a1477da3SAlexander Graf default: 1140a1477da3SAlexander Graf assert(0); 1141a1477da3SAlexander Graf } 1142a1477da3SAlexander Graf 1143a1477da3SAlexander Graf hvf_sync_vtimer(cpu); 1144a1477da3SAlexander Graf 1145a1477da3SAlexander Graf switch (ec) { 1146a1477da3SAlexander Graf case EC_DATAABORT: { 1147a1477da3SAlexander Graf bool isv = syndrome & ARM_EL_ISV; 1148a1477da3SAlexander Graf bool iswrite = (syndrome >> 6) & 1; 1149a1477da3SAlexander Graf bool s1ptw = (syndrome >> 7) & 1; 1150a1477da3SAlexander Graf uint32_t sas = (syndrome >> 22) & 3; 1151a1477da3SAlexander Graf uint32_t len = 1 << sas; 1152a1477da3SAlexander Graf uint32_t srt = (syndrome >> 16) & 0x1f; 1153a1477da3SAlexander Graf uint64_t val = 0; 1154a1477da3SAlexander Graf 1155a1477da3SAlexander Graf trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address, 1156a1477da3SAlexander Graf hvf_exit->exception.physical_address, isv, 1157a1477da3SAlexander Graf iswrite, s1ptw, len, srt); 1158a1477da3SAlexander Graf 1159a1477da3SAlexander Graf assert(isv); 1160a1477da3SAlexander Graf 1161a1477da3SAlexander Graf if (iswrite) { 1162a1477da3SAlexander Graf val = hvf_get_reg(cpu, srt); 1163a1477da3SAlexander Graf address_space_write(&address_space_memory, 1164a1477da3SAlexander Graf hvf_exit->exception.physical_address, 1165a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 1166a1477da3SAlexander Graf } else { 1167a1477da3SAlexander Graf address_space_read(&address_space_memory, 1168a1477da3SAlexander Graf hvf_exit->exception.physical_address, 1169a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 1170a1477da3SAlexander Graf hvf_set_reg(cpu, srt, val); 1171a1477da3SAlexander Graf } 1172a1477da3SAlexander Graf 1173a1477da3SAlexander Graf advance_pc = true; 1174a1477da3SAlexander Graf break; 1175a1477da3SAlexander Graf } 1176a1477da3SAlexander Graf case EC_SYSTEMREGISTERTRAP: { 1177a1477da3SAlexander Graf bool isread = (syndrome >> 0) & 1; 1178a1477da3SAlexander Graf uint32_t rt = (syndrome >> 5) & 0x1f; 1179a1477da3SAlexander Graf uint32_t reg = syndrome & SYSREG_MASK; 1180a1477da3SAlexander Graf uint64_t val; 1181a1477da3SAlexander Graf int ret = 0; 1182a1477da3SAlexander Graf 1183a1477da3SAlexander Graf if (isread) { 1184a1477da3SAlexander Graf ret = hvf_sysreg_read(cpu, reg, rt); 1185a1477da3SAlexander Graf } else { 1186a1477da3SAlexander Graf val = hvf_get_reg(cpu, rt); 1187a1477da3SAlexander Graf ret = hvf_sysreg_write(cpu, reg, val); 1188a1477da3SAlexander Graf } 1189a1477da3SAlexander Graf 1190a1477da3SAlexander Graf advance_pc = !ret; 1191a1477da3SAlexander Graf break; 1192a1477da3SAlexander Graf } 1193a1477da3SAlexander Graf case EC_WFX_TRAP: 1194a1477da3SAlexander Graf advance_pc = true; 1195219c101fSPeter Collingbourne if (!(syndrome & WFX_IS_WFE)) { 1196219c101fSPeter Collingbourne hvf_wfi(cpu); 1197219c101fSPeter Collingbourne } 1198a1477da3SAlexander Graf break; 1199a1477da3SAlexander Graf case EC_AA64_HVC: 1200a1477da3SAlexander Graf cpu_synchronize_state(cpu); 12012c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) { 12022c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 1203a1477da3SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 1204a1477da3SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 1205a1477da3SAlexander Graf env->xregs[0] = -1; 12062c9c0bf9SAlexander Graf } 12072c9c0bf9SAlexander Graf } else { 12082c9c0bf9SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 12092c9c0bf9SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 12102c9c0bf9SAlexander Graf } 1211a1477da3SAlexander Graf break; 1212a1477da3SAlexander Graf case EC_AA64_SMC: 1213a1477da3SAlexander Graf cpu_synchronize_state(cpu); 12142c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) { 12152c9c0bf9SAlexander Graf advance_pc = true; 12162c9c0bf9SAlexander Graf 12172c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 12182c9c0bf9SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 12192c9c0bf9SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 12202c9c0bf9SAlexander Graf env->xregs[0] = -1; 12212c9c0bf9SAlexander Graf } 12222c9c0bf9SAlexander Graf } else { 1223a1477da3SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 1224a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 12252c9c0bf9SAlexander Graf } 1226a1477da3SAlexander Graf break; 1227a1477da3SAlexander Graf default: 1228a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1229a1477da3SAlexander Graf trace_hvf_exit(syndrome, ec, env->pc); 1230a1477da3SAlexander Graf error_report("0x%llx: unhandled exception ec=0x%x", env->pc, ec); 1231a1477da3SAlexander Graf } 1232a1477da3SAlexander Graf 1233a1477da3SAlexander Graf if (advance_pc) { 1234a1477da3SAlexander Graf uint64_t pc; 1235a1477da3SAlexander Graf 1236a1477da3SAlexander Graf flush_cpu_state(cpu); 1237a1477da3SAlexander Graf 1238a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_PC, &pc); 1239a1477da3SAlexander Graf assert_hvf_ok(r); 1240a1477da3SAlexander Graf pc += 4; 1241a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_PC, pc); 1242a1477da3SAlexander Graf assert_hvf_ok(r); 1243a1477da3SAlexander Graf } 1244a1477da3SAlexander Graf 1245a1477da3SAlexander Graf return 0; 1246a1477da3SAlexander Graf } 1247a1477da3SAlexander Graf 1248a1477da3SAlexander Graf static const VMStateDescription vmstate_hvf_vtimer = { 1249a1477da3SAlexander Graf .name = "hvf-vtimer", 1250a1477da3SAlexander Graf .version_id = 1, 1251a1477da3SAlexander Graf .minimum_version_id = 1, 1252a1477da3SAlexander Graf .fields = (VMStateField[]) { 1253a1477da3SAlexander Graf VMSTATE_UINT64(vtimer_val, HVFVTimer), 1254a1477da3SAlexander Graf VMSTATE_END_OF_LIST() 1255a1477da3SAlexander Graf }, 1256a1477da3SAlexander Graf }; 1257a1477da3SAlexander Graf 1258a1477da3SAlexander Graf static void hvf_vm_state_change(void *opaque, bool running, RunState state) 1259a1477da3SAlexander Graf { 1260a1477da3SAlexander Graf HVFVTimer *s = opaque; 1261a1477da3SAlexander Graf 1262a1477da3SAlexander Graf if (running) { 1263a1477da3SAlexander Graf /* Update vtimer offset on all CPUs */ 1264a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time() - s->vtimer_val; 1265a1477da3SAlexander Graf cpu_synchronize_all_states(); 1266a1477da3SAlexander Graf } else { 1267a1477da3SAlexander Graf /* Remember vtimer value on every pause */ 1268a1477da3SAlexander Graf s->vtimer_val = hvf_vtimer_val_raw(); 1269a1477da3SAlexander Graf } 1270a1477da3SAlexander Graf } 1271a1477da3SAlexander Graf 1272a1477da3SAlexander Graf int hvf_arch_init(void) 1273a1477da3SAlexander Graf { 1274a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time(); 1275a1477da3SAlexander Graf vmstate_register(NULL, 0, &vmstate_hvf_vtimer, &vtimer); 1276a1477da3SAlexander Graf qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer); 1277a1477da3SAlexander Graf return 0; 1278a1477da3SAlexander Graf } 1279