git: 3f3bfb826601 - stable/13 - linux(4): Move sigframe definitions to separate headers

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Fri, 17 Jun 2022 19:40:34 UTC
The branch stable/13 has been updated by dchagin:

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

commit 3f3bfb826601d0d5581438c357a5dabd35aef9d2
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-15 18:03:01 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:35:20 +0000

    linux(4): Move sigframe definitions to separate headers
    
    The signal trampoine-related definitions are used only in the MD part
    of code, wherefore moved from everywhere used linux.h to separate MD
    headers.
    
    MFC after:              2 weeks
    
    (cherry picked from commit 21f246174184742ba8952aeb1dadbf58d48d54b4)
---
 sys/amd64/linux/linux.h              |  65 ------------
 sys/amd64/linux/linux_genassym.c     |   2 +
 sys/amd64/linux/linux_sysvec.c       |   2 +
 sys/amd64/linux32/linux.h            |  90 ----------------
 sys/amd64/linux32/linux32_genassym.c |   2 +
 sys/amd64/linux32/linux32_sysvec.c   |   2 +
 sys/arm64/linux/linux.h              |  10 --
 sys/arm64/linux/linux_sigframe.h     |  44 ++++++++
 sys/arm64/linux/linux_sysvec.c       |   2 +
 sys/i386/linux/linux.h               |  92 ----------------
 sys/i386/linux/linux_genassym.c      |   2 +
 sys/i386/linux/linux_sysvec.c        |  14 +--
 sys/x86/linux/linux_x86_sigframe.h   | 196 +++++++++++++++++++++++++++++++++++
 13 files changed, 260 insertions(+), 263 deletions(-)

diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h
index 08cf3d4b6bbd..51a2906f45cf 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -182,59 +182,6 @@ typedef struct {
 	l_size_t	ss_size;
 } l_stack_t;
 
-struct l_fpstate {
-	u_int16_t cwd;
-	u_int16_t swd;
-	u_int16_t twd;
-	u_int16_t fop;
-	u_int64_t rip;
-	u_int64_t rdp;
-	u_int32_t mxcsr;
-	u_int32_t mxcsr_mask;
-	u_int32_t st_space[32];
-	u_int32_t xmm_space[64];
-	u_int32_t reserved2[24];
-};
-
-struct l_sigcontext {
-	l_ulong		sc_r8;
-	l_ulong		sc_r9;
-	l_ulong		sc_r10;
-	l_ulong		sc_r11;
-	l_ulong		sc_r12;
-	l_ulong		sc_r13;
-	l_ulong		sc_r14;
-	l_ulong		sc_r15;
-	l_ulong		sc_rdi;
-	l_ulong		sc_rsi;
-	l_ulong		sc_rbp;
-	l_ulong		sc_rbx;
-	l_ulong		sc_rdx;
-	l_ulong		sc_rax;
-	l_ulong		sc_rcx;
-	l_ulong		sc_rsp;
-	l_ulong		sc_rip;
-	l_ulong		sc_rflags;
-	l_ushort	sc_cs;
-	l_ushort	sc_gs;
-	l_ushort	sc_fs;
-	l_ushort	sc___pad0;
-	l_ulong		sc_err;
-	l_ulong		sc_trapno;
-	l_sigset_t	sc_mask;
-	l_ulong		sc_cr2;
-	struct l_fpstate *sc_fpstate;
-	l_ulong		sc_reserved1[8];
-};
-
-struct l_ucontext {
-	l_ulong		uc_flags;
-	l_uintptr_t	uc_link;
-	l_stack_t	uc_stack;
-	struct l_sigcontext	uc_mcontext;
-	l_sigset_t	uc_sigmask;
-};
-
 #define LINUX_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 #define	LINUX_SI_MAX_SIZE	128
 #define	LINUX_SI_PAD_SIZE	((LINUX_SI_MAX_SIZE - \
@@ -304,18 +251,6 @@ typedef struct l_siginfo {
 #define	lsi_band	_sifields._sigpoll._band
 #define	lsi_fd		_sifields._sigpoll._fd
 
-/*
- * 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_rt_sigframe {
-	struct l_ucontext	sf_sc;
-	struct l_siginfo	sf_si;
-};
-
 /*
  * mount flags
  */
diff --git a/sys/amd64/linux/linux_genassym.c b/sys/amd64/linux/linux_genassym.c
index 73febbe6ef40..a468520431dc 100644
--- a/sys/amd64/linux/linux_genassym.c
+++ b/sys/amd64/linux/linux_genassym.c
@@ -8,6 +8,8 @@ __FBSDID("$FreeBSD$");
 #include <amd64/linux/linux.h>
 #include <compat/linux/linux_mib.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 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_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index 4c0806cc5c03..ea9cb74dab0d 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_util.h>
 #include <compat/linux/linux_vdso.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 MODULE_VERSION(linux64, 1);
 
 #define	LINUX_VDSOPAGE_SIZE	PAGE_SIZE * 2
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index ba7aeac517e1..1987ff515275 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -287,40 +287,6 @@ typedef struct {
 	l_size_t	ss_size;
 } l_stack_t;
 
-/* The Linux sigcontext, pretty much a standard 386 trapframe. */
-struct l_sigcontext {
-	l_uint		sc_gs;
-	l_uint		sc_fs;
-	l_uint		sc_es;
-	l_uint		sc_ds;
-	l_uint		sc_edi;
-	l_uint		sc_esi;
-	l_uint		sc_ebp;
-	l_uint		sc_esp;
-	l_uint		sc_ebx;
-	l_uint		sc_edx;
-	l_uint		sc_ecx;
-	l_uint		sc_eax;
-	l_uint		sc_trapno;
-	l_uint		sc_err;
-	l_uint		sc_eip;
-	l_uint		sc_cs;
-	l_uint		sc_eflags;
-	l_uint		sc_esp_at_signal;
-	l_uint		sc_ss;
-	l_uint		sc_387;
-	l_uint		sc_mask;
-	l_uint		sc_cr2;
-};
-
-struct l_ucontext {
-	l_ulong		uc_flags;
-	l_uintptr_t	uc_link;
-	l_stack_t	uc_stack;
-	struct l_sigcontext	uc_mcontext;
-	l_sigset_t	uc_sigmask;
-} __packed;
-
 #define	LINUX_SI_MAX_SIZE	128
 #define	LINUX_SI_PAD_SIZE	((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
 
@@ -389,62 +355,6 @@ typedef struct l_siginfo {
 #define	lsi_band	_sifields._sigpoll._band
 #define	lsi_fd		_sifields._sigpoll._fd
 
-struct l_fpreg {
-	u_int16_t	significand[4];
-	u_int16_t	exponent;
-};
-
-struct l_fpxreg {
-	u_int16_t	significand[4];
-	u_int16_t	exponent;
-	u_int16_t	padding[3];
-};
-
-struct l_xmmreg {
-	u_int32_t	element[4];
-};
-
-struct l_fpstate {
-	/* Regular FPU environment */
-	u_int32_t		cw;
-	u_int32_t		sw;
-	u_int32_t		tag;
-	u_int32_t		ipoff;
-	u_int32_t		cssel;
-	u_int32_t		dataoff;
-	u_int32_t		datasel;
-	struct l_fpreg		_st[8];
-	u_int16_t		status;
-	u_int16_t		magic;		/* 0xffff = regular FPU data */
-
-	/* FXSR FPU environment */
-	u_int32_t		_fxsr_env[6];	/* env is ignored. */
-	u_int32_t		mxcsr;
-	u_int32_t		reserved;
-	struct l_fpxreg		_fxsr_st[8];	/* reg data is ignored. */
-	struct l_xmmreg		_xmm[8];
-	u_int32_t		padding[56];
-};
-
-/*
- * 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().
- */
-struct l_sigframe {
-	l_int			sf_sig;
-	struct l_sigcontext	sf_sc;
-	struct l_fpstate	sf_fpstate;
-	l_uint			sf_extramask[1];
-};
-
-struct l_rt_sigframe {
-	l_int			sf_sig;
-	l_uintptr_t		sf_siginfo;
-	l_uintptr_t		sf_ucontext;
-	l_siginfo_t		sf_si;
-	struct l_ucontext	sf_sc;
-} __packed;
-
 /*
  * arch specific open/fcntl flags
  */
diff --git a/sys/amd64/linux32/linux32_genassym.c b/sys/amd64/linux32/linux32_genassym.c
index ca618c01ffab..2bc2586ebe4a 100644
--- a/sys/amd64/linux32/linux32_genassym.c
+++ b/sys/amd64/linux32/linux32_genassym.c
@@ -9,6 +9,8 @@ __FBSDID("$FreeBSD$");
 #include <amd64/linux32/linux.h>
 #include <compat/linux/linux_mib.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
 ASSYM(LINUX_RT_SIGF_SC, offsetof(struct l_ucontext, uc_mcontext));
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 967a5135fab9..5f9922aaf708 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -91,6 +91,8 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_util.h>
 #include <compat/linux/linux_vdso.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 MODULE_VERSION(linux, 1);
 
 #define	LINUX32_MAXUSER		((1ul << 32) - PAGE_SIZE)
diff --git a/sys/arm64/linux/linux.h b/sys/arm64/linux/linux.h
index d43795a71a83..b6e2af506ad2 100644
--- a/sys/arm64/linux/linux.h
+++ b/sys/arm64/linux/linux.h
@@ -248,16 +248,6 @@ typedef struct l_siginfo {
 #define	lsi_band	_sifields._sigpoll._band
 #define	lsi_fd		_sifields._sigpoll._fd
 
-/*
- * This structure is different from the one used by Linux,
- * but it doesn't matter - it's not user-accessible.  We need
- * it instead of the native one because of l_siginfo.
- */
-struct l_sigframe {
-	struct l_siginfo	sf_si;
-	ucontext_t		sf_uc;
-};
-
 union l_semun {
 	l_int		val;
 	l_uintptr_t	buf;
diff --git a/sys/arm64/linux/linux_sigframe.h b/sys/arm64/linux/linux_sigframe.h
new file mode 100644
index 000000000000..060b89c920ac
--- /dev/null
+++ b/sys/arm64/linux/linux_sigframe.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * Copyright (c) 2013 Dmitry Chagin <dchagin@FreeBSD.org>
+ * Copyright (c) 2018 Turing Robotic Industries Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $FreeBSD$
+ */
+#ifndef _ARM64_LINUX_SIGFRAME_H_
+#define	_ARM64_LINUX_SIGFRAME_H_
+
+/*
+ * This structure is different from the one used by Linux,
+ * but it doesn't matter - it's not user-accessible.  We need
+ * it instead of the native one because of l_siginfo.
+ */
+struct l_sigframe {
+	struct l_siginfo	sf_si;
+	ucontext_t		sf_uc;
+};
+
+#endif /* _ARM64_LINUX_SIGFRAME_H_ */
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index 98db5dd12c3b..f5ead58beef3 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -68,6 +68,8 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_util.h>
 #include <compat/linux/linux_vdso.h>
 
+#include <arm64/linux/linux_sigframe.h>
+
 #include <machine/md_var.h>
 
 #ifdef VFP
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index c26294ddc178..75995587373b 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -218,8 +218,6 @@ struct l_statfs64 {
 	l_int		f_spare[4];
 };
 
-#define	LINUX_NSIG_WORDS	2
-
 /* sigaction flags */
 #define	LINUX_SA_NOCLDSTOP	0x00000001
 #define	LINUX_SA_NOCLDWAIT	0x00000002
@@ -262,40 +260,6 @@ typedef struct {
 	l_size_t	ss_size;
 } l_stack_t;
 
-/* The Linux sigcontext, pretty much a standard 386 trapframe. */
-struct l_sigcontext {
-	l_int		sc_gs;
-	l_int		sc_fs;
-	l_int		sc_es;
-	l_int		sc_ds;
-	l_int		sc_edi;
-	l_int		sc_esi;
-	l_int		sc_ebp;
-	l_int		sc_esp;
-	l_int		sc_ebx;
-	l_int		sc_edx;
-	l_int		sc_ecx;
-	l_int		sc_eax;
-	l_int		sc_trapno;
-	l_int		sc_err;
-	l_int		sc_eip;
-	l_int		sc_cs;
-	l_int		sc_eflags;
-	l_int		sc_esp_at_signal;
-	l_int		sc_ss;
-	l_int		sc_387;
-	l_int		sc_mask;
-	l_int		sc_cr2;
-};
-
-struct l_ucontext {
-	l_ulong		uc_flags;
-	void		*uc_link;
-	l_stack_t	uc_stack;
-	struct l_sigcontext	uc_mcontext;
-	l_sigset_t	uc_sigmask;
-};
-
 #define	LINUX_SI_MAX_SIZE	128
 #define	LINUX_SI_PAD_SIZE	((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
 
@@ -364,62 +328,6 @@ typedef struct l_siginfo {
 #define	lsi_band	_sifields._sigpoll._band
 #define	lsi_fd		_sifields._sigpoll._fd
 
-struct l_fpreg {
-	u_int16_t	significand[4];
-	u_int16_t	exponent;
-};
-
-struct l_fpxreg {
-	u_int16_t	significand[4];
-	u_int16_t	exponent;
-	u_int16_t	padding[3];
-};
-
-struct l_xmmreg {
-	u_int32_t	element[4];
-};
-
-struct l_fpstate {
-	/* Regular FPU environment */
-	u_int32_t		cw;
-	u_int32_t		sw;
-	u_int32_t		tag;
-	u_int32_t		ipoff;
-	u_int32_t		cssel;
-	u_int32_t		dataoff;
-	u_int32_t		datasel;
-	struct l_fpreg		_st[8];
-	u_int16_t		status;
-	u_int16_t		magic;		/* 0xffff = regular FPU data */
-
-	/* FXSR FPU environment */
-	u_int32_t		_fxsr_env[6];	/* env is ignored. */
-	u_int32_t		mxcsr;
-	u_int32_t		reserved;
-	struct l_fpxreg		_fxsr_st[8];	/* reg data is ignored. */
-	struct l_xmmreg		_xmm[8];
-	u_int32_t		padding[56];
-};
-
-/*
- * 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().
- */
-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];
-};
-
-struct l_rt_sigframe {
-	l_int			sf_sig;
-	l_siginfo_t		*sf_siginfo;
-	struct l_ucontext	*sf_ucontext;
-	l_siginfo_t		sf_si;
-	struct l_ucontext	sf_sc;
-};
-
 extern struct sysentvec linux_sysvec;
 
 /*
diff --git a/sys/i386/linux/linux_genassym.c b/sys/i386/linux/linux_genassym.c
index 08aa0979d793..1491ce586b09 100644
--- a/sys/i386/linux/linux_genassym.c
+++ b/sys/i386/linux/linux_genassym.c
@@ -8,6 +8,8 @@ __FBSDID("$FreeBSD$");
 #include <i386/linux/linux.h>
 #include <compat/linux/linux_mib.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 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));
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 13591c569aae..c747748e87b5 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -74,6 +74,8 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_util.h>
 #include <compat/linux/linux_vdso.h>
 
+#include <x86/linux/linux_x86_sigframe.h>
+
 MODULE_VERSION(linux, 1);
 
 #define	LINUX_VDSOPAGE_SIZE	PAGE_SIZE * 2
@@ -423,8 +425,8 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	bzero(&frame, sizeof(frame));
 
 	frame.sf_sig = sig;
-	frame.sf_siginfo = &fp->sf_si;
-	frame.sf_ucontext = &fp->sf_sc;
+	frame.sf_siginfo = PTROUT(&fp->sf_si);
+	frame.sf_ucontext = PTROUT(&fp->sf_sc);
 
 	/* Fill in POSIX parts. */
 	siginfo_to_lsiginfo(&ksi->ksi_info, &frame.sf_si, sig);
@@ -470,9 +472,9 @@ 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_esp = PTROUT(fp);
 	regs->tf_eip = __kernel_rt_sigreturn;
-	regs->tf_edi = catcher;
+	regs->tf_edi = PTROUT(catcher);
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
 	regs->tf_ds = _udatasel;
@@ -571,9 +573,9 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 	}
 
 	/* Build context to run handler in. */
-	regs->tf_esp = (int)fp;
+	regs->tf_esp = PTROUT(fp);
 	regs->tf_eip = __kernel_sigreturn;
-	regs->tf_edi = catcher;
+	regs->tf_edi = PTROUT(catcher);
 	regs->tf_eflags &= ~(PSL_T | PSL_VM | PSL_D);
 	regs->tf_cs = _ucodesel;
 	regs->tf_ds = _udatasel;
diff --git a/sys/x86/linux/linux_x86_sigframe.h b/sys/x86/linux/linux_x86_sigframe.h
new file mode 100644
index 000000000000..13294740eb39
--- /dev/null
+++ b/sys/x86/linux/linux_x86_sigframe.h
@@ -0,0 +1,196 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2004 Tim J. Robbins
+ * Copyright (c) 2001 Doug Rabson
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _X86_LINUX_SIGFRAME_H_
+#define	_X86_LINUX_SIGFRAME_H_
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+
+/* The Linux sigcontext, pretty much a standard 386 trapframe. */
+struct l_sigcontext {
+	l_uint		sc_gs;
+	l_uint		sc_fs;
+	l_uint		sc_es;
+	l_uint		sc_ds;
+	l_uint		sc_edi;
+	l_uint		sc_esi;
+	l_uint		sc_ebp;
+	l_uint		sc_esp;
+	l_uint		sc_ebx;
+	l_uint		sc_edx;
+	l_uint		sc_ecx;
+	l_uint		sc_eax;
+	l_uint		sc_trapno;
+	l_uint		sc_err;
+	l_uint		sc_eip;
+	l_uint		sc_cs;
+	l_uint		sc_eflags;
+	l_uint		sc_esp_at_signal;
+	l_uint		sc_ss;
+	l_uint		sc_387;
+	l_uint		sc_mask;
+	l_uint		sc_cr2;
+};
+
+struct l_ucontext {
+	l_ulong		uc_flags;
+	l_uintptr_t	uc_link;
+	l_stack_t	uc_stack;
+	struct l_sigcontext	uc_mcontext;
+	l_sigset_t	uc_sigmask;
+} __packed;
+
+struct l_fpreg {
+	u_int16_t	significand[4];
+	u_int16_t	exponent;
+};
+
+struct l_fpxreg {
+	u_int16_t	significand[4];
+	u_int16_t	exponent;
+	u_int16_t	padding[3];
+};
+
+struct l_xmmreg {
+	u_int32_t	element[4];
+};
+
+struct l_fpstate {
+	/* Regular FPU environment */
+	u_int32_t		cw;
+	u_int32_t		sw;
+	u_int32_t		tag;
+	u_int32_t		ipoff;
+	u_int32_t		cssel;
+	u_int32_t		dataoff;
+	u_int32_t		datasel;
+	struct l_fpreg		_st[8];
+	u_int16_t		status;
+	u_int16_t		magic;		/* 0xffff = regular FPU data */
+
+	/* FXSR FPU environment */
+	u_int32_t		_fxsr_env[6];	/* env is ignored. */
+	u_int32_t		mxcsr;
+	u_int32_t		reserved;
+	struct l_fpxreg		_fxsr_st[8];	/* reg data is ignored. */
+	struct l_xmmreg		_xmm[8];
+	u_int32_t		padding[56];
+};
+
+/*
+ * 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().
+ */
+struct l_sigframe {
+	l_int			sf_sig;
+	struct l_sigcontext	sf_sc;
+	struct l_fpstate	sf_fpstate;
+	l_uint			sf_extramask[1];
+};
+
+struct l_rt_sigframe {
+	l_int			sf_sig;
+	l_uintptr_t		sf_siginfo;
+	l_uintptr_t		sf_ucontext;
+	l_siginfo_t		sf_si;
+	struct l_ucontext	sf_sc;
+};
+
+#else
+
+struct l_fpstate {
+	u_int16_t cwd;
+	u_int16_t swd;
+	u_int16_t twd;
+	u_int16_t fop;
+	u_int64_t rip;
+	u_int64_t rdp;
+	u_int32_t mxcsr;
+	u_int32_t mxcsr_mask;
+	u_int32_t st_space[32];
+	u_int32_t xmm_space[64];
+	u_int32_t reserved2[24];
+};
+
+struct l_sigcontext {
+	l_ulong		sc_r8;
+	l_ulong		sc_r9;
+	l_ulong		sc_r10;
+	l_ulong		sc_r11;
+	l_ulong		sc_r12;
+	l_ulong		sc_r13;
+	l_ulong		sc_r14;
+	l_ulong		sc_r15;
+	l_ulong		sc_rdi;
+	l_ulong		sc_rsi;
+	l_ulong		sc_rbp;
+	l_ulong		sc_rbx;
+	l_ulong		sc_rdx;
+	l_ulong		sc_rax;
+	l_ulong		sc_rcx;
+	l_ulong		sc_rsp;
+	l_ulong		sc_rip;
+	l_ulong		sc_rflags;
+	l_ushort	sc_cs;
+	l_ushort	sc_gs;
+	l_ushort	sc_fs;
+	l_ushort	sc___pad0;
+	l_ulong		sc_err;
+	l_ulong		sc_trapno;
+	l_sigset_t	sc_mask;
+	l_ulong		sc_cr2;
+	struct l_fpstate *sc_fpstate;
+	l_ulong		sc_reserved1[8];
+};
+
+struct l_ucontext {
+	l_ulong		uc_flags;
+	l_uintptr_t	uc_link;
+	l_stack_t	uc_stack;
+	struct l_sigcontext	uc_mcontext;
+	l_sigset_t	uc_sigmask;
+};
+
+/*
+ * 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().
+ */
+struct l_rt_sigframe {
+	struct l_ucontext	sf_sc;
+	struct l_siginfo	sf_si;
+};
+
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
+#endif /* !_X86_LINUX_SIGFRAME_H_ */