Skip to content

Commit

Permalink
target-arm: Implement AArch64 views of fault status and data registers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rob Herring authored and pm215 committed Apr 17, 2014
1 parent 7e09797 commit 6cd8a26
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 18 deletions.
2 changes: 1 addition & 1 deletion target-arm/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ static void arm1026_initfn(Object *obj)
ARMCPRegInfo ifar = {
.name = "IFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c6_insn),
.fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el1),
.resetvalue = 0
};
define_one_arm_cp_reg(cpu, &ifar);
Expand Down
7 changes: 3 additions & 4 deletions target-arm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,10 @@ typedef struct CPUARMState {
MPU write buffer control. */
uint32_t pmsav5_data_ap; /* PMSAv5 MPU data access permissions */
uint32_t pmsav5_insn_ap; /* PMSAv5 MPU insn access permissions */
uint32_t c5_insn; /* Fault status registers. */
uint32_t c5_data;
uint32_t ifsr_el2; /* Fault status registers. */
uint64_t esr_el1;
uint32_t c6_region[8]; /* MPU base/size registers. */
uint32_t c6_insn; /* Fault address registers. */
uint32_t c6_data;
uint64_t far_el1; /* Fault address registers. */
uint32_t c7_par; /* Translation result. */
uint32_t c7_par_hi; /* Translation result, high 32 bits */
uint32_t c9_insn; /* Cache lockdown registers. */
Expand Down
38 changes: 25 additions & 13 deletions target-arm/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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),
Expand All @@ -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
};
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 6cd8a26

Please sign in to comment.