diff options
Diffstat (limited to 'target/arm/cpu.h')
-rw-r--r-- | target/arm/cpu.h | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h index efb2a8d3f3..4289c33ef4 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1229,6 +1229,12 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) #define HCR_RW (1ULL << 31) #define HCR_CD (1ULL << 32) #define HCR_ID (1ULL << 33) +#define HCR_E2H (1ULL << 34) +/* + * When we actually implement ARMv8.1-VHE we should add HCR_E2H to + * HCR_MASK and then clear it again if the feature bit is not set in + * hcr_write(). + */ #define HCR_MASK ((1ULL << 34) - 1) #define SCR_NS (1U << 0) @@ -2234,6 +2240,54 @@ bool write_cpustate_to_list(ARMCPU *cpu); # define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif +/** + * arm_hcr_el2_imo(): Return the effective value of HCR_EL2.IMO. + * Depending on the values of HCR_EL2.E2H and TGE, this may be + * "behaves as 1 for all purposes other than direct read/write" or + * "behaves as 0 for all purposes other than direct read/write" + */ +static inline bool arm_hcr_el2_imo(CPUARMState *env) +{ + switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { + case HCR_TGE: + return true; + case HCR_TGE | HCR_E2H: + return false; + default: + return env->cp15.hcr_el2 & HCR_IMO; + } +} + +/** + * arm_hcr_el2_fmo(): Return the effective value of HCR_EL2.FMO. + */ +static inline bool arm_hcr_el2_fmo(CPUARMState *env) +{ + switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { + case HCR_TGE: + return true; + case HCR_TGE | HCR_E2H: + return false; + default: + return env->cp15.hcr_el2 & HCR_FMO; + } +} + +/** + * arm_hcr_el2_amo(): Return the effective value of HCR_EL2.AMO. + */ +static inline bool arm_hcr_el2_amo(CPUARMState *env) +{ + switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { + case HCR_TGE: + return true; + case HCR_TGE | HCR_E2H: + return false; + default: + return env->cp15.hcr_el2 & HCR_AMO; + } +} + static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, unsigned int target_el) { @@ -2261,15 +2315,13 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, break; case EXCP_VFIQ: - if (secure || !(env->cp15.hcr_el2 & HCR_FMO) - || (env->cp15.hcr_el2 & HCR_TGE)) { + if (secure || !arm_hcr_el2_fmo(env) || (env->cp15.hcr_el2 & HCR_TGE)) { /* VFIQs are only taken when hypervized and non-secure. */ return false; } return !(env->daif & PSTATE_F); case EXCP_VIRQ: - if (secure || !(env->cp15.hcr_el2 & HCR_IMO) - || (env->cp15.hcr_el2 & HCR_TGE)) { + if (secure || !arm_hcr_el2_imo(env) || (env->cp15.hcr_el2 & HCR_TGE)) { /* VIRQs are only taken when hypervized and non-secure. */ return false; } @@ -2308,7 +2360,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, * to the CPSR.F setting otherwise we further assess the state * below. */ - hcr = (env->cp15.hcr_el2 & HCR_FMO); + hcr = arm_hcr_el2_fmo(env); scr = (env->cp15.scr_el3 & SCR_FIQ); /* When EL3 is 32-bit, the SCR.FW bit controls whether the @@ -2325,7 +2377,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, * when setting the target EL, so it does not have a further * affect here. */ - hcr = (env->cp15.hcr_el2 & HCR_IMO); + hcr = arm_hcr_el2_imo(env); scr = false; break; default: |