git: ba279bcd6d75 - main - linux(4): Cleanup signal trampolines

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sun, 15 May 2022 18:12:23 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=ba279bcd6d75aa236bcb9ccf11aeb6f51a2f8514

commit ba279bcd6d75aa236bcb9ccf11aeb6f51a2f8514
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-15 18:00:05 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-05-15 18:00:05 +0000

    linux(4): Cleanup signal trampolines
    
    This is the first stage of a signal trampolines refactoring.
    
    From trampolines retired emulation of the 'call' instruction, which is
    replaced by direct call of a signal handler. The signal handler address
    is in the register.
    
    The previous trampoline implemenatation used semi-Linux-way to call
    a signal handler via the 'jmp' instruction. Wherefore the trampoline
    emulated a 'call' instruction to into the stack the return address for
    signal handler's 'ret' instruction.  Wherefore handmade DWARD annotations
    was used.
    
    While here rephrased and removed excessive comments.
    
    MFC after:              2 weeks
---
 sys/amd64/linux/linux.h              |  1 -
 sys/amd64/linux/linux_genassym.c     |  1 -
 sys/amd64/linux/linux_locore.asm     | 19 +++++--------------
 sys/amd64/linux/linux_sysvec.c       |  2 +-
 sys/amd64/linux32/linux.h            |  4 ----
 sys/amd64/linux32/linux32_genassym.c |  2 --
 sys/amd64/linux32/linux32_locore.asm | 34 +++++++++-------------------------
 sys/amd64/linux32/linux32_sysvec.c   |  4 ++--
 sys/i386/linux/linux.h               |  4 ----
 sys/i386/linux/linux_genassym.c      |  2 --
 sys/i386/linux/linux_locore.asm      | 32 ++++++++------------------------
 sys/i386/linux/linux_sysvec.c        |  4 ++--
 12 files changed, 27 insertions(+), 82 deletions(-)

diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h
index 920ca98ce01b..08cf3d4b6bbd 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -314,7 +314,6 @@ typedef struct l_siginfo {
 struct l_rt_sigframe {
 	struct l_ucontext	sf_sc;
 	struct l_siginfo	sf_si;
-	l_handler_t		sf_handler;
 };
 
 /*
diff --git a/sys/amd64/linux/linux_genassym.c b/sys/amd64/linux/linux_genassym.c
index 0edb6a043531..73febbe6ef40 100644
--- a/sys/amd64/linux/linux_genassym.c
+++ b/sys/amd64/linux/linux_genassym.c
@@ -8,7 +8,6 @@ __FBSDID("$FreeBSD$");
 #include <amd64/linux/linux.h>
 #include <compat/linux/linux_mib.h>
 
-ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
 ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
diff --git a/sys/amd64/linux/linux_locore.asm b/sys/amd64/linux/linux_locore.asm
index dd482cb87cc8..8b6833d7352f 100644
--- a/sys/amd64/linux/linux_locore.asm
+++ b/sys/amd64/linux/linux_locore.asm
@@ -11,23 +11,14 @@
 linux_platform:
 	.asciz "x86_64"
 
-
 	.text
-/*
- * To avoid excess stack frame the signal trampoline code emulates
- * the 'call' instruction.
- */
+
 ENTRY(linux_rt_sigcode)
-	movq	%rsp, %rbx			/* preserve sigframe */
-	call	.getip
-.getip:
-	popq	%rax
-	add	$.startrtsigcode-.getip, %rax	/* ret address */
-	pushq	%rax
-	jmp	*LINUX_RT_SIGF_HANDLER(%rbx)
+	movq	%rsp, %rbx			/* rt_sigframe for rt_sigreturn */
+	call	*%rcx				/* call signal handler */
 .startrtsigcode:
-	movq	$LINUX_SYS_linux_rt_sigreturn,%rax   /* linux_rt_sigreturn() */
-	syscall					/* enter kernel with args */
+	movq	$LINUX_SYS_linux_rt_sigreturn, %rax
+	syscall
 	hlt
 .endrtsigcode:
 0:	jmp	0b
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index 1ea274da8935..ea91dcae5d49 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -686,10 +686,10 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	regs->tf_rax = 0;
 	regs->tf_rsi = (register_t)&sfp->sf_si;	/* arg 2 in %rsi */
 	regs->tf_rdx = (register_t)&sfp->sf_sc;	/* arg 3 in %rdx */
+	regs->tf_rcx = (register_t)catcher;
 
 	/* Fill in POSIX parts. */
 	siginfo_to_lsiginfo(&ksi->ksi_info, &sf.sf_si, sig);
-	sf.sf_handler = catcher;
 
 	mtx_unlock(&psp->ps_mtx);
 	PROC_UNLOCK(p);
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index 1273ff485dd9..ba7aeac517e1 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -429,15 +429,12 @@ struct l_fpstate {
 /*
  * We make the stack look like Linux expects it when calling a signal
  * handler, but use the BSD way of calling the handler and sigreturn().
- * This means that we need to pass the pointer to the handler too.
- * It is appended to the frame to not interfere with the rest of it.
  */
 struct l_sigframe {
 	l_int			sf_sig;
 	struct l_sigcontext	sf_sc;
 	struct l_fpstate	sf_fpstate;
 	l_uint			sf_extramask[1];
-	l_handler_t		sf_handler;
 };
 
 struct l_rt_sigframe {
@@ -446,7 +443,6 @@ struct l_rt_sigframe {
 	l_uintptr_t		sf_ucontext;
 	l_siginfo_t		sf_si;
 	struct l_ucontext	sf_sc;
-	l_handler_t		sf_handler;
 } __packed;
 
 /*
diff --git a/sys/amd64/linux32/linux32_genassym.c b/sys/amd64/linux32/linux32_genassym.c
index bc94139c226d..ca618c01ffab 100644
--- a/sys/amd64/linux32/linux32_genassym.c
+++ b/sys/amd64/linux32/linux32_genassym.c
@@ -9,9 +9,7 @@ __FBSDID("$FreeBSD$");
 #include <amd64/linux32/linux.h>
 #include <compat/linux/linux_mib.h>
 
-ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
 ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
-ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
 ASSYM(LINUX_VERSION_CODE, LINUX_VERSION_CODE);
diff --git a/sys/amd64/linux32/linux32_locore.asm b/sys/amd64/linux32/linux32_locore.asm
index f96b3e730f9f..e0409969ee3b 100644
--- a/sys/amd64/linux32/linux32_locore.asm
+++ b/sys/amd64/linux32/linux32_locore.asm
@@ -14,38 +14,22 @@ linux_platform:
 .text
 .code32
 
-/*
- * To avoid excess stack frame the signal trampoline code emulates
- * the 'call' instruction.
- */
 ENTRY(__kernel_sigreturn)
-	movl	%esp, %ebx			/* preserve sigframe */
-	call .getip0
-.getip0:
-	popl	%eax
-	add	$.startsigcode-.getip0, %eax	/* ret address */
-	push	%eax
-	jmp	*LINUX_SIGF_HANDLER(%ebx)
+	movl	%esp, %ebx			/* sigframe for sigreturn */
+	call	*%edi				/* call signal handler */
 .startsigcode:
-	popl	%eax
-	movl	$LINUX32_SYS_linux_sigreturn,%eax	/* linux_sigreturn() */
-	int	$0x80				/* enter kernel with args */
+	popl	%eax				/* gcc unwind code need this */
+	movl	$LINUX32_SYS_linux_sigreturn, %eax
+	int	$0x80
 .endsigcode:
 0:	jmp	0b
 
 ENTRY(__kernel_rt_sigreturn)
-	leal	LINUX_RT_SIGF_UC(%esp),%ebx	/* linux ucp */
-	leal	LINUX_RT_SIGF_SC(%ebx),%ecx	/* linux sigcontext */
-	movl	%esp, %edi
-	call	.getip1
-.getip1:
-	popl	%eax
-	add	$.startrtsigcode-.getip1, %eax	/* ret address */
-	push	%eax
-	jmp	*LINUX_RT_SIGF_HANDLER(%edi)
+	leal	LINUX_RT_SIGF_UC(%esp), %ebx	/* linux ucontext for rt_sigreturn */
+	call	*%edi				/* call signal handler */
 .startrtsigcode:
-	movl	$LINUX32_SYS_linux_rt_sigreturn,%eax   /* linux_rt_sigreturn() */
-	int	$0x80				/* enter kernel with args */
+	movl	$LINUX32_SYS_linux_rt_sigreturn, %eax
+	int	$0x80
 .endrtsigcode:
 0:	jmp	0b
 
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index ed430c8e579a..b2d0f2401bf9 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -314,7 +314,6 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	bzero(&frame, sizeof(frame));
 
-	frame.sf_handler = PTROUT(catcher);
 	frame.sf_sig = sig;
 	frame.sf_siginfo = PTROUT(&fp->sf_si);
 	frame.sf_ucontext = PTROUT(&fp->sf_sc);
@@ -367,6 +366,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	/* Build context to run handler in. */
 	regs->tf_rsp = PTROUT(fp);
 	regs->tf_rip = __kernel_rt_sigreturn;
+	regs->tf_rdi = PTROUT(catcher);
 	regs->tf_rflags &= ~(PSL_T | PSL_D);
 	regs->tf_cs = _ucode32sel;
 	regs->tf_ss = _udatasel;
@@ -431,7 +431,6 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	bzero(&frame, sizeof(frame));
 
-	frame.sf_handler = PTROUT(catcher);
 	frame.sf_sig = sig;
 
 	bsd_to_linux_sigset(mask, &lmask);
@@ -473,6 +472,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	/* Build context to run handler in. */
 	regs->tf_rsp = PTROUT(fp);
 	regs->tf_rip = __kernel_sigreturn;
+	regs->tf_rdi = PTROUT(catcher);
 	regs->tf_rflags &= ~(PSL_T | PSL_D);
 	regs->tf_cs = _ucode32sel;
 	regs->tf_ss = _udatasel;
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 7fed468239a8..c26294ddc178 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -404,15 +404,12 @@ struct l_fpstate {
 /*
  * We make the stack look like Linux expects it when calling a signal
  * handler, but use the BSD way of calling the handler and sigreturn().
- * This means that we need to pass the pointer to the handler too.
- * It is appended to the frame to not interfere with the rest of it.
  */
 struct l_sigframe {
 	l_int			sf_sig;
 	struct l_sigcontext	sf_sc;
 	struct l_fpstate	sf_fpstate;
 	l_uint			sf_extramask[LINUX_NSIG_WORDS-1];
-	l_handler_t		sf_handler;
 };
 
 struct l_rt_sigframe {
@@ -421,7 +418,6 @@ struct l_rt_sigframe {
 	struct l_ucontext	*sf_ucontext;
 	l_siginfo_t		sf_si;
 	struct l_ucontext	sf_sc;
-	l_handler_t		sf_handler;
 };
 
 extern struct sysentvec linux_sysvec;
diff --git a/sys/i386/linux/linux_genassym.c b/sys/i386/linux/linux_genassym.c
index 9735110b0472..08aa0979d793 100644
--- a/sys/i386/linux/linux_genassym.c
+++ b/sys/i386/linux/linux_genassym.c
@@ -8,11 +8,9 @@ __FBSDID("$FreeBSD$");
 #include <i386/linux/linux.h>
 #include <compat/linux/linux_mib.h>
 
-ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
 ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
 ASSYM(LINUX_SC_GS, offsetof(struct l_sigcontext, sc_gs));
 ASSYM(LINUX_SC_EFLAGS, offsetof(struct l_sigcontext, sc_eflags));
-ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
 ASSYM(LINUX_SC_ESP, offsetof(struct l_sigcontext, sc_esp));
diff --git a/sys/i386/linux/linux_locore.asm b/sys/i386/linux/linux_locore.asm
index 4c5246bd5725..3459fb5a56de 100644
--- a/sys/i386/linux/linux_locore.asm
+++ b/sys/i386/linux/linux_locore.asm
@@ -15,38 +15,22 @@ linux_platform:
 
 	.text
 
-/*
- * To avoid excess stack frame the signal trampoline code emulates
- * the 'call' instruction.
- */
 ENTRY(__kernel_sigreturn)
-	movl	%esp, %ebx			/* preserve sigframe */
-	call .getip0
-.getip0:
-	popl	%eax
-	add	$.startsigcode-.getip0, %eax	/* ret address */
-	push	%eax
-	jmp	*LINUX_SIGF_HANDLER(%ebx)
+	movl	%esp, %ebx			/* sigframe for sigreturn */
+	call	*%edi				/* call signal handler */
 .startsigcode:
 	popl	%eax				/* gcc unwind code need this */
-	movl	$LINUX_SYS_linux_sigreturn,%eax	/* linux_sigreturn() */
-	int	$0x80				/* enter kernel with args */
+	movl	$LINUX_SYS_linux_sigreturn, %eax
+	int	$0x80
 .endsigcode:
 0:	jmp	0b
 
 ENTRY(__kernel_rt_sigreturn)
-	leal	LINUX_RT_SIGF_UC(%esp),%ebx	/* linux ucp */
-	leal	LINUX_RT_SIGF_SC(%ebx),%ecx	/* linux sigcontext */
-	movl	%esp, %edi
-	call	.getip1
-.getip1:
-	popl	%eax
-	add	$.startrtsigcode-.getip1, %eax	/* ret address */
-	push	%eax
-	jmp	*LINUX_RT_SIGF_HANDLER(%edi)
+	leal	LINUX_RT_SIGF_UC(%esp), %ebx	/* linux ucontext for rt_sigreturn */
+	call	*%edi				/* call signal handler */
 .startrtsigcode:
-	movl	$LINUX_SYS_linux_rt_sigreturn,%eax   /* linux_rt_sigreturn() */
-	int	$0x80				/* enter kernel with args */
+	movl	$LINUX_SYS_linux_rt_sigreturn, %eax
+	int	$0x80
 .endrtsigcode:
 0:	jmp	0b
 
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 9f0647f73c0c..d37250d7552f 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -422,7 +422,6 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	bzero(&frame, sizeof(frame));
 
-	frame.sf_handler = catcher;
 	frame.sf_sig = sig;
 	frame.sf_siginfo = &fp->sf_si;
 	frame.sf_ucontext = &fp->sf_sc;
@@ -473,6 +472,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	/* Build context to run handler in. */
 	regs->tf_esp = (int)fp;
 	regs->tf_eip = __kernel_rt_sigreturn;
+	regs->tf_edi = catcher;
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
 	regs->tf_ds = _udatasel;
@@ -532,7 +532,6 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 
 	bzero(&frame, sizeof(frame));
 
-	frame.sf_handler = catcher;
 	frame.sf_sig = sig;
 
 	bsd_to_linux_sigset(mask, &lmask);
@@ -574,6 +573,7 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	/* Build context to run handler in. */
 	regs->tf_esp = (int)fp;
 	regs->tf_eip = __kernel_sigreturn;
+	regs->tf_edi = catcher;
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
 	regs->tf_ds = _udatasel;