summaryrefslogtreecommitdiffstats
path: root/target/arm/cpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/cpu.h')
-rw-r--r--target/arm/cpu.h64
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: