PERFORCE change 31109 for review
Peter Wemm
peter at FreeBSD.org
Tue May 13 18:24:14 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=31109
Change 31109 by peter at 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,
More information about the p4-projects
mailing list