summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-07-30 14:25:22 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-07-30 17:05:22 +0100
commit987a23224218fa3bb3aa0024ad236dcf29ebde9e (patch)
treecc1a17102330fa5820749ac39d5681dbb39eac80
parent62ae78c77a6d83e6acf083d24e1be8544a5fe7bc (diff)
downloadqemu-987a23224218fa3bb3aa0024ad236dcf29ebde9e.zip
target/arm: Deliver BKPT/BRK exceptions to correct exception level
Most Arm architectural debug exceptions (eg watchpoints) are ignored if the configured "debug exception level" is below the current exception level (so for example EL1 can't arrange to get debug exceptions for EL2 execution). Exceptions generated by the BRK or BPKT instructions are a special case -- they must always cause an exception, so if we're executing above the debug exception level then we must take them to the current exception level. This fixes a bug where executing BRK at EL2 could result in an exception being taken at EL1 (which is strictly forbidden by the architecture). Fixes: https://bugs.launchpad.net/qemu/+bug/1838277 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-id: 20190730132522.27086-1-peter.maydell@linaro.org
-rw-r--r--target/arm/op_helper.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 1ab91f915e..5e1625a1c8 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -370,6 +370,9 @@ void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
*/
void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
{
+ int debug_el = arm_debug_target_el(env);
+ int cur_el = arm_current_el(env);
+
/* FSR will only be used if the debug target EL is AArch32. */
env->exception.fsr = arm_debug_exception_fsr(env);
/* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
@@ -377,7 +380,18 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
* exception/security level.
*/
env->exception.vaddress = 0;
- raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
+ /*
+ * Other kinds of architectural debug exception are ignored if
+ * they target an exception level below the current one (in QEMU
+ * this is checked by arm_generate_debug_exceptions()). Breakpoint
+ * instructions are special because they always generate an exception
+ * to somewhere: if they can't go to the configured debug exception
+ * level they are taken to the current exception level.
+ */
+ if (debug_el < cur_el) {
+ debug_el = cur_el;
+ }
+ raise_exception(env, EXCP_BKPT, syndrome, debug_el);
}
uint32_t HELPER(cpsr_read)(CPUARMState *env)