From 4d695cc85a4c53c322ace27efe64dc7bf96645f0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 12 Feb 2018 22:44:58 -0500 Subject: [PATCH] target-arm: Allow cp access functions to indicate traps to EL2 or EL3 Some coprocessor access functions will need to indicate that the instruction should trap to EL2 or EL3 rather than the default target exception level; add corresponding CPAccessResult enum entries and handling code. Backports commit 38836a2cd47c20daaaa84873e3d6020f19e4bfca from qemu --- qemu/target-arm/cpu.h | 6 +++++- qemu/target-arm/op_helper.c | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/qemu/target-arm/cpu.h b/qemu/target-arm/cpu.h index 3da0276e..7016d9eb 100644 --- a/qemu/target-arm/cpu.h +++ b/qemu/target-arm/cpu.h @@ -1268,7 +1268,8 @@ typedef enum CPAccessResult { /* Access fails due to a configurable trap or enable which would * result in a categorized exception syndrome giving information about * the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6, - * 0xc or 0x18). + * 0xc or 0x18). The exception is taken to the usual target EL (EL1 or + * PL1 if in EL0, otherwise to the current EL). */ CP_ACCESS_TRAP = 1, /* Access fails and results in an exception syndrome 0x0 ("uncategorized"). @@ -1276,6 +1277,9 @@ typedef enum CPAccessResult { * result in this failure is specifically defined by the architecture. */ CP_ACCESS_TRAP_UNCATEGORIZED = 2, + /* As CP_ACCESS_TRAP, but for traps directly to EL2 or EL3 */ + CP_ACCESS_TRAP_EL2 = 3, + CP_ACCESS_TRAP_EL3 = 4, } CPAccessResult; /* Access functions for coprocessor registers. These cannot fail and diff --git a/qemu/target-arm/op_helper.c b/qemu/target-arm/op_helper.c index 02d7bfdb..d50204d5 100644 --- a/qemu/target-arm/op_helper.c +++ b/qemu/target-arm/op_helper.c @@ -335,6 +335,7 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome) { const ARMCPRegInfo *ri = rip; + int target_el; if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14 && extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) { @@ -349,15 +350,27 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome) case CP_ACCESS_OK: return; case CP_ACCESS_TRAP: + target_el = exception_target_el(env); + break; + case CP_ACCESS_TRAP_EL2: + /* Requesting a trap to EL2 when we're in EL3 or S-EL0/1 is + * a bug in the access function. + */ + assert(!arm_is_secure(env) && !arm_current_el(env) == 3); + target_el = 2; + break; + case CP_ACCESS_TRAP_EL3: + target_el = 3; break; case CP_ACCESS_TRAP_UNCATEGORIZED: + target_el = exception_target_el(env); syndrome = syn_uncategorized(); break; default: g_assert_not_reached(); } - raise_exception(env, EXCP_UDEF, syndrome, exception_target_el(env)); + raise_exception(env, EXCP_UDEF, syndrome, target_el); } void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)