summaryrefslogtreecommitdiffstats
path: root/target-arm/helper.c
diff options
context:
space:
mode:
authorRob Herring <rob.herring@linaro.org>2014-04-15 19:18:42 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-04-17 21:34:04 +0100
commit6cd8a2649aafb8e53db4a8f0bf0ea629441f8c03 (patch)
tree7b46494b34d745af65a5463a419a92a6e1bc011d /target-arm/helper.c
parent7e09797c299712cafa7bc05dd57c1b13afcc6039 (diff)
downloadhqemu-6cd8a2649aafb8e53db4a8f0bf0ea629441f8c03.zip
hqemu-6cd8a2649aafb8e53db4a8f0bf0ea629441f8c03.tar.gz
target-arm: Implement AArch64 views of fault status and data registers
Implement AArch64 views of ESR_EL1 and FAR_EL1, and make the 32 bit DFSR, DFAR, IFAR share state with them as architecturally specified. The IFSR doesn't share state with any AArch64 register visible at EL1, so just rename the state field without widening it to 64 bits. Signed-off-by: Rob Herring <rob.herring@linaro.org> [PMM: Minor tweaks; fix some bugs involving inconsistencies between use of offsetof() or offsetoflow32() and struct field width] Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Diffstat (limited to 'target-arm/helper.c')
-rw-r--r--target-arm/helper.c38
1 files changed, 25 insertions, 13 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 289a5c0..5f6233b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -475,7 +475,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
{ .name = "DMB", .cp = 15, .crn = 7, .crm = 10, .opc1 = 0, .opc2 = 5,
.access = PL0_W, .type = ARM_CP_NOP },
{ .name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 2,
- .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
+ .access = PL1_RW,
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
.resetvalue = 0, },
/* Watchpoint Fault Address Register : should actually only be present
* for 1136, 1176, 11MPCore.
@@ -1414,11 +1415,16 @@ static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
- .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
+ .access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el1),
+ .resetfn = arm_cp_reset_ignore, },
{ .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
- .fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
+ .fieldoffset = offsetof(CPUARMState, cp15.ifsr_el2), .resetvalue = 0, },
+ { .name = "ESR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .crn = 5, .crm = 2, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.esr_el1), .resetvalue = 0, },
{ .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
@@ -1436,8 +1442,10 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
.access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write,
.resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
.fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) },
- { .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_data),
+ /* 64-bit FAR; this entry also gives us the AArch32 DFAR */
+ { .name = "FAR_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el1),
.resetvalue = 0, },
REGINFO_SENTINEL
};
@@ -1477,7 +1485,8 @@ static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri,
static const ARMCPRegInfo omap_cp_reginfo[] = {
{ .name = "DFSR", .cp = 15, .crn = 5, .crm = CP_ANY,
.opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_OVERRIDE,
- .fieldoffset = offsetof(CPUARMState, cp15.c5_data), .resetvalue = 0, },
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.esr_el1),
+ .resetvalue = 0, },
{ .name = "", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_NOP },
{ .name = "TICONFIG", .cp = 15, .crn = 15, .crm = 1, .opc1 = 0, .opc2 = 0,
@@ -3087,20 +3096,23 @@ void arm_cpu_do_interrupt(CPUState *cs)
env->exception.fsr = 2;
/* Fall through to prefetch abort. */
case EXCP_PREFETCH_ABORT:
- env->cp15.c5_insn = env->exception.fsr;
- env->cp15.c6_insn = env->exception.vaddress;
+ env->cp15.ifsr_el2 = env->exception.fsr;
+ env->cp15.far_el1 = deposit64(env->cp15.far_el1, 32, 32,
+ env->exception.vaddress);
qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
- env->cp15.c5_insn, env->cp15.c6_insn);
+ env->cp15.ifsr_el2, (uint32_t)env->exception.vaddress);
new_mode = ARM_CPU_MODE_ABT;
addr = 0x0c;
mask = CPSR_A | CPSR_I;
offset = 4;
break;
case EXCP_DATA_ABORT:
- env->cp15.c5_data = env->exception.fsr;
- env->cp15.c6_data = env->exception.vaddress;
+ env->cp15.esr_el1 = env->exception.fsr;
+ env->cp15.far_el1 = deposit64(env->cp15.far_el1, 0, 32,
+ env->exception.vaddress);
qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
- env->cp15.c5_data, env->cp15.c6_data);
+ (uint32_t)env->cp15.esr_el1,
+ (uint32_t)env->exception.vaddress);
new_mode = ARM_CPU_MODE_ABT;
addr = 0x10;
mask = CPSR_A | CPSR_I;
OpenPOWER on IntegriCloud