Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 May 2003 18:24:11 -0700 (PDT)
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 31109 for review
Message-ID:  <200305140124.h4E1OBri066466@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=31109

Change 31109 by peter@peter_hammer on 2003/05/13 18:23:33

	Implement i386 signals properly.  This works for both the 4.x
	and 5.x signal interfaces.  I have not done the 3.x syscall
	interface.  We can't run a.out binaries anyway because the
	lcall syscall method isn't implemented, so this isn't much
	of a loss.  The 3.x sigaction/sigreturn (for elf binaries)
	could be done with a bit more cut/paste though.

Affected files ...

.. //depot/projects/hammer/sys/amd64/amd64/machdep.c#31 edit
.. //depot/projects/hammer/sys/amd64/conf/GENERIC#9 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_genassym.c#1 add
.. //depot/projects/hammer/sys/amd64/ia32/ia32_misc.c#2 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_proto.h#2 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_signal.h#1 add
.. //depot/projects/hammer/sys/amd64/ia32/ia32_sigtramp.S#1 add
.. //depot/projects/hammer/sys/amd64/ia32/ia32_syscall.h#2 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_sysent.c#2 edit
.. //depot/projects/hammer/sys/amd64/ia32/ia32_sysvec.c#2 edit
.. //depot/projects/hammer/sys/amd64/ia32/syscalls.master#2 edit
.. //depot/projects/hammer/sys/amd64/include/md_var.h#10 edit
.. //depot/projects/hammer/sys/conf/files.amd64#10 edit

Differences ...

==== //depot/projects/hammer/sys/amd64/amd64/machdep.c#31 (text+ko) ====

@@ -124,7 +124,6 @@
 #define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
 
 static void cpu_startup(void *);
-static void fpstate_drop(struct thread *td);
 static void get_fpcontext(struct thread *td, mcontext_t *mcp);
 static int  set_fpcontext(struct thread *td, const mcontext_t *mcp);
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
@@ -389,6 +388,16 @@
 	return (EJUSTRETURN);
 }
 
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
+{
+ 
+	return sigreturn(td, (struct sigreturn_args *)uap);
+}
+#endif
+
+
 /*
  * Machine dependent boot() routine
  *
@@ -1628,7 +1637,7 @@
 	return (0);
 }
 
-static void
+void
 fpstate_drop(struct thread *td)
 {
 	register_t s;

==== //depot/projects/hammer/sys/amd64/conf/GENERIC#9 (text+ko) ====

@@ -24,6 +24,7 @@
 maxusers	0
 options		NDA			#Avoid accidental cut/paste of NDA'ed stuff
 options 	IA32
+options 	COMPAT_FREEBSD4
 
 makeoptions	NO_MODULES=not_yet
 

==== //depot/projects/hammer/sys/amd64/ia32/ia32_misc.c#2 (text+ko) ====

@@ -1170,40 +1170,31 @@
 	return (error);
 }
 
-#if 0
-
+#ifdef COMPAT_FREEBSD4
 int
-ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
+freebsd4_ia32_sigaction(struct thread *td, struct freebsd4_ia32_sigaction_args *uap)
 {
+	struct sigaction32 s32;
+	struct sigaction sa, osa, *sap;
 	int error;
-	caddr_t sg;
-	struct yyy32 *p32, s32;
-	struct yyy *p = NULL, s;
 
-	p32 = uap->zzz;
-	if (p32) {
-		sg = stackgap_init();
-		p = stackgap_alloc(&sg, sizeof(struct yyy));
-		uap->zzz = (struct yyy32 *)p;
-		error = copyin(p32, &s32, sizeof(s32));
+	if (uap->act) {
+		error = copyin(uap->act, &s32, sizeof(s32));
 		if (error)
 			return (error);
-		/* translate in */
-		error = copyout(&s, p, sizeof(s));
-		if (error)
-			return (error);
+		sa.sa_handler = PTRIN(s32.sa_u);
+		CP(s32, sa, sa_flags);
+		CP(s32, sa, sa_mask);
+		sap = &sa;
+	} else
+		sap = NULL;
+	error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
+	if (error != 0 && uap->oact != NULL) {
+		s32.sa_u = PTROUT(osa.sa_handler);
+		CP(osa, s32, sa_flags);
+		CP(osa, s32, sa_mask);
+		error = copyout(&s32, uap->oact, sizeof(s32));
 	}
-	error = xxx(td, (struct xxx_args *) uap);
-	if (error)
-		return (error);
-	if (p32) {
-		error = copyin(p, &s, sizeof(s));
-		if (error)
-			return (error);
-		/* translate out */
-		error = copyout(&s32, p32, sizeof(s32));
-	}
 	return (error);
 }
-
 #endif

==== //depot/projects/hammer/sys/amd64/ia32/ia32_proto.h#2 (text+ko) ====

@@ -201,11 +201,6 @@
 	char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)];
 	char newlen_l_[PADL_(u_int32_t)]; u_int32_t newlen; char newlen_r_[PADR_(u_int32_t)];
 };
-struct ia32_sigaction_args {
-	char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
-	char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
-	char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
-};
 struct ia32_sendfile_args {
 	char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
 	char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
@@ -216,6 +211,14 @@
 	char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)];
 	char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
 };
+struct ia32_sigreturn_args {
+	char sigcntxp_l_[PADL_(const struct ia32_ucontext *)]; const struct ia32_ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct ia32_ucontext *)];
+};
+struct ia32_sigaction_args {
+	char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+	char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
+	char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
+};
 int	ia32_open(struct thread *, struct ia32_open_args *);
 int	ia32_wait4(struct thread *, struct ia32_wait4_args *);
 int	ia32_getfsstat(struct thread *, struct ia32_getfsstat_args *);
@@ -247,8 +250,9 @@
 int	ia32_truncate(struct thread *, struct ia32_truncate_args *);
 int	ia32_ftruncate(struct thread *, struct ia32_ftruncate_args *);
 int	ia32_sysctl(struct thread *, struct ia32_sysctl_args *);
+int	ia32_sendfile(struct thread *, struct ia32_sendfile_args *);
+int	ia32_sigreturn(struct thread *, struct ia32_sigreturn_args *);
 int	ia32_sigaction(struct thread *, struct ia32_sigaction_args *);
-int	ia32_sendfile(struct thread *, struct ia32_sendfile_args *);
 
 #ifdef COMPAT_43
 
@@ -268,7 +272,17 @@
 	char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)];
 	char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
 };
+struct freebsd4_ia32_sigaction_args {
+	char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+	char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
+	char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
+};
+struct freebsd4_ia32_sigreturn_args {
+	char sigcntxp_l_[PADL_(const struct __ucontext *)]; const struct __ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct __ucontext *)];
+};
 int	freebsd4_ia32_sendfile(struct thread *, struct freebsd4_ia32_sendfile_args *);
+int	freebsd4_ia32_sigaction(struct thread *, struct freebsd4_ia32_sigaction_args *);
+int	freebsd4_ia32_sigreturn(struct thread *, struct freebsd4_ia32_sigreturn_args *);
 
 #endif /* COMPAT_FREEBSD4 */
 

==== //depot/projects/hammer/sys/amd64/ia32/ia32_syscall.h#2 (text+ko) ====

@@ -252,9 +252,9 @@
 #define	IA32_SYS_jail	338
 #define	IA32_SYS_sigprocmask	340
 #define	IA32_SYS_sigsuspend	341
-#define	IA32_SYS_ia32_sigaction	342
+				/* 342 is old ia32_sigaction */
 #define	IA32_SYS_sigpending	343
-#define	IA32_SYS_sigreturn	344
+				/* 344 is old ia32_sigreturn */
 #define	IA32_SYS___acl_get_file	347
 #define	IA32_SYS___acl_set_file	348
 #define	IA32_SYS___acl_get_fd	349
@@ -286,6 +286,8 @@
 #define	IA32_SYS_lchflags	391
 #define	IA32_SYS_uuidgen	392
 #define	IA32_SYS_ia32_sendfile	393
+#define	IA32_SYS_ia32_sigreturn	416
+#define	IA32_SYS_ia32_sigaction	417
 #define	IA32_SYS_thr_create	430
 #define	IA32_SYS_thr_exit	431
 #define	IA32_SYS_thr_self	432

==== //depot/projects/hammer/sys/amd64/ia32/ia32_sysent.c#2 (text+ko) ====

@@ -367,9 +367,9 @@
 	{ 0, (sy_call_t *)nosys },			/* 339 = pioctl */
 	{ SYF_MPSAFE | AS(sigprocmask_args), (sy_call_t *)sigprocmask },	/* 340 = sigprocmask */
 	{ SYF_MPSAFE | AS(sigsuspend_args), (sy_call_t *)sigsuspend },	/* 341 = sigsuspend */
-	{ AS(ia32_sigaction_args), (sy_call_t *)ia32_sigaction },	/* 342 = ia32_sigaction */
+	{ compat4(AS(freebsd4_ia32_sigaction_args),ia32_sigaction) },	/* 342 = old ia32_sigaction */
 	{ SYF_MPSAFE | AS(sigpending_args), (sy_call_t *)sigpending },	/* 343 = sigpending */
-	{ SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn },	/* 344 = sigreturn */
+	{ compat4(SYF_MPSAFE | AS(freebsd4_ia32_sigreturn_args),ia32_sigreturn) },	/* 344 = old ia32_sigreturn */
 	{ 0, (sy_call_t *)nosys },			/* 345 = sigtimedwait */
 	{ 0, (sy_call_t *)nosys },			/* 346 = sigwaitinfo */
 	{ SYF_MPSAFE | AS(__acl_get_file_args), (sy_call_t *)__acl_get_file },	/* 347 = __acl_get_file */
@@ -441,8 +441,8 @@
 	{ 0, (sy_call_t *)nosys },			/* 413 = extattr_get_link */
 	{ 0, (sy_call_t *)nosys },			/* 414 = extattr_delete_link */
 	{ 0, (sy_call_t *)nosys },			/* 415 = __mac_execve */
-	{ 0, (sy_call_t *)nosys },			/* 416 = newsigreturn */
-	{ 0, (sy_call_t *)nosys },			/* 417 = newsigaction */
+	{ SYF_MPSAFE | AS(ia32_sigreturn_args), (sy_call_t *)ia32_sigreturn },	/* 416 = ia32_sigreturn */
+	{ AS(ia32_sigaction_args), (sy_call_t *)ia32_sigaction },	/* 417 = ia32_sigaction */
 	{ 0, (sy_call_t *)nosys },			/* 418 = __xstat */
 	{ 0, (sy_call_t *)nosys },			/* 419 = __xfstat */
 	{ 0, (sy_call_t *)nosys },			/* 420 = __xlstat */

==== //depot/projects/hammer/sys/amd64/ia32/ia32_sysvec.c#2 (text+ko) ====

@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 2003 Peter Wemm
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,6 +27,8 @@
  * $FreeBSD: src/sys/ia64/ia32/ia32_sysvec.c,v 1.2 2002/09/01 21:41:23 jake Exp $
  */
 
+#include "opt_compat.h"
+
 #define __ELF_WORD_SIZE 32
 
 #include <sys/param.h>
@@ -61,33 +64,33 @@
 #include <vm/vm_extern.h>
 
 #include <amd64/ia32/ia32_util.h>
+#include <amd64/ia32/ia32_proto.h>
+#include <amd64/ia32/ia32_signal.h>
 #include <machine/psl.h>
 #include <machine/segments.h>
 #include <machine/specialreg.h>
 #include <machine/frame.h>
 #include <machine/md_var.h>
 #include <machine/pcb.h>
+#include <machine/cpufunc.h>
 
 static register_t *ia32_copyout_strings(struct image_params *imgp);
 static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
     u_long ps_strings);
 
+#ifdef COMPAT_FREEBSD4
+static void freebsd4_ia32_sendsig(sig_t, int, sigset_t *, u_long);
+#endif
+static void ia32_sendsig(sig_t, int, sigset_t *, u_long);
+static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
+static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
+
 extern struct sysent ia32_sysent[];
 
-static char ia32_sigcode[] = {
-	0xff, 0x54, 0x24, 0x10,		/* call *SIGF_HANDLER(%esp) */
-	0x8d, 0x44, 0x24, 0x14,		/* lea SIGF_UC(%esp),%eax */
-	0x50,				/* pushl %eax */
-	0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
-	0x75, 0x03,			/* jne 9f */
-	0x8e, 0x68, 0x14,		/* movl UC_GS(%eax),%gs */
-	0xb8, 0x57, 0x01, 0x00, 0x00,	/* 9: movl $SYS_sigreturn,%eax */
-	0x50,				/* pushl %eax */
-	0xcd, 0x80,			/* int $0x80 */
-	0xeb, 0xfe,			/* 0: jmp 0b */
-	0, 0, 0, 0
-};
-static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+extern char ia32_sigcode[];
+extern char freebsd4_ia32_sigcode[];
+extern int sz_ia32_sigcode;
+extern int sz_freebsd4_ia32_sigcode;
 
 struct sysentvec ia32_freebsd_sysvec = {
 	SYS_MAXSYSCALL,
@@ -99,9 +102,9 @@
 	NULL,
 	NULL,
 	elf32_freebsd_fixup,
-	sendsig,
+	ia32_sendsig,
 	ia32_sigcode,
-	&ia32_szsigcode,
+	&sz_ia32_sigcode,
 	NULL,
 	"FreeBSD ELF32",
 	elf32_coredump,
@@ -134,6 +137,9 @@
 
 extern int _ucode32sel, _udatasel;
 
+#define	CS_SECURE(cs)		(ISPL(cs) == SEL_UPL)
+#define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+
 static register_t *
 ia32_copyout_strings(struct image_params *imgp)
 {
@@ -290,15 +296,485 @@
 	 */
 	load_cr0(rcr0() | CR0_MP | CR0_TS);
 
-	/* Initialize the npx (if any) for the current process. */
-	s = intr_disable();
-	if (PCPU_GET(fpcurthread) == td)
-		npxdrop();
-	pcb->pcb_flags &= ~PCB_NPXINITDONE;
-	intr_restore(s);
+	fpstate_drop(td);
 
 	/* Return via doreti so that we can change to a different %cs */
 	pcb->pcb_flags |= PCB_FULLCTX;
 	td->td_retval[1] = 0;
 
 }
+
+static void
+ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
+{
+	struct savefpu *addr;
+
+	/*
+	 * XXX mc_fpstate might be misaligned, since its declaration is not
+	 * unportabilized using __attribute__((aligned(16))) like the
+	 * declaration of struct savemm, and anyway, alignment doesn't work
+	 * for auto variables since we don't use gcc's pessimal stack
+	 * alignment.  Work around this by abusing the spare fields after
+	 * mcp->mc_fpstate.
+	 *
+	 * XXX unpessimize most cases by only aligning when fxsave might be
+	 * called, although this requires knowing too much about
+	 * npxgetregs()'s internals.
+	 */
+	addr = (struct savefpu *)&mcp->mc_fpstate;
+	if (td == PCPU_GET(fpcurthread) && ((uintptr_t)(void *)addr & 0xF)) {
+		do
+			addr = (void *)((char *)addr + 4);
+		while ((uintptr_t)(void *)addr & 0xF);
+	}
+	mcp->mc_ownedfp = npxgetregs(td, addr);
+	if (addr != (struct savefpu *)&mcp->mc_fpstate) {
+		bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
+		bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2));
+	}
+	mcp->mc_fpformat = npxformat();
+}
+
+static int
+ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
+{
+	struct savefpu *addr;
+
+	if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
+		return (0);
+	else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
+		return (EINVAL);
+	else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
+		/* We don't care what state is left in the FPU or PCB. */
+		fpstate_drop(td);
+	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
+	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
+		/* XXX align as above. */
+		addr = (struct savefpu *)&mcp->mc_fpstate;
+		if (td == PCPU_GET(fpcurthread) &&
+		    ((uintptr_t)(void *)addr & 0xF)) {
+			do
+				addr = (void *)((char *)addr + 4);
+			while ((uintptr_t)(void *)addr & 0xF);
+			bcopy(&mcp->mc_fpstate, addr, sizeof(mcp->mc_fpstate));
+		}
+		/*
+		 * XXX we violate the dubious requirement that npxsetregs()
+		 * be called with interrupts disabled.
+		 */
+		npxsetregs(td, addr);
+		/*
+		 * Don't bother putting things back where they were in the
+		 * misaligned case, since we know that the caller won't use
+		 * them again.
+		 */
+	} else
+		return (EINVAL);
+	return (0);
+}
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * at top to call routine, followed by kcall
+ * to sigreturn routine below.  After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+#ifdef COMPAT_FREEBSD4
+static void
+freebsd4_ia32_sendsig(catcher, sig, mask, code)
+	sig_t catcher;
+	int sig;
+	sigset_t *mask;
+	u_long code;
+{
+	struct ia32_sigframe4 sf, *sfp;
+	struct proc *p;
+	struct thread *td;
+	struct sigacts *psp;
+	struct trapframe *regs;
+	int oonstack;
+
+	td = curthread;
+	p = td->td_proc;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	psp = p->p_sigacts;
+	regs = td->td_frame;
+	oonstack = sigonstack(regs->tf_rsp);
+
+	/* Save user context. */
+	bzero(&sf, sizeof(sf));
+	sf.sf_uc.uc_sigmask = *mask;
+	sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp;
+	sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size;
+	sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
+	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+	sf.sf_uc.uc_mcontext.mc_gs = rgs();
+	sf.sf_uc.uc_mcontext.mc_fs = rfs();
+	__asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
+	__asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
+	sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
+	sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
+	sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
+	sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
+	sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
+	sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
+	sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
+	sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
+	sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
+	sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
+	sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
+	sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
+	sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
+	sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
+	sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+
+	/* Allocate space for the signal handler context. */
+	if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		sfp = (struct ia32_sigframe4 *)(p->p_sigstk.ss_sp +
+		    p->p_sigstk.ss_size - sizeof(sf));
+	} else
+		sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1;
+	PROC_UNLOCK(p);
+
+	/* Translate the signal if appropriate. */
+	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
+		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+	/* Build the argument list for the signal handler. */
+	sf.sf_signum = sig;
+	sf.sf_ucontext = (register_t)&sfp->sf_uc;
+	PROC_LOCK(p);
+	if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+		/* Signal handler installed with SA_SIGINFO. */
+		sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
+		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+
+		/* Fill in POSIX parts */
+		sf.sf_si.si_signo = sig;
+		sf.sf_si.si_code = code;
+		sf.sf_si.si_addr = regs->tf_addr;
+	} else {
+		/* Old FreeBSD-style arguments. */
+		sf.sf_siginfo = code;
+		sf.sf_addr = regs->tf_addr;
+		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+	}
+	PROC_UNLOCK(p);
+
+	/*
+	 * Copy the sigframe out to the user's stack.
+	 */
+	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
+#ifdef DEBUG
+		printf("process %ld has trashed its stack\n", (long)p->p_pid);
+#endif
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	regs->tf_rsp = (uintptr_t)sfp;
+	regs->tf_rip = PS_STRINGS - sz_freebsd4_ia32_sigcode;
+	regs->tf_rflags &= ~PSL_T;
+	regs->tf_cs = _ucode32sel;
+	regs->tf_ss = _udatasel;
+	load_ds(_udatasel);
+	load_es(_udatasel);
+	load_fs(_udatasel);
+	PROC_LOCK(p);
+}
+#endif	/* COMPAT_FREEBSD4 */
+
+static void
+ia32_sendsig(catcher, sig, mask, code)
+	sig_t catcher;
+	int sig;
+	sigset_t *mask;
+	u_long code;
+{
+	struct ia32_sigframe sf, *sfp;
+	struct proc *p;
+	struct thread *td;
+	struct sigacts *psp;
+	char *sp;
+	struct trapframe *regs;
+	int oonstack;
+
+	td = curthread;
+	p = td->td_proc;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	psp = p->p_sigacts;
+#ifdef COMPAT_FREEBSD4
+	if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
+		freebsd4_ia32_sendsig(catcher, sig, mask, code);
+		return;
+	}
+#endif
+	regs = td->td_frame;
+	oonstack = sigonstack(regs->tf_rsp);
+
+	/* Save user context. */
+	bzero(&sf, sizeof(sf));
+	sf.sf_uc.uc_sigmask = *mask;
+	sf.sf_uc.uc_stack.ss_sp = (uintptr_t)p->p_sigstk.ss_sp;
+	sf.sf_uc.uc_stack.ss_size = p->p_sigstk.ss_size;
+	sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
+	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+	sf.sf_uc.uc_mcontext.mc_gs = rgs();
+	sf.sf_uc.uc_mcontext.mc_fs = rfs();
+	__asm __volatile("movl %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
+	__asm __volatile("movl %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
+	sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
+	sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
+	sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
+	sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
+	sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
+	sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
+	sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
+	sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
+	sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
+	sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
+	sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
+	sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
+	sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
+	sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
+	sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
+	ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
+	fpstate_drop(td);
+
+	/* Allocate space for the signal handler context. */
+	if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		sp = p->p_sigstk.ss_sp +
+		    p->p_sigstk.ss_size - sizeof(sf);
+	} else
+		sp = (char *)regs->tf_rsp - sizeof(sf);
+	/* Align to 16 bytes. */
+	sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
+	PROC_UNLOCK(p);
+
+	/* Translate the signal if appropriate. */
+	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
+		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+	/* Build the argument list for the signal handler. */
+	sf.sf_signum = sig;
+	sf.sf_ucontext = (register_t)&sfp->sf_uc;
+	PROC_LOCK(p);
+	if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) {
+		/* Signal handler installed with SA_SIGINFO. */
+		sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
+		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+
+		/* Fill in POSIX parts */
+		sf.sf_si.si_signo = sig;
+		sf.sf_si.si_code = code;
+		sf.sf_si.si_addr = regs->tf_addr;
+	} else {
+		/* Old FreeBSD-style arguments. */
+		sf.sf_siginfo = code;
+		sf.sf_addr = regs->tf_err;
+		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
+	}
+	PROC_UNLOCK(p);
+
+	/*
+	 * Copy the sigframe out to the user's stack.
+	 */
+	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
+#ifdef DEBUG
+		printf("process %ld has trashed its stack\n", (long)p->p_pid);
+#endif
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	regs->tf_rsp = (uintptr_t)sfp;
+	regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+	regs->tf_rflags &= ~PSL_T;
+	regs->tf_cs = _ucode32sel;
+	regs->tf_ss = _udatasel;
+	load_ds(_udatasel);
+	load_es(_udatasel);
+	load_fs(_udatasel);
+	PROC_LOCK(p);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken.  Reset signal mask and
+ * stack state from context left by sendsig (above).
+ * Return to previous pc and psl as specified by
+ * context left by sendsig. Check carefully to
+ * make sure that the user has not modified the
+ * state to gain improper privileges.
+ */
+#ifdef COMPAT_FREEBSD4
+/*
+ * MPSAFE
+ */
+int
+freebsd4_ia32_sigreturn(td, uap)
+	struct thread *td;
+	struct freebsd4_ia32_sigreturn_args /* {
+		const struct freebsd4_ucontext *sigcntxp;
+	} */ *uap;
+{
+	struct ia32_ucontext4 uc;
+	struct proc *p = td->td_proc;
+	struct trapframe *regs;
+	const struct ia32_ucontext4 *ucp;
+	int cs, eflags, error;
+
+	error = copyin(uap->sigcntxp, &uc, sizeof(uc));
+	if (error != 0)
+		return (error);
+	ucp = &uc;
+	regs = td->td_frame;
+	eflags = ucp->uc_mcontext.mc_eflags;
+	/*
+	 * Don't allow users to change privileged or reserved flags.
+	 */
+	/*
+	 * XXX do allow users to change the privileged flag PSL_RF.
+	 * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
+	 * should sometimes set it there too.  tf_eflags is kept in
+	 * the signal context during signal handling and there is no
+	 * other place to remember it, so the PSL_RF bit may be
+	 * corrupted by the signal handler without us knowing.
+	 * Corruption of the PSL_RF bit at worst causes one more or
+	 * one less debugger trap, so allowing it is fairly harmless.
+	 */
+	if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
+		printf("freebsd4_ia32_sigreturn: eflags = 0x%x\n", eflags);
+		return (EINVAL);
+	}
+
+	/*
+	 * Don't allow users to load a valid privileged %cs.  Let the
+	 * hardware check for invalid selectors, excess privilege in
+	 * other selectors, invalid %eip's and invalid %esp's.
+	 */
+	cs = ucp->uc_mcontext.mc_cs;
+	if (!CS_SECURE(cs)) {
+		printf("freebsd4_sigreturn: cs = 0x%x\n", cs);
+		trapsignal(td, SIGBUS, T_PROTFLT);
+		return (EINVAL);
+	}
+
+	/* mc_gs is done by sigtramp.S */
+	load_fs(ucp->uc_mcontext.mc_fs);
+	load_es(ucp->uc_mcontext.mc_es);
+	load_ds(ucp->uc_mcontext.mc_ds);
+	regs->tf_rdi = ucp->uc_mcontext.mc_edi;
+	regs->tf_rsi = ucp->uc_mcontext.mc_esi;
+	regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
+	regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
+	regs->tf_rdx = ucp->uc_mcontext.mc_edx;
+	regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
+	regs->tf_rax = ucp->uc_mcontext.mc_eax;
+	regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
+	regs->tf_err = ucp->uc_mcontext.mc_err;
+	regs->tf_rip = ucp->uc_mcontext.mc_eip;
+	regs->tf_cs = cs;
+	regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
+	regs->tf_rsp = ucp->uc_mcontext.mc_esp;
+	regs->tf_ss = ucp->uc_mcontext.mc_ss;
+
+	PROC_LOCK(p);
+	td->td_sigmask = ucp->uc_sigmask;
+	SIG_CANTMASK(td->td_sigmask);
+	signotify(td);
+	PROC_UNLOCK(p);
+	return (EJUSTRETURN);
+}
+#endif	/* COMPAT_FREEBSD4 */
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sigreturn(td, uap)
+	struct thread *td;
+	struct ia32_sigreturn_args /* {
+		const struct ia32_ucontext *sigcntxp;
+	} */ *uap;
+{
+	struct ia32_ucontext uc;
+	struct proc *p = td->td_proc;
+	struct trapframe *regs;
+	const struct ia32_ucontext *ucp;
+	int cs, eflags, error, ret;
+
+	error = copyin(uap->sigcntxp, &uc, sizeof(uc));
+	if (error != 0)
+		return (error);
+	ucp = &uc;
+	regs = td->td_frame;
+	eflags = ucp->uc_mcontext.mc_eflags;
+	/*
+	 * Don't allow users to change privileged or reserved flags.
+	 */
+	/*
+	 * XXX do allow users to change the privileged flag PSL_RF.
+	 * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
+	 * should sometimes set it there too.  tf_eflags is kept in
+	 * the signal context during signal handling and there is no
+	 * other place to remember it, so the PSL_RF bit may be
+	 * corrupted by the signal handler without us knowing.
+	 * Corruption of the PSL_RF bit at worst causes one more or
+	 * one less debugger trap, so allowing it is fairly harmless.
+	 */
+	if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
+		printf("ia32_sigreturn: eflags = 0x%x\n", eflags);
+		return (EINVAL);
+	}
+
+	/*
+	 * Don't allow users to load a valid privileged %cs.  Let the
+	 * hardware check for invalid selectors, excess privilege in
+	 * other selectors, invalid %eip's and invalid %esp's.
+	 */
+	cs = ucp->uc_mcontext.mc_cs;
+	if (!CS_SECURE(cs)) {
+		printf("sigreturn: cs = 0x%x\n", cs);
+		trapsignal(td, SIGBUS, T_PROTFLT);
+		return (EINVAL);
+	}
+
+	ret = ia32_set_fpcontext(td, &ucp->uc_mcontext);
+	if (ret != 0)
+		return (ret);
+
+	/* mc_gs is done by sigtramp.S */
+	load_fs(ucp->uc_mcontext.mc_fs);
+	load_es(ucp->uc_mcontext.mc_es);
+	load_ds(ucp->uc_mcontext.mc_ds);
+	regs->tf_rdi = ucp->uc_mcontext.mc_edi;
+	regs->tf_rsi = ucp->uc_mcontext.mc_esi;
+	regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
+	regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
+	regs->tf_rdx = ucp->uc_mcontext.mc_edx;
+	regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
+	regs->tf_rax = ucp->uc_mcontext.mc_eax;
+	regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
+	regs->tf_err = ucp->uc_mcontext.mc_err;
+	regs->tf_rip = ucp->uc_mcontext.mc_eip;
+	regs->tf_cs = cs;
+	regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
+	regs->tf_rsp = ucp->uc_mcontext.mc_esp;
+	regs->tf_ss = ucp->uc_mcontext.mc_ss;
+
+	PROC_LOCK(p);
+	td->td_sigmask = ucp->uc_sigmask;
+	SIG_CANTMASK(td->td_sigmask);
+	signotify(td);
+	PROC_UNLOCK(p);
+	return (EJUSTRETURN);
+}

==== //depot/projects/hammer/sys/amd64/ia32/syscalls.master#2 (text+ko) ====

@@ -484,11 +484,11 @@
 340	MNOPROTO POSIX	{ int sigprocmask(int how, const sigset_t *set, \
 			    sigset_t *oset); }
 341	MNOPROTO POSIX	{ int sigsuspend(const sigset_t *sigmask); }
-342	STD POSIX	{ int ia32_sigaction(int sig, \
+342	COMPAT4 POSIX	{ int ia32_sigaction(int sig, \
 			    struct sigaction32 *act, \
 			    struct sigaction32 *oact); }
 343	MNOPROTO POSIX	{ int sigpending(sigset_t *set); }
-344	MNOPROTO BSD	{ int sigreturn(const struct __ucontext *sigcntxp); }
+344	MCOMPAT4 BSD	{ int ia32_sigreturn(const struct __ucontext *sigcntxp); }
 345	UNIMPL	NOHIDE	sigtimedwait
 346	UNIMPL	NOHIDE	sigwaitinfo
 347	MNOPROTO BSD	{ int __acl_get_file(const char *path, \
@@ -586,8 +586,10 @@
 413	UNIMPL	BSD	extattr_get_link
 414	UNIMPL	BSD	extattr_delete_link
 415	UNIMPL	BSD	__mac_execve
-416	UNIMPL	BSD	newsigreturn
-417	UNIMPL	BSD	newsigaction
+416	MSTD BSD	{ int ia32_sigreturn(const struct ia32_ucontext *sigcntxp); }
+417	STD POSIX	{ int ia32_sigaction(int sig, \
+			    struct sigaction32 *act, \
+			    struct sigaction32 *oact); }
 418	UNIMPL	BSD	__xstat
 419	UNIMPL	BSD	__xfstat
 420	UNIMPL	BSD	__xlstat

==== //depot/projects/hammer/sys/amd64/include/md_var.h#10 (text+ko) ====

@@ -69,5 +69,6 @@
 int	is_physical_memory(vm_offset_t addr);
 void	setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
 void	swi_vm(void *);
+void	fpstate_drop(struct thread *td);
 
 #endif /* !_MACHINE_MD_VAR_H_ */

==== //depot/projects/hammer/sys/conf/files.amd64#10 (text+ko) ====

@@ -8,6 +8,19 @@
 # dependency lines other than the first are silently ignored.
 #
 
+ia32_genassym.o			optional	ia32			\
+	dependency 	"$S/amd64/ia32/ia32_genassym.c"			\
+	compile-with	"${CC} ${CFLAGS:N-fno-common} -c ${.IMPSRC}"	\
+	no-obj no-implicit-rule						\
+	clean		"ia32_genassym.o"
+#
+ia32_assym.h			optional	ia32			\
+	dependency 	"$S/kern/genassym.sh ia32_genassym.o"		\
+	compile-with	"sh $S/kern/genassym.sh ia32_genassym.o > ${.TARGET}" \
+	no-obj no-implicit-rule before-depend				\
+	clean		"ia32_assym.h"
+#
+
 dev/kbd/atkbd.c			optional	atkbd
 dev/kbd/atkbdc.c		optional	atkbdc
 dev/kbd/kbd.c			optional	atkbd
@@ -67,6 +80,7 @@
 amd64/ia32/ia32_misc.c		optional	ia32
 amd64/ia32/ia32_sysent.c	optional	ia32
 amd64/ia32/ia32_sysvec.c	optional	ia32
+amd64/ia32/ia32_sigtramp.S	optional	ia32
 kern/imgact_elf32.c		optional	ia32
 
 # This file tells config what files go into building a kernel,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200305140124.h4E1OBri066466>