summaryrefslogtreecommitdiff
path: root/target-arm/op_helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-05-29 11:28:52 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-05-29 11:28:52 +0100
commit38836a2cd47c20daaaa84873e3d6020f19e4bfca (patch)
treefc60a44ad185291c62720987cf47ebd7c59b552f /target-arm/op_helper.c
parent012a906b19e99b126403ff4a257617dab9b34163 (diff)
downloadqemu-38836a2cd47c20daaaa84873e3d6020f19e4bfca.zip
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. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r--target-arm/op_helper.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index a4507dff1b..79e7d10055 100644
--- a/target-arm/op_helper.c
+++ b/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)