6f08fa6f4d
Add in upstream stable patches. Also a new more minor tweaks. OBS-URL: https://build.opensuse.org/request/show/734440 OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=492
102 lines
4.8 KiB
Diff
102 lines
4.8 KiB
Diff
From: Peter Maydell <peter.maydell@linaro.org>
|
|
Date: Thu, 22 Aug 2019 14:15:34 +0100
|
|
Subject: target/arm: Don't abort on M-profile exception return in linux-user
|
|
mode
|
|
|
|
Git-commit: 5e5584c89f36b302c666bc6db535fd3f7ff35ad2
|
|
|
|
An attempt to do an exception-return (branch to one of the magic
|
|
addresses) in linux-user mode for M-profile should behave like
|
|
a normal branch, because linux-user mode is always going to be
|
|
in 'handler' mode. This used to work, but we broke it when we added
|
|
support for the M-profile security extension in commit d02a8698d7ae2bfed.
|
|
|
|
In that commit we allowed even handler-mode calls to magic return
|
|
values to be checked for and dealt with by causing an
|
|
EXCP_EXCEPTION_EXIT exception to be taken, because this is
|
|
needed for the FNC_RETURN return-from-non-secure-function-call
|
|
handling. For system mode we added a check in do_v7m_exception_exit()
|
|
to make any spurious calls from Handler mode behave correctly, but
|
|
forgot that linux-user mode would also be affected.
|
|
|
|
How an attempted return-from-non-secure-function-call in linux-user
|
|
mode should be handled is not clear -- on real hardware it would
|
|
result in return to secure code (not to the Linux kernel) which
|
|
could then handle the error in any way it chose. For QEMU we take
|
|
the simple approach of treating this erroneous return the same way
|
|
it would be handled on a CPU without the security extensions --
|
|
treat it as a normal branch.
|
|
|
|
The upshot of all this is that for linux-user mode we should never
|
|
do any of the bx_excret magic, so the code change is simple.
|
|
|
|
This ought to be a weird corner case that only affects broken guest
|
|
code (because Linux user processes should never be attempting to do
|
|
exception returns or NS function returns), except that the code that
|
|
assigns addresses in RAM for the process and stack in our linux-user
|
|
code does not attempt to avoid this magic address range, so
|
|
legitimate code attempting to return to a trampoline routine on the
|
|
stack can fall into this case. This change fixes those programs,
|
|
but we should also look at restricting the range of memory we
|
|
use for M-profile linux-user guests to the area that would be
|
|
real RAM in hardware.
|
|
|
|
Cc: qemu-stable@nongnu.org
|
|
Reported-by: Christophe Lyon <christophe.lyon@linaro.org>
|
|
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
|
Message-id: 20190822131534.16602-1-peter.maydell@linaro.org
|
|
Fixes: https://bugs.launchpad.net/qemu/+bug/1840922
|
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
|
Signed-off-by: Bruce Rogers <brogers@suse.com>
|
|
---
|
|
target/arm/translate.c | 21 ++++++++++++++++++++-
|
|
1 file changed, 20 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/target/arm/translate.c b/target/arm/translate.c
|
|
index 7853462b21b870fdc3e3d2166a3e..24cb4ba075d095e050b193570ad2 100644
|
|
--- a/target/arm/translate.c
|
|
+++ b/target/arm/translate.c
|
|
@@ -952,10 +952,27 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
|
|
store_cpu_field(var, thumb);
|
|
}
|
|
|
|
-/* Set PC and Thumb state from var. var is marked as dead.
|
|
+/*
|
|
+ * Set PC and Thumb state from var. var is marked as dead.
|
|
* For M-profile CPUs, include logic to detect exception-return
|
|
* branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
|
|
* and BX reg, and no others, and happens only for code in Handler mode.
|
|
+ * The Security Extension also requires us to check for the FNC_RETURN
|
|
+ * which signals a function return from non-secure state; this can happen
|
|
+ * in both Handler and Thread mode.
|
|
+ * To avoid having to do multiple comparisons in inline generated code,
|
|
+ * we make the check we do here loose, so it will match for EXC_RETURN
|
|
+ * in Thread mode. For system emulation do_v7m_exception_exit() checks
|
|
+ * for these spurious cases and returns without doing anything (giving
|
|
+ * the same behaviour as for a branch to a non-magic address).
|
|
+ *
|
|
+ * In linux-user mode it is unclear what the right behaviour for an
|
|
+ * attempted FNC_RETURN should be, because in real hardware this will go
|
|
+ * directly to Secure code (ie not the Linux kernel) which will then treat
|
|
+ * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
|
|
+ * attempt behave the way it would on a CPU without the security extension,
|
|
+ * which is to say "like a normal branch". That means we can simply treat
|
|
+ * all branches as normal with no magic address behaviour.
|
|
*/
|
|
static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
|
|
{
|
|
@@ -963,10 +980,12 @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
|
|
* s->base.is_jmp that we need to do the rest of the work later.
|
|
*/
|
|
gen_bx(s, var);
|
|
+#ifndef CONFIG_USER_ONLY
|
|
if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
|
|
(s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
|
|
s->base.is_jmp = DISAS_BX_EXCRET;
|
|
}
|
|
+#endif
|
|
}
|
|
|
|
static inline void gen_bx_excret_final_code(DisasContext *s)
|