git: d957343f8713 - main - linux(4): Rework signal trampoline on Aarch64
Date: Sun, 14 May 2023 21:31:09 UTC
The branch main has been updated by dchagin:
URL: https://cgit.FreeBSD.org/src/commit/?id=d957343f8713a312442a0140b7a7752ed7b2d870
commit d957343f8713a312442a0140b7a7752ed7b2d870
Author: Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-05-14 21:27:31 +0000
Commit: Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-05-14 21:27:31 +0000
linux(4): Rework signal trampoline on Aarch64
To avoid clobbering of any registers by the trampoline code use Linux
way to call signal handlers. I.e., we are out from the kernel right into
the signal handler, put return address from the signal handler into the
link register.
The mysterious NOP is required for some unwinders (e.g. libc++) that
unconditionally subtract one from the result of _Unwind_GetIP() in order
to identify the calling function.
MFC after: 1 week
---
sys/arm64/linux/linux_locore.asm | 5 +++--
sys/arm64/linux/linux_sysvec.c | 6 +++---
sys/arm64/linux/linux_vdso.lds.s | 1 +
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/sys/arm64/linux/linux_locore.asm b/sys/arm64/linux/linux_locore.asm
index 6ebecef51b39..de3e5dd52a00 100644
--- a/sys/arm64/linux/linux_locore.asm
+++ b/sys/arm64/linux/linux_locore.asm
@@ -45,10 +45,11 @@ linux_platform:
.text
- nop /* This is what Linux calls a "Mysterious NOP". */
EENTRY(__kernel_rt_sigreturn)
- blr x8
+ nop /* This is what Linux calls a "Mysterious NOP". */
+ .globl __user_rt_sigreturn
+__user_rt_sigreturn:
mov x8, #LINUX_SYS_linux_rt_sigreturn
svc #0
EEND(__kernel_rt_sigreturn)
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index 299586e1c7b6..bb9ff25893eb 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -118,7 +118,7 @@ LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo);
LINUX_VDSO_SYM_CHAR(linux_platform);
LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
-LINUX_VDSO_SYM_INTPTR(__kernel_rt_sigreturn);
+LINUX_VDSO_SYM_INTPTR(__user_rt_sigreturn);
static int
linux_fetch_syscall_args(struct thread *td)
@@ -353,9 +353,9 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
tf->tf_x[2] = 0;
}
tf->tf_x[29] = (register_t)&fp->fp;
- tf->tf_x[8] = (register_t)catcher;
+ tf->tf_elr = (register_t)catcher;
tf->tf_sp = (register_t)fp;
- tf->tf_elr = (register_t)__kernel_rt_sigreturn;
+ tf->tf_lr = (register_t)__user_rt_sigreturn;
CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
tf->tf_sp);
diff --git a/sys/arm64/linux/linux_vdso.lds.s b/sys/arm64/linux/linux_vdso.lds.s
index 652b99545069..3f6b70c09176 100644
--- a/sys/arm64/linux/linux_vdso.lds.s
+++ b/sys/arm64/linux/linux_vdso.lds.s
@@ -70,6 +70,7 @@ VERSION
global:
linux_platform;
kern_timekeep_base;
+ __user_rt_sigreturn;
local: *;
};
}