@@ -425,6 +425,14 @@ int arm_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
#define SCTLR_AFE (1U << 29)
#define SCTLR_TE (1U << 30)
+/* Bitmask for banked bits (Security Extensions) */
+#define SCTLR_BANKED (SCTLR_TE | SCTLR_AFE | SCTLR_TRE | SCTLR_EE | \
+ SCTLR_VE | SCTLR_HA | SCTLR_UWXN | SCTLR_WXN | SCTLR_V | \
+ SCTLR_I | SCTLR_Z | SCTLR_SW | SCTLR_CP15BEN | SCTLR_C | \
+ SCTLR_A | SCTLR_M)
+/* Treat bits that are not explicitly banked as common */
+#define SCTLR_COMMON (~SCTLR_BANKED)
+
#define CPSR_M (0x1fU)
#define CPSR_T (1U << 5)
#define CPSR_F (1U << 6)
@@ -662,6 +670,8 @@ static inline int arm_feature(CPUARMState *env, int feature)
return (env->features & (1ULL << feature)) != 0;
}
+#define SCR_NS (1U << 0)
+
/* Return true if the processor is in secure state */
static inline bool arm_is_secure(CPUARMState *env)
{
@@ -2165,12 +2165,49 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
}
raw_write(env, ri, value);
+
+ if (!arm_el_is_aa64(env, 3)) {
+ /* Aarch32 has some bits that are common to secure (mapped to
+ * SCTLR_EL3) and non-secure instances of the SCTLR. */
+
+ env->cp15.c1_sys_el1 &= SCTLR_BANKED |
+ (arm_current_sctlr(env) & SCTLR_COMMON);
+ env->cp15.c1_sys_el3 &= SCTLR_BANKED |
+ (arm_current_sctlr(env) & SCTLR_COMMON);
+ }
+
/* ??? Lots of these bits are not implemented. */
/* This may enable/disable the MMU, so do a TLB flush. */
tlb_flush(CPU(cpu), 1);
}
#ifndef CONFIG_USER_ONLY
+static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ if (!arm_el_is_aa64(env, 3) &&
+ (value & SCR_NS) != (env->cp15.c1_scr & SCR_NS)) {
+ /* If EL3 is using Aarch32 switching NS-bit may make the CPU use a
+ * different instance (secure or non-secure) when accessing CP
+ * registers.
+ * Common bits of otherwise banked registers need to by synchronized
+ * at this point.
+ */
+ env->cp15.c1_sys_el1 &= SCTLR_BANKED |
+ (arm_current_sctlr(env) & SCTLR_COMMON);
+ env->cp15.c1_sys_el3 &= SCTLR_BANKED |
+ (arm_current_sctlr(env) & SCTLR_COMMON);
I must be missing something, if the common bits are sync'd across the banks in sctlr_write(), why do we need to do it here?
Right, should not be needed. I’ll remove it.
+ }
+
+ env->cp15.c1_scr = value;
+
+ /* After possible switch, calculate c2_mask and c2_base_mask again for the
+ * instance which is now active (secure or non-secure).
+ */
+ int maskshift = extract32(A32_BANKED_REG_GET(env, c2_control), 0, 3);
+ env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift);
+ env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift);