summaryrefslogtreecommitdiffstats
path: root/target/arm/mte_helper.c
diff options
context:
space:
mode:
authorRichard Henderson2021-02-12 19:48:59 +0100
committerPeter Maydell2021-02-16 14:17:10 +0100
commit5d70c3510b2cb5664430d25da5d9bcbb7443f63f (patch)
treeafcc0d115b5f44d21632a0a3c253c6c6dc858e6a /target/arm/mte_helper.c
parentlinux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault (diff)
downloadqemu-5d70c3510b2cb5664430d25da5d9bcbb7443f63f.tar.gz
qemu-5d70c3510b2cb5664430d25da5d9bcbb7443f63f.tar.xz
qemu-5d70c3510b2cb5664430d25da5d9bcbb7443f63f.zip
linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error
The real kernel collects _TIF_MTE_ASYNC_FAULT into the current thread's state on any kernel entry (interrupt, exception etc), and then delivers the signal in advance of resuming the thread. This means that while the signal won't be delivered immediately, it will not be delayed forever -- at minimum it will be delivered after the next clock interrupt. We don't have a clock interrupt in linux-user, so we issue a cpu_kick to signal a return to the main loop at the end of the current TB. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210212184902.1251044-29-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/mte_helper.c')
-rw-r--r--target/arm/mte_helper.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
index 153bd1e9df..d55f8d1e1e 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/mte_helper.c
@@ -565,6 +565,16 @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
select = 0;
}
env->cp15.tfsr_el[el] |= 1 << select;
+#ifdef CONFIG_USER_ONLY
+ /*
+ * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
+ * which then sends a SIGSEGV when the thread is next scheduled.
+ * This cpu will return to the main loop at the end of the TB,
+ * which is rather sooner than "normal". But the alternative
+ * is waiting until the next syscall.
+ */
+ qemu_cpu_kick(env_cpu(env));
+#endif
break;
default: