aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2023-05-14 21:27:31 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2023-05-14 21:27:31 +0000
commitd957343f8713a312442a0140b7a7752ed7b2d870 (patch)
treef915459b7b1fbbcd87ff28d94f60691756a1ad9a
parent5f19e18b641add5632e1bf19cce27b5d46e1e55a (diff)
downloadsrc-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.asm5
-rw-r--r--sys/arm64/linux/linux_sysvec.c6
-rw-r--r--sys/arm64/linux/linux_vdso.lds.s1
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: *;
};
}