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" 28*2c9c0bf9SAlexander 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) 45a1477da3SAlexander Graf 46a1477da3SAlexander Graf #define WFX_IS_WFE (1 << 0) 47a1477da3SAlexander Graf 48a1477da3SAlexander Graf #define TMR_CTL_ENABLE (1 << 0) 49a1477da3SAlexander Graf #define TMR_CTL_IMASK (1 << 1) 50a1477da3SAlexander Graf #define TMR_CTL_ISTATUS (1 << 2) 51a1477da3SAlexander Graf 52*2c9c0bf9SAlexander Graf static void hvf_wfi(CPUState *cpu); 53*2c9c0bf9SAlexander Graf 54a1477da3SAlexander Graf typedef struct HVFVTimer { 55a1477da3SAlexander Graf /* Vtimer value during migration and paused state */ 56a1477da3SAlexander Graf uint64_t vtimer_val; 57a1477da3SAlexander Graf } HVFVTimer; 58a1477da3SAlexander Graf 59a1477da3SAlexander Graf static HVFVTimer vtimer; 60a1477da3SAlexander Graf 61585df85eSPeter Maydell typedef struct ARMHostCPUFeatures { 62585df85eSPeter Maydell ARMISARegisters isar; 63585df85eSPeter Maydell uint64_t features; 64585df85eSPeter Maydell uint64_t midr; 65585df85eSPeter Maydell uint32_t reset_sctlr; 66585df85eSPeter Maydell const char *dtb_compatible; 67585df85eSPeter Maydell } ARMHostCPUFeatures; 68585df85eSPeter Maydell 69585df85eSPeter Maydell static ARMHostCPUFeatures arm_host_cpu_features; 70585df85eSPeter Maydell 71a1477da3SAlexander Graf struct hvf_reg_match { 72a1477da3SAlexander Graf int reg; 73a1477da3SAlexander Graf uint64_t offset; 74a1477da3SAlexander Graf }; 75a1477da3SAlexander Graf 76a1477da3SAlexander Graf static const struct hvf_reg_match hvf_reg_match[] = { 77a1477da3SAlexander Graf { HV_REG_X0, offsetof(CPUARMState, xregs[0]) }, 78a1477da3SAlexander Graf { HV_REG_X1, offsetof(CPUARMState, xregs[1]) }, 79a1477da3SAlexander Graf { HV_REG_X2, offsetof(CPUARMState, xregs[2]) }, 80a1477da3SAlexander Graf { HV_REG_X3, offsetof(CPUARMState, xregs[3]) }, 81a1477da3SAlexander Graf { HV_REG_X4, offsetof(CPUARMState, xregs[4]) }, 82a1477da3SAlexander Graf { HV_REG_X5, offsetof(CPUARMState, xregs[5]) }, 83a1477da3SAlexander Graf { HV_REG_X6, offsetof(CPUARMState, xregs[6]) }, 84a1477da3SAlexander Graf { HV_REG_X7, offsetof(CPUARMState, xregs[7]) }, 85a1477da3SAlexander Graf { HV_REG_X8, offsetof(CPUARMState, xregs[8]) }, 86a1477da3SAlexander Graf { HV_REG_X9, offsetof(CPUARMState, xregs[9]) }, 87a1477da3SAlexander Graf { HV_REG_X10, offsetof(CPUARMState, xregs[10]) }, 88a1477da3SAlexander Graf { HV_REG_X11, offsetof(CPUARMState, xregs[11]) }, 89a1477da3SAlexander Graf { HV_REG_X12, offsetof(CPUARMState, xregs[12]) }, 90a1477da3SAlexander Graf { HV_REG_X13, offsetof(CPUARMState, xregs[13]) }, 91a1477da3SAlexander Graf { HV_REG_X14, offsetof(CPUARMState, xregs[14]) }, 92a1477da3SAlexander Graf { HV_REG_X15, offsetof(CPUARMState, xregs[15]) }, 93a1477da3SAlexander Graf { HV_REG_X16, offsetof(CPUARMState, xregs[16]) }, 94a1477da3SAlexander Graf { HV_REG_X17, offsetof(CPUARMState, xregs[17]) }, 95a1477da3SAlexander Graf { HV_REG_X18, offsetof(CPUARMState, xregs[18]) }, 96a1477da3SAlexander Graf { HV_REG_X19, offsetof(CPUARMState, xregs[19]) }, 97a1477da3SAlexander Graf { HV_REG_X20, offsetof(CPUARMState, xregs[20]) }, 98a1477da3SAlexander Graf { HV_REG_X21, offsetof(CPUARMState, xregs[21]) }, 99a1477da3SAlexander Graf { HV_REG_X22, offsetof(CPUARMState, xregs[22]) }, 100a1477da3SAlexander Graf { HV_REG_X23, offsetof(CPUARMState, xregs[23]) }, 101a1477da3SAlexander Graf { HV_REG_X24, offsetof(CPUARMState, xregs[24]) }, 102a1477da3SAlexander Graf { HV_REG_X25, offsetof(CPUARMState, xregs[25]) }, 103a1477da3SAlexander Graf { HV_REG_X26, offsetof(CPUARMState, xregs[26]) }, 104a1477da3SAlexander Graf { HV_REG_X27, offsetof(CPUARMState, xregs[27]) }, 105a1477da3SAlexander Graf { HV_REG_X28, offsetof(CPUARMState, xregs[28]) }, 106a1477da3SAlexander Graf { HV_REG_X29, offsetof(CPUARMState, xregs[29]) }, 107a1477da3SAlexander Graf { HV_REG_X30, offsetof(CPUARMState, xregs[30]) }, 108a1477da3SAlexander Graf { HV_REG_PC, offsetof(CPUARMState, pc) }, 109a1477da3SAlexander Graf }; 110a1477da3SAlexander Graf 111a1477da3SAlexander Graf static const struct hvf_reg_match hvf_fpreg_match[] = { 112a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q0, offsetof(CPUARMState, vfp.zregs[0]) }, 113a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q1, offsetof(CPUARMState, vfp.zregs[1]) }, 114a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q2, offsetof(CPUARMState, vfp.zregs[2]) }, 115a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q3, offsetof(CPUARMState, vfp.zregs[3]) }, 116a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q4, offsetof(CPUARMState, vfp.zregs[4]) }, 117a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q5, offsetof(CPUARMState, vfp.zregs[5]) }, 118a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q6, offsetof(CPUARMState, vfp.zregs[6]) }, 119a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q7, offsetof(CPUARMState, vfp.zregs[7]) }, 120a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q8, offsetof(CPUARMState, vfp.zregs[8]) }, 121a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q9, offsetof(CPUARMState, vfp.zregs[9]) }, 122a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q10, offsetof(CPUARMState, vfp.zregs[10]) }, 123a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q11, offsetof(CPUARMState, vfp.zregs[11]) }, 124a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q12, offsetof(CPUARMState, vfp.zregs[12]) }, 125a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q13, offsetof(CPUARMState, vfp.zregs[13]) }, 126a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q14, offsetof(CPUARMState, vfp.zregs[14]) }, 127a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q15, offsetof(CPUARMState, vfp.zregs[15]) }, 128a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q16, offsetof(CPUARMState, vfp.zregs[16]) }, 129a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q17, offsetof(CPUARMState, vfp.zregs[17]) }, 130a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q18, offsetof(CPUARMState, vfp.zregs[18]) }, 131a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q19, offsetof(CPUARMState, vfp.zregs[19]) }, 132a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q20, offsetof(CPUARMState, vfp.zregs[20]) }, 133a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q21, offsetof(CPUARMState, vfp.zregs[21]) }, 134a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q22, offsetof(CPUARMState, vfp.zregs[22]) }, 135a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q23, offsetof(CPUARMState, vfp.zregs[23]) }, 136a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q24, offsetof(CPUARMState, vfp.zregs[24]) }, 137a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q25, offsetof(CPUARMState, vfp.zregs[25]) }, 138a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q26, offsetof(CPUARMState, vfp.zregs[26]) }, 139a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q27, offsetof(CPUARMState, vfp.zregs[27]) }, 140a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q28, offsetof(CPUARMState, vfp.zregs[28]) }, 141a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q29, offsetof(CPUARMState, vfp.zregs[29]) }, 142a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q30, offsetof(CPUARMState, vfp.zregs[30]) }, 143a1477da3SAlexander Graf { HV_SIMD_FP_REG_Q31, offsetof(CPUARMState, vfp.zregs[31]) }, 144a1477da3SAlexander Graf }; 145a1477da3SAlexander Graf 146a1477da3SAlexander Graf struct hvf_sreg_match { 147a1477da3SAlexander Graf int reg; 148a1477da3SAlexander Graf uint32_t key; 149a1477da3SAlexander Graf uint32_t cp_idx; 150a1477da3SAlexander Graf }; 151a1477da3SAlexander Graf 152a1477da3SAlexander Graf static struct hvf_sreg_match hvf_sreg_match[] = { 153a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) }, 154a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) }, 155a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) }, 156a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) }, 157a1477da3SAlexander Graf 158a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) }, 159a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) }, 160a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) }, 161a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) }, 162a1477da3SAlexander Graf 163a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) }, 164a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) }, 165a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) }, 166a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) }, 167a1477da3SAlexander Graf 168a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) }, 169a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) }, 170a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) }, 171a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) }, 172a1477da3SAlexander Graf 173a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) }, 174a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) }, 175a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) }, 176a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) }, 177a1477da3SAlexander Graf 178a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) }, 179a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) }, 180a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) }, 181a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) }, 182a1477da3SAlexander Graf 183a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) }, 184a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) }, 185a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) }, 186a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) }, 187a1477da3SAlexander Graf 188a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) }, 189a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) }, 190a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) }, 191a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) }, 192a1477da3SAlexander Graf 193a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) }, 194a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) }, 195a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) }, 196a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) }, 197a1477da3SAlexander Graf 198a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) }, 199a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) }, 200a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) }, 201a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) }, 202a1477da3SAlexander Graf 203a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) }, 204a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) }, 205a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) }, 206a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) }, 207a1477da3SAlexander Graf 208a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) }, 209a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) }, 210a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) }, 211a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) }, 212a1477da3SAlexander Graf 213a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) }, 214a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) }, 215a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) }, 216a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) }, 217a1477da3SAlexander Graf 218a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) }, 219a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) }, 220a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) }, 221a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) }, 222a1477da3SAlexander Graf 223a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) }, 224a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) }, 225a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) }, 226a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) }, 227a1477da3SAlexander Graf 228a1477da3SAlexander Graf { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) }, 229a1477da3SAlexander Graf { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) }, 230a1477da3SAlexander Graf { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) }, 231a1477da3SAlexander Graf { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) }, 232a1477da3SAlexander Graf 233a1477da3SAlexander Graf #ifdef SYNC_NO_RAW_REGS 234a1477da3SAlexander Graf /* 235a1477da3SAlexander Graf * The registers below are manually synced on init because they are 236a1477da3SAlexander Graf * marked as NO_RAW. We still list them to make number space sync easier. 237a1477da3SAlexander Graf */ 238a1477da3SAlexander Graf { HV_SYS_REG_MDCCINT_EL1, HVF_SYSREG(0, 2, 2, 0, 0) }, 239a1477da3SAlexander Graf { HV_SYS_REG_MIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 0) }, 240a1477da3SAlexander Graf { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) }, 241a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) }, 242a1477da3SAlexander Graf #endif 243a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) }, 244a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) }, 245a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) }, 246a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) }, 247a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64ISAR1_EL1, HVF_SYSREG(0, 6, 3, 0, 1) }, 248a1477da3SAlexander Graf #ifdef SYNC_NO_MMFR0 249a1477da3SAlexander Graf /* We keep the hardware MMFR0 around. HW limits are there anyway */ 250a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR0_EL1, HVF_SYSREG(0, 7, 3, 0, 0) }, 251a1477da3SAlexander Graf #endif 252a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR1_EL1, HVF_SYSREG(0, 7, 3, 0, 1) }, 253a1477da3SAlexander Graf { HV_SYS_REG_ID_AA64MMFR2_EL1, HVF_SYSREG(0, 7, 3, 0, 2) }, 254a1477da3SAlexander Graf 255a1477da3SAlexander Graf { HV_SYS_REG_MDSCR_EL1, HVF_SYSREG(0, 2, 2, 0, 2) }, 256a1477da3SAlexander Graf { HV_SYS_REG_SCTLR_EL1, HVF_SYSREG(1, 0, 3, 0, 0) }, 257a1477da3SAlexander Graf { HV_SYS_REG_CPACR_EL1, HVF_SYSREG(1, 0, 3, 0, 2) }, 258a1477da3SAlexander Graf { HV_SYS_REG_TTBR0_EL1, HVF_SYSREG(2, 0, 3, 0, 0) }, 259a1477da3SAlexander Graf { HV_SYS_REG_TTBR1_EL1, HVF_SYSREG(2, 0, 3, 0, 1) }, 260a1477da3SAlexander Graf { HV_SYS_REG_TCR_EL1, HVF_SYSREG(2, 0, 3, 0, 2) }, 261a1477da3SAlexander Graf 262a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 0) }, 263a1477da3SAlexander Graf { HV_SYS_REG_APIAKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 1) }, 264a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYLO_EL1, HVF_SYSREG(2, 1, 3, 0, 2) }, 265a1477da3SAlexander Graf { HV_SYS_REG_APIBKEYHI_EL1, HVF_SYSREG(2, 1, 3, 0, 3) }, 266a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 0) }, 267a1477da3SAlexander Graf { HV_SYS_REG_APDAKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 1) }, 268a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYLO_EL1, HVF_SYSREG(2, 2, 3, 0, 2) }, 269a1477da3SAlexander Graf { HV_SYS_REG_APDBKEYHI_EL1, HVF_SYSREG(2, 2, 3, 0, 3) }, 270a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYLO_EL1, HVF_SYSREG(2, 3, 3, 0, 0) }, 271a1477da3SAlexander Graf { HV_SYS_REG_APGAKEYHI_EL1, HVF_SYSREG(2, 3, 3, 0, 1) }, 272a1477da3SAlexander Graf 273a1477da3SAlexander Graf { HV_SYS_REG_SPSR_EL1, HVF_SYSREG(4, 0, 3, 0, 0) }, 274a1477da3SAlexander Graf { HV_SYS_REG_ELR_EL1, HVF_SYSREG(4, 0, 3, 0, 1) }, 275a1477da3SAlexander Graf { HV_SYS_REG_SP_EL0, HVF_SYSREG(4, 1, 3, 0, 0) }, 276a1477da3SAlexander Graf { HV_SYS_REG_AFSR0_EL1, HVF_SYSREG(5, 1, 3, 0, 0) }, 277a1477da3SAlexander Graf { HV_SYS_REG_AFSR1_EL1, HVF_SYSREG(5, 1, 3, 0, 1) }, 278a1477da3SAlexander Graf { HV_SYS_REG_ESR_EL1, HVF_SYSREG(5, 2, 3, 0, 0) }, 279a1477da3SAlexander Graf { HV_SYS_REG_FAR_EL1, HVF_SYSREG(6, 0, 3, 0, 0) }, 280a1477da3SAlexander Graf { HV_SYS_REG_PAR_EL1, HVF_SYSREG(7, 4, 3, 0, 0) }, 281a1477da3SAlexander Graf { HV_SYS_REG_MAIR_EL1, HVF_SYSREG(10, 2, 3, 0, 0) }, 282a1477da3SAlexander Graf { HV_SYS_REG_AMAIR_EL1, HVF_SYSREG(10, 3, 3, 0, 0) }, 283a1477da3SAlexander Graf { HV_SYS_REG_VBAR_EL1, HVF_SYSREG(12, 0, 3, 0, 0) }, 284a1477da3SAlexander Graf { HV_SYS_REG_CONTEXTIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 1) }, 285a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL1, HVF_SYSREG(13, 0, 3, 0, 4) }, 286a1477da3SAlexander Graf { HV_SYS_REG_CNTKCTL_EL1, HVF_SYSREG(14, 1, 3, 0, 0) }, 287a1477da3SAlexander Graf { HV_SYS_REG_CSSELR_EL1, HVF_SYSREG(0, 0, 3, 2, 0) }, 288a1477da3SAlexander Graf { HV_SYS_REG_TPIDR_EL0, HVF_SYSREG(13, 0, 3, 3, 2) }, 289a1477da3SAlexander Graf { HV_SYS_REG_TPIDRRO_EL0, HVF_SYSREG(13, 0, 3, 3, 3) }, 290a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CTL_EL0, HVF_SYSREG(14, 3, 3, 3, 1) }, 291a1477da3SAlexander Graf { HV_SYS_REG_CNTV_CVAL_EL0, HVF_SYSREG(14, 3, 3, 3, 2) }, 292a1477da3SAlexander Graf { HV_SYS_REG_SP_EL1, HVF_SYSREG(4, 1, 3, 4, 0) }, 293a1477da3SAlexander Graf }; 294a1477da3SAlexander Graf 295a1477da3SAlexander Graf int hvf_get_registers(CPUState *cpu) 296a1477da3SAlexander Graf { 297a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 298a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 299a1477da3SAlexander Graf hv_return_t ret; 300a1477da3SAlexander Graf uint64_t val; 301a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 302a1477da3SAlexander Graf int i; 303a1477da3SAlexander Graf 304a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 305a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, hvf_reg_match[i].reg, &val); 306a1477da3SAlexander Graf *(uint64_t *)((void *)env + hvf_reg_match[i].offset) = val; 307a1477da3SAlexander Graf assert_hvf_ok(ret); 308a1477da3SAlexander Graf } 309a1477da3SAlexander Graf 310a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 311a1477da3SAlexander Graf ret = hv_vcpu_get_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 312a1477da3SAlexander Graf &fpval); 313a1477da3SAlexander Graf memcpy((void *)env + hvf_fpreg_match[i].offset, &fpval, sizeof(fpval)); 314a1477da3SAlexander Graf assert_hvf_ok(ret); 315a1477da3SAlexander Graf } 316a1477da3SAlexander Graf 317a1477da3SAlexander Graf val = 0; 318a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPCR, &val); 319a1477da3SAlexander Graf assert_hvf_ok(ret); 320a1477da3SAlexander Graf vfp_set_fpcr(env, val); 321a1477da3SAlexander Graf 322a1477da3SAlexander Graf val = 0; 323a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_FPSR, &val); 324a1477da3SAlexander Graf assert_hvf_ok(ret); 325a1477da3SAlexander Graf vfp_set_fpsr(env, val); 326a1477da3SAlexander Graf 327a1477da3SAlexander Graf ret = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_CPSR, &val); 328a1477da3SAlexander Graf assert_hvf_ok(ret); 329a1477da3SAlexander Graf pstate_write(env, val); 330a1477da3SAlexander Graf 331a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 332a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 333a1477da3SAlexander Graf continue; 334a1477da3SAlexander Graf } 335a1477da3SAlexander Graf 336a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, &val); 337a1477da3SAlexander Graf assert_hvf_ok(ret); 338a1477da3SAlexander Graf 339a1477da3SAlexander Graf arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx] = val; 340a1477da3SAlexander Graf } 341a1477da3SAlexander Graf assert(write_list_to_cpustate(arm_cpu)); 342a1477da3SAlexander Graf 343a1477da3SAlexander Graf aarch64_restore_sp(env, arm_current_el(env)); 344a1477da3SAlexander Graf 345a1477da3SAlexander Graf return 0; 346a1477da3SAlexander Graf } 347a1477da3SAlexander Graf 348a1477da3SAlexander Graf int hvf_put_registers(CPUState *cpu) 349a1477da3SAlexander Graf { 350a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 351a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 352a1477da3SAlexander Graf hv_return_t ret; 353a1477da3SAlexander Graf uint64_t val; 354a1477da3SAlexander Graf hv_simd_fp_uchar16_t fpval; 355a1477da3SAlexander Graf int i; 356a1477da3SAlexander Graf 357a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_reg_match); i++) { 358a1477da3SAlexander Graf val = *(uint64_t *)((void *)env + hvf_reg_match[i].offset); 359a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, hvf_reg_match[i].reg, val); 360a1477da3SAlexander Graf assert_hvf_ok(ret); 361a1477da3SAlexander Graf } 362a1477da3SAlexander Graf 363a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_fpreg_match); i++) { 364a1477da3SAlexander Graf memcpy(&fpval, (void *)env + hvf_fpreg_match[i].offset, sizeof(fpval)); 365a1477da3SAlexander Graf ret = hv_vcpu_set_simd_fp_reg(cpu->hvf->fd, hvf_fpreg_match[i].reg, 366a1477da3SAlexander Graf fpval); 367a1477da3SAlexander Graf assert_hvf_ok(ret); 368a1477da3SAlexander Graf } 369a1477da3SAlexander Graf 370a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPCR, vfp_get_fpcr(env)); 371a1477da3SAlexander Graf assert_hvf_ok(ret); 372a1477da3SAlexander Graf 373a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_FPSR, vfp_get_fpsr(env)); 374a1477da3SAlexander Graf assert_hvf_ok(ret); 375a1477da3SAlexander Graf 376a1477da3SAlexander Graf ret = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_CPSR, pstate_read(env)); 377a1477da3SAlexander Graf assert_hvf_ok(ret); 378a1477da3SAlexander Graf 379a1477da3SAlexander Graf aarch64_save_sp(env, arm_current_el(env)); 380a1477da3SAlexander Graf 381a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 382a1477da3SAlexander Graf for (i = 0; i < ARRAY_SIZE(hvf_sreg_match); i++) { 383a1477da3SAlexander Graf if (hvf_sreg_match[i].cp_idx == -1) { 384a1477da3SAlexander Graf continue; 385a1477da3SAlexander Graf } 386a1477da3SAlexander Graf 387a1477da3SAlexander Graf val = arm_cpu->cpreg_values[hvf_sreg_match[i].cp_idx]; 388a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, hvf_sreg_match[i].reg, val); 389a1477da3SAlexander Graf assert_hvf_ok(ret); 390a1477da3SAlexander Graf } 391a1477da3SAlexander Graf 392a1477da3SAlexander Graf ret = hv_vcpu_set_vtimer_offset(cpu->hvf->fd, hvf_state->vtimer_offset); 393a1477da3SAlexander Graf assert_hvf_ok(ret); 394a1477da3SAlexander Graf 395a1477da3SAlexander Graf return 0; 396a1477da3SAlexander Graf } 397a1477da3SAlexander Graf 398a1477da3SAlexander Graf static void flush_cpu_state(CPUState *cpu) 399a1477da3SAlexander Graf { 400a1477da3SAlexander Graf if (cpu->vcpu_dirty) { 401a1477da3SAlexander Graf hvf_put_registers(cpu); 402a1477da3SAlexander Graf cpu->vcpu_dirty = false; 403a1477da3SAlexander Graf } 404a1477da3SAlexander Graf } 405a1477da3SAlexander Graf 406a1477da3SAlexander Graf static void hvf_set_reg(CPUState *cpu, int rt, uint64_t val) 407a1477da3SAlexander Graf { 408a1477da3SAlexander Graf hv_return_t r; 409a1477da3SAlexander Graf 410a1477da3SAlexander Graf flush_cpu_state(cpu); 411a1477da3SAlexander Graf 412a1477da3SAlexander Graf if (rt < 31) { 413a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_X0 + rt, val); 414a1477da3SAlexander Graf assert_hvf_ok(r); 415a1477da3SAlexander Graf } 416a1477da3SAlexander Graf } 417a1477da3SAlexander Graf 418a1477da3SAlexander Graf static uint64_t hvf_get_reg(CPUState *cpu, int rt) 419a1477da3SAlexander Graf { 420a1477da3SAlexander Graf uint64_t val = 0; 421a1477da3SAlexander Graf hv_return_t r; 422a1477da3SAlexander Graf 423a1477da3SAlexander Graf flush_cpu_state(cpu); 424a1477da3SAlexander Graf 425a1477da3SAlexander Graf if (rt < 31) { 426a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_X0 + rt, &val); 427a1477da3SAlexander Graf assert_hvf_ok(r); 428a1477da3SAlexander Graf } 429a1477da3SAlexander Graf 430a1477da3SAlexander Graf return val; 431a1477da3SAlexander Graf } 432a1477da3SAlexander Graf 433585df85eSPeter Maydell static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) 434585df85eSPeter Maydell { 435585df85eSPeter Maydell ARMISARegisters host_isar = {}; 436585df85eSPeter Maydell const struct isar_regs { 437585df85eSPeter Maydell int reg; 438585df85eSPeter Maydell uint64_t *val; 439585df85eSPeter Maydell } regs[] = { 440585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, 441585df85eSPeter Maydell { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, 442585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, 443585df85eSPeter Maydell { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, 444585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, 445585df85eSPeter Maydell { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, 446585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, 447585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, 448585df85eSPeter Maydell { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, 449585df85eSPeter Maydell }; 450585df85eSPeter Maydell hv_vcpu_t fd; 451585df85eSPeter Maydell hv_return_t r = HV_SUCCESS; 452585df85eSPeter Maydell hv_vcpu_exit_t *exit; 453585df85eSPeter Maydell int i; 454585df85eSPeter Maydell 455585df85eSPeter Maydell ahcf->dtb_compatible = "arm,arm-v8"; 456585df85eSPeter Maydell ahcf->features = (1ULL << ARM_FEATURE_V8) | 457585df85eSPeter Maydell (1ULL << ARM_FEATURE_NEON) | 458585df85eSPeter Maydell (1ULL << ARM_FEATURE_AARCH64) | 459585df85eSPeter Maydell (1ULL << ARM_FEATURE_PMU) | 460585df85eSPeter Maydell (1ULL << ARM_FEATURE_GENERIC_TIMER); 461585df85eSPeter Maydell 462585df85eSPeter Maydell /* We set up a small vcpu to extract host registers */ 463585df85eSPeter Maydell 464585df85eSPeter Maydell if (hv_vcpu_create(&fd, &exit, NULL) != HV_SUCCESS) { 465585df85eSPeter Maydell return false; 466585df85eSPeter Maydell } 467585df85eSPeter Maydell 468585df85eSPeter Maydell for (i = 0; i < ARRAY_SIZE(regs); i++) { 469585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, regs[i].reg, regs[i].val); 470585df85eSPeter Maydell } 471585df85eSPeter Maydell r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr); 472585df85eSPeter Maydell r |= hv_vcpu_destroy(fd); 473585df85eSPeter Maydell 474585df85eSPeter Maydell ahcf->isar = host_isar; 475585df85eSPeter Maydell 476585df85eSPeter Maydell /* 477585df85eSPeter Maydell * A scratch vCPU returns SCTLR 0, so let's fill our default with the M1 478585df85eSPeter Maydell * boot SCTLR from https://github.com/AsahiLinux/m1n1/issues/97 479585df85eSPeter Maydell */ 480585df85eSPeter Maydell ahcf->reset_sctlr = 0x30100180; 481585df85eSPeter Maydell /* 482585df85eSPeter Maydell * SPAN is disabled by default when SCTLR.SPAN=1. To improve compatibility, 483585df85eSPeter Maydell * let's disable it on boot and then allow guest software to turn it on by 484585df85eSPeter Maydell * setting it to 0. 485585df85eSPeter Maydell */ 486585df85eSPeter Maydell ahcf->reset_sctlr |= 0x00800000; 487585df85eSPeter Maydell 488585df85eSPeter Maydell /* Make sure we don't advertise AArch32 support for EL0/EL1 */ 489585df85eSPeter Maydell if ((host_isar.id_aa64pfr0 & 0xff) != 0x11) { 490585df85eSPeter Maydell return false; 491585df85eSPeter Maydell } 492585df85eSPeter Maydell 493585df85eSPeter Maydell return r == HV_SUCCESS; 494585df85eSPeter Maydell } 495585df85eSPeter Maydell 496585df85eSPeter Maydell void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu) 497585df85eSPeter Maydell { 498585df85eSPeter Maydell if (!arm_host_cpu_features.dtb_compatible) { 499585df85eSPeter Maydell if (!hvf_enabled() || 500585df85eSPeter Maydell !hvf_arm_get_host_cpu_features(&arm_host_cpu_features)) { 501585df85eSPeter Maydell /* 502585df85eSPeter Maydell * We can't report this error yet, so flag that we need to 503585df85eSPeter Maydell * in arm_cpu_realizefn(). 504585df85eSPeter Maydell */ 505585df85eSPeter Maydell cpu->host_cpu_probe_failed = true; 506585df85eSPeter Maydell return; 507585df85eSPeter Maydell } 508585df85eSPeter Maydell } 509585df85eSPeter Maydell 510585df85eSPeter Maydell cpu->dtb_compatible = arm_host_cpu_features.dtb_compatible; 511585df85eSPeter Maydell cpu->isar = arm_host_cpu_features.isar; 512585df85eSPeter Maydell cpu->env.features = arm_host_cpu_features.features; 513585df85eSPeter Maydell cpu->midr = arm_host_cpu_features.midr; 514585df85eSPeter Maydell cpu->reset_sctlr = arm_host_cpu_features.reset_sctlr; 515585df85eSPeter Maydell } 516585df85eSPeter Maydell 517a1477da3SAlexander Graf void hvf_arch_vcpu_destroy(CPUState *cpu) 518a1477da3SAlexander Graf { 519a1477da3SAlexander Graf } 520a1477da3SAlexander Graf 521a1477da3SAlexander Graf int hvf_arch_init_vcpu(CPUState *cpu) 522a1477da3SAlexander Graf { 523a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 524a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 525a1477da3SAlexander Graf uint32_t sregs_match_len = ARRAY_SIZE(hvf_sreg_match); 526a1477da3SAlexander Graf uint32_t sregs_cnt = 0; 527a1477da3SAlexander Graf uint64_t pfr; 528a1477da3SAlexander Graf hv_return_t ret; 529a1477da3SAlexander Graf int i; 530a1477da3SAlexander Graf 531a1477da3SAlexander Graf env->aarch64 = 1; 532a1477da3SAlexander Graf asm volatile("mrs %0, cntfrq_el0" : "=r"(arm_cpu->gt_cntfrq_hz)); 533a1477da3SAlexander Graf 534a1477da3SAlexander Graf /* Allocate enough space for our sysreg sync */ 535a1477da3SAlexander Graf arm_cpu->cpreg_indexes = g_renew(uint64_t, arm_cpu->cpreg_indexes, 536a1477da3SAlexander Graf sregs_match_len); 537a1477da3SAlexander Graf arm_cpu->cpreg_values = g_renew(uint64_t, arm_cpu->cpreg_values, 538a1477da3SAlexander Graf sregs_match_len); 539a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes = g_renew(uint64_t, 540a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_indexes, 541a1477da3SAlexander Graf sregs_match_len); 542a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values = g_renew(uint64_t, 543a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_values, 544a1477da3SAlexander Graf sregs_match_len); 545a1477da3SAlexander Graf 546a1477da3SAlexander Graf memset(arm_cpu->cpreg_values, 0, sregs_match_len * sizeof(uint64_t)); 547a1477da3SAlexander Graf 548a1477da3SAlexander Graf /* Populate cp list for all known sysregs */ 549a1477da3SAlexander Graf for (i = 0; i < sregs_match_len; i++) { 550a1477da3SAlexander Graf const ARMCPRegInfo *ri; 551a1477da3SAlexander Graf uint32_t key = hvf_sreg_match[i].key; 552a1477da3SAlexander Graf 553a1477da3SAlexander Graf ri = get_arm_cp_reginfo(arm_cpu->cp_regs, key); 554a1477da3SAlexander Graf if (ri) { 555a1477da3SAlexander Graf assert(!(ri->type & ARM_CP_NO_RAW)); 556a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = sregs_cnt; 557a1477da3SAlexander Graf arm_cpu->cpreg_indexes[sregs_cnt++] = cpreg_to_kvm_id(key); 558a1477da3SAlexander Graf } else { 559a1477da3SAlexander Graf hvf_sreg_match[i].cp_idx = -1; 560a1477da3SAlexander Graf } 561a1477da3SAlexander Graf } 562a1477da3SAlexander Graf arm_cpu->cpreg_array_len = sregs_cnt; 563a1477da3SAlexander Graf arm_cpu->cpreg_vmstate_array_len = sregs_cnt; 564a1477da3SAlexander Graf 565a1477da3SAlexander Graf assert(write_cpustate_to_list(arm_cpu, false)); 566a1477da3SAlexander Graf 567a1477da3SAlexander Graf /* Set CP_NO_RAW system registers on init */ 568a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MIDR_EL1, 569a1477da3SAlexander Graf arm_cpu->midr); 570a1477da3SAlexander Graf assert_hvf_ok(ret); 571a1477da3SAlexander Graf 572a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_MPIDR_EL1, 573a1477da3SAlexander Graf arm_cpu->mp_affinity); 574a1477da3SAlexander Graf assert_hvf_ok(ret); 575a1477da3SAlexander Graf 576a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, &pfr); 577a1477da3SAlexander Graf assert_hvf_ok(ret); 578a1477da3SAlexander Graf pfr |= env->gicv3state ? (1 << 24) : 0; 579a1477da3SAlexander Graf ret = hv_vcpu_set_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64PFR0_EL1, pfr); 580a1477da3SAlexander Graf assert_hvf_ok(ret); 581a1477da3SAlexander Graf 582a1477da3SAlexander Graf /* We're limited to underlying hardware caps, override internal versions */ 583a1477da3SAlexander Graf ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, 584a1477da3SAlexander Graf &arm_cpu->isar.id_aa64mmfr0); 585a1477da3SAlexander Graf assert_hvf_ok(ret); 586a1477da3SAlexander Graf 587a1477da3SAlexander Graf return 0; 588a1477da3SAlexander Graf } 589a1477da3SAlexander Graf 590a1477da3SAlexander Graf void hvf_kick_vcpu_thread(CPUState *cpu) 591a1477da3SAlexander Graf { 592219c101fSPeter Collingbourne cpus_kick_thread(cpu); 593a1477da3SAlexander Graf hv_vcpus_exit(&cpu->hvf->fd, 1); 594a1477da3SAlexander Graf } 595a1477da3SAlexander Graf 596a1477da3SAlexander Graf static void hvf_raise_exception(CPUState *cpu, uint32_t excp, 597a1477da3SAlexander Graf uint32_t syndrome) 598a1477da3SAlexander Graf { 599a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 600a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 601a1477da3SAlexander Graf 602a1477da3SAlexander Graf cpu->exception_index = excp; 603a1477da3SAlexander Graf env->exception.target_el = 1; 604a1477da3SAlexander Graf env->exception.syndrome = syndrome; 605a1477da3SAlexander Graf 606a1477da3SAlexander Graf arm_cpu_do_interrupt(cpu); 607a1477da3SAlexander Graf } 608a1477da3SAlexander Graf 609*2c9c0bf9SAlexander Graf static void hvf_psci_cpu_off(ARMCPU *arm_cpu) 610*2c9c0bf9SAlexander Graf { 611*2c9c0bf9SAlexander Graf int32_t ret = arm_set_cpu_off(arm_cpu->mp_affinity); 612*2c9c0bf9SAlexander Graf assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS); 613*2c9c0bf9SAlexander Graf } 614*2c9c0bf9SAlexander Graf 615*2c9c0bf9SAlexander Graf /* 616*2c9c0bf9SAlexander Graf * Handle a PSCI call. 617*2c9c0bf9SAlexander Graf * 618*2c9c0bf9SAlexander Graf * Returns 0 on success 619*2c9c0bf9SAlexander Graf * -1 when the PSCI call is unknown, 620*2c9c0bf9SAlexander Graf */ 621*2c9c0bf9SAlexander Graf static bool hvf_handle_psci_call(CPUState *cpu) 622*2c9c0bf9SAlexander Graf { 623*2c9c0bf9SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 624*2c9c0bf9SAlexander Graf CPUARMState *env = &arm_cpu->env; 625*2c9c0bf9SAlexander Graf uint64_t param[4] = { 626*2c9c0bf9SAlexander Graf env->xregs[0], 627*2c9c0bf9SAlexander Graf env->xregs[1], 628*2c9c0bf9SAlexander Graf env->xregs[2], 629*2c9c0bf9SAlexander Graf env->xregs[3] 630*2c9c0bf9SAlexander Graf }; 631*2c9c0bf9SAlexander Graf uint64_t context_id, mpidr; 632*2c9c0bf9SAlexander Graf bool target_aarch64 = true; 633*2c9c0bf9SAlexander Graf CPUState *target_cpu_state; 634*2c9c0bf9SAlexander Graf ARMCPU *target_cpu; 635*2c9c0bf9SAlexander Graf target_ulong entry; 636*2c9c0bf9SAlexander Graf int target_el = 1; 637*2c9c0bf9SAlexander Graf int32_t ret = 0; 638*2c9c0bf9SAlexander Graf 639*2c9c0bf9SAlexander Graf trace_hvf_psci_call(param[0], param[1], param[2], param[3], 640*2c9c0bf9SAlexander Graf arm_cpu->mp_affinity); 641*2c9c0bf9SAlexander Graf 642*2c9c0bf9SAlexander Graf switch (param[0]) { 643*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_PSCI_VERSION: 644*2c9c0bf9SAlexander Graf ret = QEMU_PSCI_0_2_RET_VERSION_0_2; 645*2c9c0bf9SAlexander Graf break; 646*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: 647*2c9c0bf9SAlexander Graf ret = QEMU_PSCI_0_2_RET_TOS_MIGRATION_NOT_REQUIRED; /* No trusted OS */ 648*2c9c0bf9SAlexander Graf break; 649*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_AFFINITY_INFO: 650*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: 651*2c9c0bf9SAlexander Graf mpidr = param[1]; 652*2c9c0bf9SAlexander Graf 653*2c9c0bf9SAlexander Graf switch (param[2]) { 654*2c9c0bf9SAlexander Graf case 0: 655*2c9c0bf9SAlexander Graf target_cpu_state = arm_get_cpu_by_id(mpidr); 656*2c9c0bf9SAlexander Graf if (!target_cpu_state) { 657*2c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 658*2c9c0bf9SAlexander Graf break; 659*2c9c0bf9SAlexander Graf } 660*2c9c0bf9SAlexander Graf target_cpu = ARM_CPU(target_cpu_state); 661*2c9c0bf9SAlexander Graf 662*2c9c0bf9SAlexander Graf ret = target_cpu->power_state; 663*2c9c0bf9SAlexander Graf break; 664*2c9c0bf9SAlexander Graf default: 665*2c9c0bf9SAlexander Graf /* Everything above affinity level 0 is always on. */ 666*2c9c0bf9SAlexander Graf ret = 0; 667*2c9c0bf9SAlexander Graf } 668*2c9c0bf9SAlexander Graf break; 669*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_RESET: 670*2c9c0bf9SAlexander Graf qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 671*2c9c0bf9SAlexander Graf /* 672*2c9c0bf9SAlexander Graf * QEMU reset and shutdown are async requests, but PSCI 673*2c9c0bf9SAlexander Graf * mandates that we never return from the reset/shutdown 674*2c9c0bf9SAlexander Graf * call, so power the CPU off now so it doesn't execute 675*2c9c0bf9SAlexander Graf * anything further. 676*2c9c0bf9SAlexander Graf */ 677*2c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 678*2c9c0bf9SAlexander Graf break; 679*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_SYSTEM_OFF: 680*2c9c0bf9SAlexander Graf qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 681*2c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 682*2c9c0bf9SAlexander Graf break; 683*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_ON: 684*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_ON: 685*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_ON: 686*2c9c0bf9SAlexander Graf mpidr = param[1]; 687*2c9c0bf9SAlexander Graf entry = param[2]; 688*2c9c0bf9SAlexander Graf context_id = param[3]; 689*2c9c0bf9SAlexander Graf ret = arm_set_cpu_on(mpidr, entry, context_id, 690*2c9c0bf9SAlexander Graf target_el, target_aarch64); 691*2c9c0bf9SAlexander Graf break; 692*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_OFF: 693*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_OFF: 694*2c9c0bf9SAlexander Graf hvf_psci_cpu_off(arm_cpu); 695*2c9c0bf9SAlexander Graf break; 696*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_CPU_SUSPEND: 697*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_CPU_SUSPEND: 698*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: 699*2c9c0bf9SAlexander Graf /* Affinity levels are not supported in QEMU */ 700*2c9c0bf9SAlexander Graf if (param[1] & 0xfffe0000) { 701*2c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_INVALID_PARAMS; 702*2c9c0bf9SAlexander Graf break; 703*2c9c0bf9SAlexander Graf } 704*2c9c0bf9SAlexander Graf /* Powerdown is not supported, we always go into WFI */ 705*2c9c0bf9SAlexander Graf env->xregs[0] = 0; 706*2c9c0bf9SAlexander Graf hvf_wfi(cpu); 707*2c9c0bf9SAlexander Graf break; 708*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_1_FN_MIGRATE: 709*2c9c0bf9SAlexander Graf case QEMU_PSCI_0_2_FN_MIGRATE: 710*2c9c0bf9SAlexander Graf ret = QEMU_PSCI_RET_NOT_SUPPORTED; 711*2c9c0bf9SAlexander Graf break; 712*2c9c0bf9SAlexander Graf default: 713*2c9c0bf9SAlexander Graf return false; 714*2c9c0bf9SAlexander Graf } 715*2c9c0bf9SAlexander Graf 716*2c9c0bf9SAlexander Graf env->xregs[0] = ret; 717*2c9c0bf9SAlexander Graf return true; 718*2c9c0bf9SAlexander Graf } 719*2c9c0bf9SAlexander Graf 720a1477da3SAlexander Graf static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, uint32_t rt) 721a1477da3SAlexander Graf { 722a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 723a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 724a1477da3SAlexander Graf uint64_t val = 0; 725a1477da3SAlexander Graf 726a1477da3SAlexander Graf switch (reg) { 727a1477da3SAlexander Graf case SYSREG_CNTPCT_EL0: 728a1477da3SAlexander Graf val = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 729a1477da3SAlexander Graf gt_cntfrq_period_ns(arm_cpu); 730a1477da3SAlexander Graf break; 731a1477da3SAlexander Graf case SYSREG_OSLSR_EL1: 732a1477da3SAlexander Graf val = env->cp15.oslsr_el1; 733a1477da3SAlexander Graf break; 734a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 735a1477da3SAlexander Graf /* Dummy register */ 736a1477da3SAlexander Graf break; 737a1477da3SAlexander Graf default: 738a1477da3SAlexander Graf cpu_synchronize_state(cpu); 739a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_read(env->pc, reg, 740a1477da3SAlexander Graf (reg >> 20) & 0x3, 741a1477da3SAlexander Graf (reg >> 14) & 0x7, 742a1477da3SAlexander Graf (reg >> 10) & 0xf, 743a1477da3SAlexander Graf (reg >> 1) & 0xf, 744a1477da3SAlexander Graf (reg >> 17) & 0x7); 745a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 746a1477da3SAlexander Graf return 1; 747a1477da3SAlexander Graf } 748a1477da3SAlexander Graf 749a1477da3SAlexander Graf trace_hvf_sysreg_read(reg, 750a1477da3SAlexander Graf (reg >> 20) & 0x3, 751a1477da3SAlexander Graf (reg >> 14) & 0x7, 752a1477da3SAlexander Graf (reg >> 10) & 0xf, 753a1477da3SAlexander Graf (reg >> 1) & 0xf, 754a1477da3SAlexander Graf (reg >> 17) & 0x7, 755a1477da3SAlexander Graf val); 756a1477da3SAlexander Graf hvf_set_reg(cpu, rt, val); 757a1477da3SAlexander Graf 758a1477da3SAlexander Graf return 0; 759a1477da3SAlexander Graf } 760a1477da3SAlexander Graf 761a1477da3SAlexander Graf static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val) 762a1477da3SAlexander Graf { 763a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 764a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 765a1477da3SAlexander Graf 766a1477da3SAlexander Graf trace_hvf_sysreg_write(reg, 767a1477da3SAlexander Graf (reg >> 20) & 0x3, 768a1477da3SAlexander Graf (reg >> 14) & 0x7, 769a1477da3SAlexander Graf (reg >> 10) & 0xf, 770a1477da3SAlexander Graf (reg >> 1) & 0xf, 771a1477da3SAlexander Graf (reg >> 17) & 0x7, 772a1477da3SAlexander Graf val); 773a1477da3SAlexander Graf 774a1477da3SAlexander Graf switch (reg) { 775a1477da3SAlexander Graf case SYSREG_OSLAR_EL1: 776a1477da3SAlexander Graf env->cp15.oslsr_el1 = val & 1; 777a1477da3SAlexander Graf break; 778a1477da3SAlexander Graf case SYSREG_OSDLR_EL1: 779a1477da3SAlexander Graf /* Dummy register */ 780a1477da3SAlexander Graf break; 781a1477da3SAlexander Graf default: 782a1477da3SAlexander Graf cpu_synchronize_state(cpu); 783a1477da3SAlexander Graf trace_hvf_unhandled_sysreg_write(env->pc, reg, 784a1477da3SAlexander Graf (reg >> 20) & 0x3, 785a1477da3SAlexander Graf (reg >> 14) & 0x7, 786a1477da3SAlexander Graf (reg >> 10) & 0xf, 787a1477da3SAlexander Graf (reg >> 1) & 0xf, 788a1477da3SAlexander Graf (reg >> 17) & 0x7); 789a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 790a1477da3SAlexander Graf return 1; 791a1477da3SAlexander Graf } 792a1477da3SAlexander Graf 793a1477da3SAlexander Graf return 0; 794a1477da3SAlexander Graf } 795a1477da3SAlexander Graf 796a1477da3SAlexander Graf static int hvf_inject_interrupts(CPUState *cpu) 797a1477da3SAlexander Graf { 798a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_FIQ) { 799a1477da3SAlexander Graf trace_hvf_inject_fiq(); 800a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_FIQ, 801a1477da3SAlexander Graf true); 802a1477da3SAlexander Graf } 803a1477da3SAlexander Graf 804a1477da3SAlexander Graf if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { 805a1477da3SAlexander Graf trace_hvf_inject_irq(); 806a1477da3SAlexander Graf hv_vcpu_set_pending_interrupt(cpu->hvf->fd, HV_INTERRUPT_TYPE_IRQ, 807a1477da3SAlexander Graf true); 808a1477da3SAlexander Graf } 809a1477da3SAlexander Graf 810a1477da3SAlexander Graf return 0; 811a1477da3SAlexander Graf } 812a1477da3SAlexander Graf 813a1477da3SAlexander Graf static uint64_t hvf_vtimer_val_raw(void) 814a1477da3SAlexander Graf { 815a1477da3SAlexander Graf /* 816a1477da3SAlexander Graf * mach_absolute_time() returns the vtimer value without the VM 817a1477da3SAlexander Graf * offset that we define. Add our own offset on top. 818a1477da3SAlexander Graf */ 819a1477da3SAlexander Graf return mach_absolute_time() - hvf_state->vtimer_offset; 820a1477da3SAlexander Graf } 821a1477da3SAlexander Graf 822219c101fSPeter Collingbourne static uint64_t hvf_vtimer_val(void) 823219c101fSPeter Collingbourne { 824219c101fSPeter Collingbourne if (!runstate_is_running()) { 825219c101fSPeter Collingbourne /* VM is paused, the vtimer value is in vtimer.vtimer_val */ 826219c101fSPeter Collingbourne return vtimer.vtimer_val; 827219c101fSPeter Collingbourne } 828219c101fSPeter Collingbourne 829219c101fSPeter Collingbourne return hvf_vtimer_val_raw(); 830219c101fSPeter Collingbourne } 831219c101fSPeter Collingbourne 832219c101fSPeter Collingbourne static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) 833219c101fSPeter Collingbourne { 834219c101fSPeter Collingbourne /* 835219c101fSPeter Collingbourne * Use pselect to sleep so that other threads can IPI us while we're 836219c101fSPeter Collingbourne * sleeping. 837219c101fSPeter Collingbourne */ 838219c101fSPeter Collingbourne qatomic_mb_set(&cpu->thread_kicked, false); 839219c101fSPeter Collingbourne qemu_mutex_unlock_iothread(); 840219c101fSPeter Collingbourne pselect(0, 0, 0, 0, ts, &cpu->hvf->unblock_ipi_mask); 841219c101fSPeter Collingbourne qemu_mutex_lock_iothread(); 842219c101fSPeter Collingbourne } 843219c101fSPeter Collingbourne 844219c101fSPeter Collingbourne static void hvf_wfi(CPUState *cpu) 845219c101fSPeter Collingbourne { 846219c101fSPeter Collingbourne ARMCPU *arm_cpu = ARM_CPU(cpu); 847219c101fSPeter Collingbourne struct timespec ts; 848219c101fSPeter Collingbourne hv_return_t r; 849219c101fSPeter Collingbourne uint64_t ctl; 850219c101fSPeter Collingbourne uint64_t cval; 851219c101fSPeter Collingbourne int64_t ticks_to_sleep; 852219c101fSPeter Collingbourne uint64_t seconds; 853219c101fSPeter Collingbourne uint64_t nanos; 854219c101fSPeter Collingbourne uint32_t cntfrq; 855219c101fSPeter Collingbourne 856219c101fSPeter Collingbourne if (cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) { 857219c101fSPeter Collingbourne /* Interrupt pending, no need to wait */ 858219c101fSPeter Collingbourne return; 859219c101fSPeter Collingbourne } 860219c101fSPeter Collingbourne 861219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 862219c101fSPeter Collingbourne assert_hvf_ok(r); 863219c101fSPeter Collingbourne 864219c101fSPeter Collingbourne if (!(ctl & 1) || (ctl & 2)) { 865219c101fSPeter Collingbourne /* Timer disabled or masked, just wait for an IPI. */ 866219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, NULL); 867219c101fSPeter Collingbourne return; 868219c101fSPeter Collingbourne } 869219c101fSPeter Collingbourne 870219c101fSPeter Collingbourne r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval); 871219c101fSPeter Collingbourne assert_hvf_ok(r); 872219c101fSPeter Collingbourne 873219c101fSPeter Collingbourne ticks_to_sleep = cval - hvf_vtimer_val(); 874219c101fSPeter Collingbourne if (ticks_to_sleep < 0) { 875219c101fSPeter Collingbourne return; 876219c101fSPeter Collingbourne } 877219c101fSPeter Collingbourne 878219c101fSPeter Collingbourne cntfrq = gt_cntfrq_period_ns(arm_cpu); 879219c101fSPeter Collingbourne seconds = muldiv64(ticks_to_sleep, cntfrq, NANOSECONDS_PER_SECOND); 880219c101fSPeter Collingbourne ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq); 881219c101fSPeter Collingbourne nanos = ticks_to_sleep * cntfrq; 882219c101fSPeter Collingbourne 883219c101fSPeter Collingbourne /* 884219c101fSPeter Collingbourne * Don't sleep for less than the time a context switch would take, 885219c101fSPeter Collingbourne * so that we can satisfy fast timer requests on the same CPU. 886219c101fSPeter Collingbourne * Measurements on M1 show the sweet spot to be ~2ms. 887219c101fSPeter Collingbourne */ 888219c101fSPeter Collingbourne if (!seconds && nanos < (2 * SCALE_MS)) { 889219c101fSPeter Collingbourne return; 890219c101fSPeter Collingbourne } 891219c101fSPeter Collingbourne 892219c101fSPeter Collingbourne ts = (struct timespec) { seconds, nanos }; 893219c101fSPeter Collingbourne hvf_wait_for_ipi(cpu, &ts); 894219c101fSPeter Collingbourne } 895219c101fSPeter Collingbourne 896a1477da3SAlexander Graf static void hvf_sync_vtimer(CPUState *cpu) 897a1477da3SAlexander Graf { 898a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 899a1477da3SAlexander Graf hv_return_t r; 900a1477da3SAlexander Graf uint64_t ctl; 901a1477da3SAlexander Graf bool irq_state; 902a1477da3SAlexander Graf 903a1477da3SAlexander Graf if (!cpu->hvf->vtimer_masked) { 904a1477da3SAlexander Graf /* We will get notified on vtimer changes by hvf, nothing to do */ 905a1477da3SAlexander Graf return; 906a1477da3SAlexander Graf } 907a1477da3SAlexander Graf 908a1477da3SAlexander Graf r = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); 909a1477da3SAlexander Graf assert_hvf_ok(r); 910a1477da3SAlexander Graf 911a1477da3SAlexander Graf irq_state = (ctl & (TMR_CTL_ENABLE | TMR_CTL_IMASK | TMR_CTL_ISTATUS)) == 912a1477da3SAlexander Graf (TMR_CTL_ENABLE | TMR_CTL_ISTATUS); 913a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], irq_state); 914a1477da3SAlexander Graf 915a1477da3SAlexander Graf if (!irq_state) { 916a1477da3SAlexander Graf /* Timer no longer asserting, we can unmask it */ 917a1477da3SAlexander Graf hv_vcpu_set_vtimer_mask(cpu->hvf->fd, false); 918a1477da3SAlexander Graf cpu->hvf->vtimer_masked = false; 919a1477da3SAlexander Graf } 920a1477da3SAlexander Graf } 921a1477da3SAlexander Graf 922a1477da3SAlexander Graf int hvf_vcpu_exec(CPUState *cpu) 923a1477da3SAlexander Graf { 924a1477da3SAlexander Graf ARMCPU *arm_cpu = ARM_CPU(cpu); 925a1477da3SAlexander Graf CPUARMState *env = &arm_cpu->env; 926a1477da3SAlexander Graf hv_vcpu_exit_t *hvf_exit = cpu->hvf->exit; 927a1477da3SAlexander Graf hv_return_t r; 928a1477da3SAlexander Graf bool advance_pc = false; 929a1477da3SAlexander Graf 930a1477da3SAlexander Graf if (hvf_inject_interrupts(cpu)) { 931a1477da3SAlexander Graf return EXCP_INTERRUPT; 932a1477da3SAlexander Graf } 933a1477da3SAlexander Graf 934a1477da3SAlexander Graf if (cpu->halted) { 935a1477da3SAlexander Graf return EXCP_HLT; 936a1477da3SAlexander Graf } 937a1477da3SAlexander Graf 938a1477da3SAlexander Graf flush_cpu_state(cpu); 939a1477da3SAlexander Graf 940a1477da3SAlexander Graf qemu_mutex_unlock_iothread(); 941a1477da3SAlexander Graf assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); 942a1477da3SAlexander Graf 943a1477da3SAlexander Graf /* handle VMEXIT */ 944a1477da3SAlexander Graf uint64_t exit_reason = hvf_exit->reason; 945a1477da3SAlexander Graf uint64_t syndrome = hvf_exit->exception.syndrome; 946a1477da3SAlexander Graf uint32_t ec = syn_get_ec(syndrome); 947a1477da3SAlexander Graf 948a1477da3SAlexander Graf qemu_mutex_lock_iothread(); 949a1477da3SAlexander Graf switch (exit_reason) { 950a1477da3SAlexander Graf case HV_EXIT_REASON_EXCEPTION: 951a1477da3SAlexander Graf /* This is the main one, handle below. */ 952a1477da3SAlexander Graf break; 953a1477da3SAlexander Graf case HV_EXIT_REASON_VTIMER_ACTIVATED: 954a1477da3SAlexander Graf qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); 955a1477da3SAlexander Graf cpu->hvf->vtimer_masked = true; 956a1477da3SAlexander Graf return 0; 957a1477da3SAlexander Graf case HV_EXIT_REASON_CANCELED: 958a1477da3SAlexander Graf /* we got kicked, no exit to process */ 959a1477da3SAlexander Graf return 0; 960a1477da3SAlexander Graf default: 961a1477da3SAlexander Graf assert(0); 962a1477da3SAlexander Graf } 963a1477da3SAlexander Graf 964a1477da3SAlexander Graf hvf_sync_vtimer(cpu); 965a1477da3SAlexander Graf 966a1477da3SAlexander Graf switch (ec) { 967a1477da3SAlexander Graf case EC_DATAABORT: { 968a1477da3SAlexander Graf bool isv = syndrome & ARM_EL_ISV; 969a1477da3SAlexander Graf bool iswrite = (syndrome >> 6) & 1; 970a1477da3SAlexander Graf bool s1ptw = (syndrome >> 7) & 1; 971a1477da3SAlexander Graf uint32_t sas = (syndrome >> 22) & 3; 972a1477da3SAlexander Graf uint32_t len = 1 << sas; 973a1477da3SAlexander Graf uint32_t srt = (syndrome >> 16) & 0x1f; 974a1477da3SAlexander Graf uint64_t val = 0; 975a1477da3SAlexander Graf 976a1477da3SAlexander Graf trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address, 977a1477da3SAlexander Graf hvf_exit->exception.physical_address, isv, 978a1477da3SAlexander Graf iswrite, s1ptw, len, srt); 979a1477da3SAlexander Graf 980a1477da3SAlexander Graf assert(isv); 981a1477da3SAlexander Graf 982a1477da3SAlexander Graf if (iswrite) { 983a1477da3SAlexander Graf val = hvf_get_reg(cpu, srt); 984a1477da3SAlexander Graf address_space_write(&address_space_memory, 985a1477da3SAlexander Graf hvf_exit->exception.physical_address, 986a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 987a1477da3SAlexander Graf } else { 988a1477da3SAlexander Graf address_space_read(&address_space_memory, 989a1477da3SAlexander Graf hvf_exit->exception.physical_address, 990a1477da3SAlexander Graf MEMTXATTRS_UNSPECIFIED, &val, len); 991a1477da3SAlexander Graf hvf_set_reg(cpu, srt, val); 992a1477da3SAlexander Graf } 993a1477da3SAlexander Graf 994a1477da3SAlexander Graf advance_pc = true; 995a1477da3SAlexander Graf break; 996a1477da3SAlexander Graf } 997a1477da3SAlexander Graf case EC_SYSTEMREGISTERTRAP: { 998a1477da3SAlexander Graf bool isread = (syndrome >> 0) & 1; 999a1477da3SAlexander Graf uint32_t rt = (syndrome >> 5) & 0x1f; 1000a1477da3SAlexander Graf uint32_t reg = syndrome & SYSREG_MASK; 1001a1477da3SAlexander Graf uint64_t val; 1002a1477da3SAlexander Graf int ret = 0; 1003a1477da3SAlexander Graf 1004a1477da3SAlexander Graf if (isread) { 1005a1477da3SAlexander Graf ret = hvf_sysreg_read(cpu, reg, rt); 1006a1477da3SAlexander Graf } else { 1007a1477da3SAlexander Graf val = hvf_get_reg(cpu, rt); 1008a1477da3SAlexander Graf ret = hvf_sysreg_write(cpu, reg, val); 1009a1477da3SAlexander Graf } 1010a1477da3SAlexander Graf 1011a1477da3SAlexander Graf advance_pc = !ret; 1012a1477da3SAlexander Graf break; 1013a1477da3SAlexander Graf } 1014a1477da3SAlexander Graf case EC_WFX_TRAP: 1015a1477da3SAlexander Graf advance_pc = true; 1016219c101fSPeter Collingbourne if (!(syndrome & WFX_IS_WFE)) { 1017219c101fSPeter Collingbourne hvf_wfi(cpu); 1018219c101fSPeter Collingbourne } 1019a1477da3SAlexander Graf break; 1020a1477da3SAlexander Graf case EC_AA64_HVC: 1021a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1022*2c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_HVC) { 1023*2c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 1024a1477da3SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 1025a1477da3SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 1026a1477da3SAlexander Graf env->xregs[0] = -1; 1027*2c9c0bf9SAlexander Graf } 1028*2c9c0bf9SAlexander Graf } else { 1029*2c9c0bf9SAlexander Graf trace_hvf_unknown_hvc(env->xregs[0]); 1030*2c9c0bf9SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 1031*2c9c0bf9SAlexander Graf } 1032a1477da3SAlexander Graf break; 1033a1477da3SAlexander Graf case EC_AA64_SMC: 1034a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1035*2c9c0bf9SAlexander Graf if (arm_cpu->psci_conduit == QEMU_PSCI_CONDUIT_SMC) { 1036*2c9c0bf9SAlexander Graf advance_pc = true; 1037*2c9c0bf9SAlexander Graf 1038*2c9c0bf9SAlexander Graf if (!hvf_handle_psci_call(cpu)) { 1039*2c9c0bf9SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 1040*2c9c0bf9SAlexander Graf /* SMCCC 1.3 section 5.2 says every unknown SMCCC call returns -1 */ 1041*2c9c0bf9SAlexander Graf env->xregs[0] = -1; 1042*2c9c0bf9SAlexander Graf } 1043*2c9c0bf9SAlexander Graf } else { 1044a1477da3SAlexander Graf trace_hvf_unknown_smc(env->xregs[0]); 1045a1477da3SAlexander Graf hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized()); 1046*2c9c0bf9SAlexander Graf } 1047a1477da3SAlexander Graf break; 1048a1477da3SAlexander Graf default: 1049a1477da3SAlexander Graf cpu_synchronize_state(cpu); 1050a1477da3SAlexander Graf trace_hvf_exit(syndrome, ec, env->pc); 1051a1477da3SAlexander Graf error_report("0x%llx: unhandled exception ec=0x%x", env->pc, ec); 1052a1477da3SAlexander Graf } 1053a1477da3SAlexander Graf 1054a1477da3SAlexander Graf if (advance_pc) { 1055a1477da3SAlexander Graf uint64_t pc; 1056a1477da3SAlexander Graf 1057a1477da3SAlexander Graf flush_cpu_state(cpu); 1058a1477da3SAlexander Graf 1059a1477da3SAlexander Graf r = hv_vcpu_get_reg(cpu->hvf->fd, HV_REG_PC, &pc); 1060a1477da3SAlexander Graf assert_hvf_ok(r); 1061a1477da3SAlexander Graf pc += 4; 1062a1477da3SAlexander Graf r = hv_vcpu_set_reg(cpu->hvf->fd, HV_REG_PC, pc); 1063a1477da3SAlexander Graf assert_hvf_ok(r); 1064a1477da3SAlexander Graf } 1065a1477da3SAlexander Graf 1066a1477da3SAlexander Graf return 0; 1067a1477da3SAlexander Graf } 1068a1477da3SAlexander Graf 1069a1477da3SAlexander Graf static const VMStateDescription vmstate_hvf_vtimer = { 1070a1477da3SAlexander Graf .name = "hvf-vtimer", 1071a1477da3SAlexander Graf .version_id = 1, 1072a1477da3SAlexander Graf .minimum_version_id = 1, 1073a1477da3SAlexander Graf .fields = (VMStateField[]) { 1074a1477da3SAlexander Graf VMSTATE_UINT64(vtimer_val, HVFVTimer), 1075a1477da3SAlexander Graf VMSTATE_END_OF_LIST() 1076a1477da3SAlexander Graf }, 1077a1477da3SAlexander Graf }; 1078a1477da3SAlexander Graf 1079a1477da3SAlexander Graf static void hvf_vm_state_change(void *opaque, bool running, RunState state) 1080a1477da3SAlexander Graf { 1081a1477da3SAlexander Graf HVFVTimer *s = opaque; 1082a1477da3SAlexander Graf 1083a1477da3SAlexander Graf if (running) { 1084a1477da3SAlexander Graf /* Update vtimer offset on all CPUs */ 1085a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time() - s->vtimer_val; 1086a1477da3SAlexander Graf cpu_synchronize_all_states(); 1087a1477da3SAlexander Graf } else { 1088a1477da3SAlexander Graf /* Remember vtimer value on every pause */ 1089a1477da3SAlexander Graf s->vtimer_val = hvf_vtimer_val_raw(); 1090a1477da3SAlexander Graf } 1091a1477da3SAlexander Graf } 1092a1477da3SAlexander Graf 1093a1477da3SAlexander Graf int hvf_arch_init(void) 1094a1477da3SAlexander Graf { 1095a1477da3SAlexander Graf hvf_state->vtimer_offset = mach_absolute_time(); 1096a1477da3SAlexander Graf vmstate_register(NULL, 0, &vmstate_hvf_vtimer, &vtimer); 1097a1477da3SAlexander Graf qemu_add_vm_change_state_handler(hvf_vm_state_change, &vtimer); 1098a1477da3SAlexander Graf return 0; 1099a1477da3SAlexander Graf } 1100