diff options
Diffstat (limited to 'target/arm/tcg/op_helper.c')
| -rw-r--r-- | target/arm/tcg/op_helper.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index 1161d301b7..1ba727e8e9 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -758,6 +758,7 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key, const ARMCPRegInfo *ri = get_arm_cp_reginfo(cpu->cp_regs, key); CPAccessResult res = CP_ACCESS_OK; int target_el; + uint32_t excp; assert(ri != NULL); @@ -851,8 +852,18 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key, } fail: + excp = EXCP_UDEF; switch (res & ~CP_ACCESS_EL_MASK) { case CP_ACCESS_TRAP: + /* + * If EL3 is AArch32 then there's no syndrome register; the cases + * where we would raise a SystemAccessTrap to AArch64 EL3 all become + * raising a Monitor trap exception. (Because there's no visible + * syndrome it doesn't matter what we pass to raise_exception().) + */ + if ((res & CP_ACCESS_EL_MASK) == 3 && !arm_el_is_aa64(env, 3)) { + excp = EXCP_MON_TRAP; + } break; case CP_ACCESS_TRAP_UNCATEGORIZED: /* Only CP_ACCESS_TRAP traps are direct to a specified EL */ @@ -888,7 +899,7 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key, g_assert_not_reached(); } - raise_exception(env, EXCP_UDEF, syndrome, target_el); + raise_exception(env, excp, syndrome, target_el); } const void *HELPER(lookup_cp_reg)(CPUARMState *env, uint32_t key) |