diff options
-rw-r--r-- | sys/alpha/alpha/machdep.c | 143 | ||||
-rw-r--r-- | sys/alpha/include/cpu.h | 8 | ||||
-rw-r--r-- | sys/alpha/include/fpu.h | 4 | ||||
-rw-r--r-- | sys/alpha/include/signal.h | 7 | ||||
-rw-r--r-- | sys/alpha/include/ucontext.h | 9 | ||||
-rw-r--r-- | sys/amd64/amd64/fpu.c | 4 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 3 | ||||
-rw-r--r-- | sys/amd64/include/signal.h | 4 | ||||
-rw-r--r-- | sys/amd64/include/ucontext.h | 13 | ||||
-rw-r--r-- | sys/amd64/isa/npx.c | 4 | ||||
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 3 | ||||
-rw-r--r-- | sys/i386/include/signal.h | 4 | ||||
-rw-r--r-- | sys/i386/include/ucontext.h | 13 | ||||
-rw-r--r-- | sys/i386/isa/npx.c | 4 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 14 | ||||
-rw-r--r-- | sys/kern/kern_context.c | 134 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 4 | ||||
-rw-r--r-- | sys/powerpc/aim/machdep.c | 14 | ||||
-rw-r--r-- | sys/powerpc/powerpc/machdep.c | 14 | ||||
-rw-r--r-- | sys/sparc64/sparc64/machdep.c | 14 | ||||
-rw-r--r-- | sys/sys/ucontext.h | 8 |
22 files changed, 371 insertions, 55 deletions
diff --git a/sys/alpha/alpha/machdep.c b/sys/alpha/alpha/machdep.c index 7a4a001..ddf67d7 100644 --- a/sys/alpha/alpha/machdep.c +++ b/sys/alpha/alpha/machdep.c @@ -210,7 +210,9 @@ static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); #endif +static void get_fpcontext(struct thread *td, mcontext_t *mcp); static void identifycpu(void); +static int set_fpcontext(struct thread *td, const mcontext_t *mcp); struct kva_md_info kmi; @@ -1405,7 +1407,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) frame->tf_regs[FRAME_TRAPARG_A1]; sf.sf_uc.uc_mcontext.mc_regs[R_TRAPARG_A2] = frame->tf_regs[FRAME_TRAPARG_A2]; - sf.sf_uc.uc_mcontext.mc_format = __UC_REV0_SIGFRAME; + sf.sf_uc.uc_mcontext.mc_format = _MC_REV0_SIGFRAME; /* * Allocate and validate space for the signal handler @@ -1664,13 +1666,15 @@ sigreturn(struct thread *td, return (error); } #ifdef COMPAT_43 - if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) - return osigreturn(td, (struct osigreturn_args *)uap); + if (((struct osigcontext*)&uc)->sc_regs[R_ZERO] == 0xACEDBADE) + return osigreturn(td, (struct osigreturn_args *)uap); #endif /* * Restore the user-supplied information */ + if ((error = set_fpcontext(td, &uc.uc_mcontext)) != 0) + return (error); set_regs(td, (struct reg *)uc.uc_mcontext.mc_regs); val = (uc.uc_mcontext.mc_regs[R_PS] | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR; @@ -1692,12 +1696,6 @@ sigreturn(struct thread *td, signotify(p); PROC_UNLOCK(p); - /* XXX ksc.sc_ownedfp ? */ - alpha_fpstate_drop(td); - bcopy((struct fpreg *)uc.uc_mcontext.mc_fpregs, - &td->td_pcb->pcb_fp, sizeof(struct fpreg)); - td->td_pcb->pcb_fp_control = uc.uc_mcontext.mc_fp_control; - return (EJUSTRETURN); } @@ -2011,6 +2009,133 @@ set_regs(td, regs) } int +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + /* + * Use a trapframe for getsetcontext, so just copy the + * threads trapframe. + */ + bcopy(&td->td_frame, &mcp->mc_regs, sizeof(td->td_frame)); + + /* + * When the thread is the current thread, the user stack pointer + * is not in the PCB; it must be read from the PAL. + */ + if (td == curthread) + mcp->mc_regs[FRAME_SP] = alpha_pal_rdusp(); + + mcp->mc_format = _MC_REV0_TRAPFRAME; + mcp->mc_onstack = sigonstack(alpha_pal_rdusp()) ? 1 : 0; + get_fpcontext(td, mcp); + return (0); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + int ret; + unsigned long val; + + if ((mcp->mc_format != _MC_REV0_TRAPFRAME) && + (mcp->mc_format != _MC_REV0_SIGFRAME)) + return (EINVAL); + else if ((ret = set_fpcontext(td, mcp)) != 0) + return (ret); + + if (mcp->mc_format == _MC_REV0_SIGFRAME) { + set_regs(td, (struct reg *)&mcp->mc_regs); + val = (mcp->mc_regs[R_PS] | ALPHA_PSL_USERSET) & + ~ALPHA_PSL_USERCLR; + td->td_frame->tf_regs[FRAME_PS] = val; + td->td_frame->tf_regs[FRAME_PC] = mcp->mc_regs[R_PC]; + td->td_frame->tf_regs[FRAME_FLAGS] = 0; + if (td == curthread) + alpha_pal_wrusp(mcp->mc_regs[R_SP]); + + } else { + if (td == curthread) + alpha_pal_wrusp(mcp->mc_regs[FRAME_SP]); + /* + * The context is a trapframe, so just copy it over the + * threads frame. + */ + bcopy(&mcp->mc_regs, &td->td_frame, sizeof(td->td_frame)); + } + return (0); +} + +static void +get_fpcontext(struct thread *td, mcontext_t *mcp) +{ + register_t s; + + s = intr_disable(); + if ((td->td_md.md_flags & MDTD_FPUSED) == 0) { + intr_restore(s); + mcp->mc_ownedfp = _MC_FPOWNED_NONE; + } else if (PCPU_GET(fpcurthread) == td) { + /* See comments in alpha_fpstate_save() regarding FEN. */ + if (td != curthread) + alpha_pal_wrfen(1); + /* + * The last field (fpr_cr) of struct fpreg isn't + * included in mc_fpregs, but it immediately follows + * it in mcontext_t. + */ + savefpstate((struct fpreg *)&mcp->mc_fpregs); + if (td != curthread) + alpha_pal_wrfen(0); + intr_restore(s); + mcp->mc_ownedfp = _MC_FPOWNED_FPU; + } else { + /* + * The thread doesn't own the FPU so get the state from + * the PCB. + */ + intr_restore(s); + bcopy(&td->td_pcb->pcb_fp, &mcp->mc_fpregs, + sizeof(td->td_pcb->pcb_fp)); + mcp->mc_ownedfp = _MC_FPOWNED_PCB; + } + /* There's no harm in always doing the following. */ + mcp->mc_fp_control = td->td_pcb->pcb_fp_control; +} + +static int +set_fpcontext(struct thread *td, const mcontext_t *mcp) +{ + register_t s; + + if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) { + /* XXX - Drop fpu state so we get a clean state? */ + alpha_fpstate_drop(td); + } + else if ((mcp->mc_ownedfp != _MC_FPOWNED_FPU) && + (mcp->mc_ownedfp != _MC_FPOWNED_PCB)) + return (EINVAL); + else { + s = intr_disable(); + if (PCPU_GET(fpcurthread) == td) { + /* + * The last field (fpr_cr) of struct fpreg isn't + * included in mc_fpregs, but it immediately follows + * it in mcontext_t. + */ + restorefpstate((struct fpreg *)&mcp->mc_fpregs); + intr_restore(s); + } + else { + /* Just save the state in the PCB. */ + intr_restore(s); + bcopy(&mcp->mc_fpregs, &td->td_pcb->pcb_fp, + sizeof (td->td_pcb->pcb_fp)); + } + td->td_pcb->pcb_fp_control = mcp->mc_fp_control; + } + return (0); +} + +int fill_dbregs(struct thread *td, struct dbreg *dbregs) { diff --git a/sys/alpha/include/cpu.h b/sys/alpha/include/cpu.h index 9d05765..0e39182 100644 --- a/sys/alpha/include/cpu.h +++ b/sys/alpha/include/cpu.h @@ -115,11 +115,11 @@ void XentRestart(void); /* MAGIC */ void XentSys(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */ void XentUna(u_int64_t, u_int64_t, u_int64_t); /* MAGIC */ void alpha_init(u_long, u_long, u_long, u_long, u_long); +void alpha_fpstate_check(struct thread *td); +void alpha_fpstate_drop(struct thread *td); +void alpha_fpstate_save(struct thread *td, int write); +void alpha_fpstate_switch(struct thread *td); int alpha_pa_access(u_long); -void alpha_fpstate_check(struct thread *p); -void alpha_fpstate_save(struct thread *p, int write); -void alpha_fpstate_drop(struct thread *p); -void alpha_fpstate_switch(struct thread *p); int badaddr (void *, size_t); int badaddr_read(void *, size_t, void *); u_int64_t console_restart(u_int64_t, u_int64_t, u_int64_t); diff --git a/sys/alpha/include/fpu.h b/sys/alpha/include/fpu.h index 712a1f9..9f4800f 100644 --- a/sys/alpha/include/fpu.h +++ b/sys/alpha/include/fpu.h @@ -116,9 +116,7 @@ __asm__("trapb") #ifdef _KERNEL - -extern int fp_software_completion(u_int64_t regmask, struct thread *p); - +extern int fp_software_completion(u_int64_t regmask, struct thread *td); #endif #endif /* ! _MACHINE_FPU_H_ */ diff --git a/sys/alpha/include/signal.h b/sys/alpha/include/signal.h index 2a1f17b..37a969e 100644 --- a/sys/alpha/include/signal.h +++ b/sys/alpha/include/signal.h @@ -94,10 +94,9 @@ struct sigcontext { unsigned long sc_fpregs[32]; /* FP register set (see above) */ unsigned long sc_fpcr; /* FP control register (see above) */ unsigned long sc_fp_control; /* FP software control word */ - long sc_ownedfp; /* fp has been used */ - long sc_xxx1[2]; /* sc_ssize, sc_sbase on DUX */ - long sc_xxx2[3]; /* sc_fp_trap_pc, sc_fp_trigger_sum, sc_fp_trigger_inst */ - long sc_reserved[2]; /* XXX */ + long sc_ownedfp; /* fp has been used; see mcontext_t */ + long sc_format; /* see mcontext_t */ + long sc_spare[6]; /* XXX */ }; #define sc_sp sc_regs[R_SP] diff --git a/sys/alpha/include/ucontext.h b/sys/alpha/include/ucontext.h index bfc18df..2c3ed70 100644 --- a/sys/alpha/include/ucontext.h +++ b/sys/alpha/include/ucontext.h @@ -43,11 +43,14 @@ typedef struct __mcontext { unsigned long mc_fpregs[32]; unsigned long mc_fpcr; unsigned long mc_fp_control; +#define _MC_FPOWNED_NONE 0 /* FP state not used */ +#define _MC_FPOWNED_FPU 1 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 2 /* FP state came from PCB */ long mc_ownedfp; -#define __UC_REV0_SIGFRAME 1 /* context is a signal frame */ -#define __UC_REV0_TRAPFRAME 2 /* context is a trap frame */ +#define _MC_REV0_SIGFRAME 1 /* context is a signal frame */ +#define _MC_REV0_TRAPFRAME 2 /* context is a trap frame */ long mc_format; - long __spare__[6]; + long mc_spare[6]; } mcontext_t; #if defined(_KERNEL) && defined(COMPAT_FREEBSD4) diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 3395c99..661a698 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -161,14 +161,14 @@ void stop_emulating(void); typedef u_char bool_t; +static void fpusave(union savefpu *); +static void fpurstor(union savefpu *); static int npx_attach(device_t dev); static void npx_identify(driver_t *driver, device_t parent); #ifndef SMP static void npx_intr(void *); #endif static int npx_probe(device_t dev); -static void fpusave(union savefpu *); -static void fpurstor(union savefpu *); #ifdef I586_CPU_XXX static long timezero(const char *funcname, void (*func)(void *buf, size_t len)); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 181463e..1aedc3d 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -2317,7 +2317,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs) /* * Get machine context. */ -void +int get_mcontext(struct thread *td, mcontext_t *mcp) { struct trapframe *tp; @@ -2344,6 +2344,7 @@ get_mcontext(struct thread *td, mcontext_t *mcp) mcp->mc_ss = tp->tf_ss; mcp->mc_len = sizeof(*mcp); get_fpcontext(td, mcp); + return (0); } /* diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h index 29a9776..efc7ef0 100644 --- a/sys/amd64/include/signal.h +++ b/sys/amd64/include/signal.h @@ -119,7 +119,7 @@ struct sigcontext { int sc_efl; int sc_esp; int sc_ss; - int sc_len; /* sizeof(struct mcontext_t) */ + int sc_len; /* sizeof(mcontext_t) */ /* * XXX - See <machine/ucontext.h> and <machine/npx.h> for * the following fields. @@ -127,7 +127,7 @@ struct sigcontext { int sc_fpformat; int sc_ownedfp; int sc_spare1[1]; - int sc_fpregs[128]; + int sc_fpstate[128]; int sc_spare2[8]; }; diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h index af9b4fd..ea6f0b6 100644 --- a/sys/amd64/include/ucontext.h +++ b/sys/amd64/include/ucontext.h @@ -38,7 +38,7 @@ typedef struct __mcontext { * and ucontext_t at the same time. */ int mc_onstack; /* XXX - sigcontext compat. */ - int mc_gs; + int mc_gs; /* machine state (trapframe) */ int mc_fs; int mc_es; int mc_ds; @@ -55,7 +55,7 @@ typedef struct __mcontext { int mc_eip; int mc_cs; int mc_eflags; - int mc_esp; /* machine state */ + int mc_esp; int mc_ss; int mc_len; /* sizeof(mcontext_t) */ @@ -72,8 +72,7 @@ typedef struct __mcontext { int mc_spare2[8]; } mcontext_t; -#ifdef _KERNEL -#ifdef COMPAT_FREEBSD4 +#if defined(_KERNEL) && defined(COMPAT_FREEBSD4) /* For 4.x binaries */ struct mcontext4 { int mc_onstack; /* XXX - sigcontext compat. */ @@ -101,10 +100,4 @@ struct mcontext4 { }; #endif -struct thread; - -void get_mcontext(struct thread *td, mcontext_t *mcp); -int set_mcontext(struct thread *td, const mcontext_t *mcp); -#endif - #endif /* !_MACHINE_UCONTEXT_H_ */ diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c index 3395c99..661a698 100644 --- a/sys/amd64/isa/npx.c +++ b/sys/amd64/isa/npx.c @@ -161,14 +161,14 @@ void stop_emulating(void); typedef u_char bool_t; +static void fpusave(union savefpu *); +static void fpurstor(union savefpu *); static int npx_attach(device_t dev); static void npx_identify(driver_t *driver, device_t parent); #ifndef SMP static void npx_intr(void *); #endif static int npx_probe(device_t dev); -static void fpusave(union savefpu *); -static void fpurstor(union savefpu *); #ifdef I586_CPU_XXX static long timezero(const char *funcname, void (*func)(void *buf, size_t len)); diff --git a/sys/conf/files b/sys/conf/files index 300fe54..c562b1b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -975,6 +975,7 @@ kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard +kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_poll.c optional device_polling kern/kern_environment.c standard diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 181463e..1aedc3d 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2317,7 +2317,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs) /* * Get machine context. */ -void +int get_mcontext(struct thread *td, mcontext_t *mcp) { struct trapframe *tp; @@ -2344,6 +2344,7 @@ get_mcontext(struct thread *td, mcontext_t *mcp) mcp->mc_ss = tp->tf_ss; mcp->mc_len = sizeof(*mcp); get_fpcontext(td, mcp); + return (0); } /* diff --git a/sys/i386/include/signal.h b/sys/i386/include/signal.h index 29a9776..efc7ef0 100644 --- a/sys/i386/include/signal.h +++ b/sys/i386/include/signal.h @@ -119,7 +119,7 @@ struct sigcontext { int sc_efl; int sc_esp; int sc_ss; - int sc_len; /* sizeof(struct mcontext_t) */ + int sc_len; /* sizeof(mcontext_t) */ /* * XXX - See <machine/ucontext.h> and <machine/npx.h> for * the following fields. @@ -127,7 +127,7 @@ struct sigcontext { int sc_fpformat; int sc_ownedfp; int sc_spare1[1]; - int sc_fpregs[128]; + int sc_fpstate[128]; int sc_spare2[8]; }; diff --git a/sys/i386/include/ucontext.h b/sys/i386/include/ucontext.h index af9b4fd..ea6f0b6 100644 --- a/sys/i386/include/ucontext.h +++ b/sys/i386/include/ucontext.h @@ -38,7 +38,7 @@ typedef struct __mcontext { * and ucontext_t at the same time. */ int mc_onstack; /* XXX - sigcontext compat. */ - int mc_gs; + int mc_gs; /* machine state (trapframe) */ int mc_fs; int mc_es; int mc_ds; @@ -55,7 +55,7 @@ typedef struct __mcontext { int mc_eip; int mc_cs; int mc_eflags; - int mc_esp; /* machine state */ + int mc_esp; int mc_ss; int mc_len; /* sizeof(mcontext_t) */ @@ -72,8 +72,7 @@ typedef struct __mcontext { int mc_spare2[8]; } mcontext_t; -#ifdef _KERNEL -#ifdef COMPAT_FREEBSD4 +#if defined(_KERNEL) && defined(COMPAT_FREEBSD4) /* For 4.x binaries */ struct mcontext4 { int mc_onstack; /* XXX - sigcontext compat. */ @@ -101,10 +100,4 @@ struct mcontext4 { }; #endif -struct thread; - -void get_mcontext(struct thread *td, mcontext_t *mcp); -int set_mcontext(struct thread *td, const mcontext_t *mcp); -#endif - #endif /* !_MACHINE_UCONTEXT_H_ */ diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 3395c99..661a698 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -161,14 +161,14 @@ void stop_emulating(void); typedef u_char bool_t; +static void fpusave(union savefpu *); +static void fpurstor(union savefpu *); static int npx_attach(device_t dev); static void npx_identify(driver_t *driver, device_t parent); #ifndef SMP static void npx_intr(void *); #endif static int npx_probe(device_t dev); -static void fpusave(union savefpu *); -static void fpurstor(union savefpu *); #ifdef I586_CPU_XXX static long timezero(const char *funcname, void (*func)(void *buf, size_t len)); diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index df7dc4a..3bb9e34 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1038,6 +1038,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +int +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + + return (ENOSYS); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + + return (ENOSYS); +} + /* * Machine dependent boot() routine */ diff --git a/sys/kern/kern_context.c b/sys/kern/kern_context.c new file mode 100644 index 0000000..1cc0eac --- /dev/null +++ b/sys/kern/kern_context.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org> + * 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. + * 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$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sysent.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/signalvar.h> +#include <sys/ucontext.h> + +/* + * The first two fields of a ucontext_t are the signal mask and + * the machine context. The next field is uc_link; we want to + * avoid destroying the link when copying out contexts. + */ +#define UC_COPY_SIZE (sizeof(sigset_t) + sizeof(mcontext_t)) + + +#ifndef _SYS_SYSPROTO_H_ +struct getcontext_args { + struct __ucontext *ucp; +} +struct setcontext_args { + const struct __ucontext_t *ucp; +} +struct swapcontext_args { + struct __ucontext *oucp; + const struct __ucontext_t *ucp; +} +#endif + +/* + * MPSAFE + */ +int +getcontext(struct thread *td, struct getcontext_args *uap) +{ + ucontext_t uc; + int ret; + + if (uap->ucp == NULL) + ret = EINVAL; + else { + get_mcontext(td, &uc.uc_mcontext); + uc.uc_sigmask = td->td_proc->p_sigmask; + ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); + } + return (ret); +} + +/* + * MPSAFE + */ +int +setcontext(struct thread *td, struct setcontext_args *uap) +{ + ucontext_t uc; + int ret; + + if (uap->ucp == NULL) + ret = EINVAL; + else { + ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); + if (ret == 0) { + ret = set_mcontext(td, &uc.uc_mcontext); + if (ret == 0) { + SIG_CANTMASK(uc.uc_sigmask); + PROC_LOCK(td->td_proc); + td->td_proc->p_sigmask = uc.uc_sigmask; + PROC_UNLOCK(td->td_proc); + } + } + } + return (ret); +} + +int +swapcontext(struct thread *td, struct swapcontext_args *uap) +{ + ucontext_t uc; + int ret; + + if (uap->oucp == NULL || uap->ucp == NULL) + ret = EINVAL; + else { + get_mcontext(td, &uc.uc_mcontext); + uc.uc_sigmask = td->td_proc->p_sigmask; + ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); + if (ret == 0) { + ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); + if (ret == 0) { + ret = set_mcontext(td, &uc.uc_mcontext); + if (ret == 0) { + SIG_CANTMASK(uc.uc_sigmask); + PROC_LOCK(td->td_proc); + td->td_proc->p_sigmask = uc.uc_sigmask; + PROC_UNLOCK(td->td_proc); + } + } + } + } + return (ret); +} diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 650c65b..a41eb12 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -608,6 +608,10 @@ 418 UNIMPL BSD __xstat 419 UNIMPL BSD __xfstat 420 UNIMPL BSD __xlstat +421 MSTD BSD { int getcontext(struct __ucontext *ucp); } +422 MSTD BSD { int setcontext(const struct __ucontext *ucp); } +423 MSTD BSD { int swapcontext(struct __ucontext *oucp, \ + const struct __ucontext *ucp); } ; Please copy any additions and changes to the following compatability tables: ; sys/ia64/ia32/syscalls.master (take a best guess) diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index a14d966..ffb5070 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -638,6 +638,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +int +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + + return (ENOSYS); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + + return (ENOSYS); +} + void cpu_boot(int howto) { diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c index a14d966..ffb5070 100644 --- a/sys/powerpc/powerpc/machdep.c +++ b/sys/powerpc/powerpc/machdep.c @@ -638,6 +638,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +int +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + + return (ENOSYS); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + + return (ENOSYS); +} + void cpu_boot(int howto) { diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index 116741b..84cf92a 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -504,6 +504,20 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) } #endif +int +get_mcontext(struct thread *td, mcontext_t *mcp) +{ + + return (ENOSYS); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + + return (ENOSYS); +} + /* * Exit the kernel and execute a firmware call that will not return, as * specified by the arguments. diff --git a/sys/sys/ucontext.h b/sys/sys/ucontext.h index dcce16e..1ea01d5 100644 --- a/sys/sys/ucontext.h +++ b/sys/sys/ucontext.h @@ -79,6 +79,14 @@ int swapcontext(ucontext_t *, const ucontext_t *); __END_DECLS +#else /* _KERNEL */ + +struct thread; + +/* Machine-dependent functions: */ +int get_mcontext(struct thread *td, mcontext_t *mcp); +int set_mcontext(struct thread *td, const mcontext_t *mcp); + #endif /* !_KERNEL */ #endif /* !_SYS_UCONTEXT_H_ */ |