diff options
author | Dmitry Chagin <dchagin@FreeBSD.org> | 2023-05-14 21:27:31 +0000 |
---|---|---|
committer | Dmitry Chagin <dchagin@FreeBSD.org> | 2023-05-14 21:27:31 +0000 |
commit | d957343f8713a312442a0140b7a7752ed7b2d870 (patch) | |
tree | f915459b7b1fbbcd87ff28d94f60691756a1ad9a | |
parent | 5f19e18b641add5632e1bf19cce27b5d46e1e55a (diff) | |
download | src-d957343f8713a312442a0140b7a7752ed7b2d870.tar.gz src-d957343f8713a312442a0140b7a7752ed7b2d870.zip |
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
-rw-r--r-- | sys/arm64/linux/linux_locore.asm | 5 | ||||
-rw-r--r-- | sys/arm64/linux/linux_sysvec.c | 6 | ||||
-rw-r--r-- | 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: *; }; } |