From ff1ca0608dc21e56753352bba8b912caef3a120b Mon Sep 17 00:00:00 2001 From: Fabian Aggeler Date: Mon, 12 Feb 2018 09:17:49 -0500 Subject: [PATCH] target-arm: make IFAR/DFAR banked When EL3 is running in AArch32 (or ARMv7 with Security Extensions) IFAR and DFAR have a secure and a non-secure instance. Backports commit b848ce2b9cbd38da3f2530fd93dba76dba0621c0 from qemu --- qemu/target-arm/cpu.c | 2 +- qemu/target-arm/cpu.h | 19 ++++++++++++++++++- qemu/target-arm/helper.c | 15 ++++++++------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/qemu/target-arm/cpu.c b/qemu/target-arm/cpu.c index 893614b4..70382418 100644 --- a/qemu/target-arm/cpu.c +++ b/qemu/target-arm/cpu.c @@ -499,7 +499,7 @@ static void arm1026_initfn(struct uc_struct *uc, Object *obj, void *opaque) ifar.opc1 = 0; ifar.opc2 = 1; ifar.access = PL1_RW; - ifar.fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[1]); + ifar.fieldoffset = offsetof(CPUARMState, cp15.ifar_ns), ifar.resetvalue = 0; define_one_arm_cp_reg(cpu, &ifar); } diff --git a/qemu/target-arm/cpu.h b/qemu/target-arm/cpu.h index 7346a8b3..150b9318 100644 --- a/qemu/target-arm/cpu.h +++ b/qemu/target-arm/cpu.h @@ -263,7 +263,24 @@ typedef struct CPUARMState { uint64_t esr_el[4]; }; uint32_t c6_region[8]; /* MPU base/size registers. */ - uint64_t far_el[4]; /* Fault address registers. */ + union { /* Fault address registers. */ + struct { + uint64_t _unused_far0; +#ifdef HOST_WORDS_BIGENDIAN + uint32_t ifar_ns; + uint32_t dfar_ns; + uint32_t ifar_s; + uint32_t dfar_s; +#else + uint32_t dfar_ns; + uint32_t ifar_ns; + uint32_t dfar_s; + uint32_t ifar_s; +#endif + uint64_t _unused_far3; + }; + uint64_t far_el[4]; + }; uint64_t par_el1; /* Translation result. */ uint32_t c9_insn; /* Cache lockdown registers. */ uint32_t c9_data; diff --git a/qemu/target-arm/helper.c b/qemu/target-arm/helper.c index 1d896b24..6c86cb31 100644 --- a/qemu/target-arm/helper.c +++ b/qemu/target-arm/helper.c @@ -444,7 +444,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { { "DMB", 15,7,10, 0,0,5, 0, ARM_CP_NOP, PL0_W, }, { "IFAR", 15,6,0, 0,0,2, 0, - 0, PL1_RW, 0, NULL, 0, offsetofhigh32(CPUARMState, cp15.far_el[1]), }, + 0, PL1_RW, 0, NULL, 0, 0, + { offsetof(CPUARMState, cp15.ifar_s), offsetof(CPUARMState, cp15.ifar_ns) } }, /* Watchpoint Fault Address Register : should actually only be present * for 1136, 1176, 11MPCore. */ @@ -1431,9 +1432,11 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = { ARM_CP_NO_MIGRATE, PL1_RW, 0, NULL, 0, 0, { offsetoflow32(CPUARMState, cp15.tcr_el[3]), offsetoflow32(CPUARMState, cp15.tcr_el[1]) }, NULL, NULL, vmsa_ttbcr_write, NULL, vmsa_ttbcr_raw_write, arm_cp_reset_ignore, }, - /* 64-bit FAR; this entry also gives us the AArch32 DFAR */ - { "FAR_EL1", 0,6,0, 3,0,0, ARM_CP_STATE_BOTH, + { "FAR_EL1", 0,6,0, 3,0,0, ARM_CP_STATE_AA64, 0, PL1_RW, 0, NULL, 0, offsetof(CPUARMState, cp15.far_el[1]), }, + { "DFAR", 15,6,0, 0,0,0, 0,0, + PL1_RW, 0, NULL, 0, 0, + { offsetof(CPUARMState, cp15.dfar_s), offsetof(CPUARMState, cp15.dfar_ns) } }, REGINFO_SENTINEL }; @@ -3828,8 +3831,7 @@ void arm_cpu_do_interrupt(CPUState *cs) /* Fall through to prefetch abort. */ case EXCP_PREFETCH_ABORT: A32_BANKED_CURRENT_REG_SET(env, ifsr, env->exception.fsr); - env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 32, 32, - env->exception.vaddress); + A32_BANKED_CURRENT_REG_SET(env, ifar, env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n", env->exception.fsr, (uint32_t)env->exception.vaddress); new_mode = ARM_CPU_MODE_ABT; @@ -3839,8 +3841,7 @@ void arm_cpu_do_interrupt(CPUState *cs) break; case EXCP_DATA_ABORT: A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr); - env->cp15.far_el[1] = deposit64(env->cp15.far_el[1], 0, 32, - env->exception.vaddress); + A32_BANKED_CURRENT_REG_SET(env, dfar, env->exception.vaddress); qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n", env->exception.fsr, (uint32_t)env->exception.vaddress);