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: *; }; }