diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-03-20 21:44:09 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-03-20 21:44:09 +0000 |
commit | 2adbed0e667a38266c5f7af35a555358a3a18065 (patch) | |
tree | 0cacbe115f2ec8d48c44183272e96f6a904dabff /sys | |
parent | 66da337841752aaa4e76f748b61818f649a94e5f (diff) |
When reading MXCSR from userland sigcontext or a ptrace request,
mask out invalid bits to prevent a protect fault.
Original diff by joshe@; further feedback and ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/fpu.c | 17 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/process_machdep.c | 5 | ||||
-rw-r--r-- | sys/arch/amd64/include/fpu.h | 4 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 9 | ||||
-rw-r--r-- | sys/arch/i386/i386/process_machdep.c | 4 | ||||
-rw-r--r-- | sys/arch/i386/include/npx.h | 9 | ||||
-rw-r--r-- | sys/arch/i386/isa/npx.c | 17 |
8 files changed, 59 insertions, 15 deletions
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c index 45d98c1cceb..047468a8fd8 100644 --- a/sys/arch/amd64/amd64/fpu.c +++ b/sys/arch/amd64/amd64/fpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.c,v 1.21 2010/09/29 15:11:31 joshe Exp $ */ +/* $OpenBSD: fpu.c,v 1.22 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */ /*- @@ -96,6 +96,11 @@ void fpudna(struct cpu_info *); static int x86fpflags_to_siginfo(u_int32_t); /* + * The mxcsr_mask for this host, taken from fxsave() on the primary CPU + */ +uint32_t fpu_mxcsr_mask; + +/* * Init the FPU. */ void @@ -103,6 +108,16 @@ fpuinit(struct cpu_info *ci) { lcr0(rcr0() & ~(CR0_EM|CR0_TS)); fninit(); + if (fpu_mxcsr_mask == 0) { + struct fxsave64 fx __attribute__((aligned(16))); + + bzero(&fx, sizeof(fx)); + fxsave(&fx); + if (fx.fx_mxcsr_mask) + fpu_mxcsr_mask = fx.fx_mxcsr_mask; + else + fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__; + } lcr0(rcr0() | (CR0_TS)); } diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index bff89202e01..2a961d94d3e 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.131 2011/03/18 03:10:47 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.132 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -655,9 +655,11 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) fpusave_proc(p, 0); if (ksc.sc_fpstate) { - if ((error = copyin(ksc.sc_fpstate, - &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, sizeof (struct fxsave64)))) + struct fxsave64 *fx = &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave; + + if ((error = copyin(ksc.sc_fpstate, fx, sizeof(*fx)))) return (error); + fx->fx_mxcsr &= fpu_mxcsr_mask; p->p_md.md_flags |= MDP_USEDFPU; } @@ -1504,6 +1506,7 @@ init_x86_64(paddr_t first_avail) cpu_init_idt(); intr_default_setup(); + fpuinit(&cpu_info_primary); softintr_init(); splraise(IPL_IPI); diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c index 98febadb35e..5ea4192a7e1 100644 --- a/sys/arch/amd64/amd64/process_machdep.c +++ b/sys/arch/amd64/amd64/process_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: process_machdep.c,v 1.9 2010/09/29 15:11:31 joshe Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.10 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */ /*- @@ -137,7 +137,7 @@ process_read_fpregs(struct proc *p, struct fpreg *regs) frame->fx_fsw = 0x0000; frame->fx_ftw = 0xff; frame->fx_mxcsr = __INITIAL_MXCSR__; - frame->fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; + frame->fx_mxcsr_mask = fpu_mxcsr_mask; p->p_md.md_flags |= MDP_USEDFPU; } @@ -198,6 +198,7 @@ process_write_fpregs(struct proc *p, struct fpreg *regs) } memcpy(frame, ®s->fxstate, sizeof(*regs)); + frame->fx_mxcsr &= fpu_mxcsr_mask; return (0); } diff --git a/sys/arch/amd64/include/fpu.h b/sys/arch/amd64/include/fpu.h index 612e1bb0137..345bebbb8ce 100644 --- a/sys/arch/amd64/include/fpu.h +++ b/sys/arch/amd64/include/fpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fpu.h,v 1.7 2010/11/20 20:11:17 miod Exp $ */ +/* $OpenBSD: fpu.h,v 1.8 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ #ifndef _AMD64_FPU_H_ @@ -49,6 +49,8 @@ struct savefpu { struct trapframe; struct cpu_info; +extern uint32_t fpu_mxcsr_mask; + void fpuinit(struct cpu_info *); void fpudrop(void); void fpudiscard(struct proc *); diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index b6af6b52eef..8a82fac962b 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.488 2011/03/12 03:52:26 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.489 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -2367,9 +2367,12 @@ sys_sigreturn(struct proc *p, void *v, register_t *retval) npxsave_proc(p, 0); if (context.sc_fpstate) { - if ((error = copyin(context.sc_fpstate, - &p->p_addr->u_pcb.pcb_savefpu, sizeof (union savefpu)))) + union savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu; + + if ((error = copyin(context.sc_fpstate, sfp, sizeof(*sfp)))) return (error); + if (i386_use_fxsave) + sfp->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask; p->p_md.md_flags |= MDP_USEDFPU; } diff --git a/sys/arch/i386/i386/process_machdep.c b/sys/arch/i386/i386/process_machdep.c index f3eed0a4a2b..e65ce8b02c1 100644 --- a/sys/arch/i386/i386/process_machdep.c +++ b/sys/arch/i386/i386/process_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: process_machdep.c,v 1.26 2010/12/27 12:48:35 kettenis Exp $ */ +/* $OpenBSD: process_machdep.c,v 1.27 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: process_machdep.c,v 1.22 1996/05/03 19:42:25 christos Exp $ */ /* @@ -137,6 +137,7 @@ process_fninit_xmm(struct savexmm *sxmm) memset(sxmm, 0, sizeof(*sxmm)); sxmm->sv_env.en_cw = __OpenBSD_NPXCW__; sxmm->sv_env.en_mxcsr = __INITIAL_MXCSR__; + sxmm->sv_env.en_mxcsr_mask = fpu_mxcsr_mask; sxmm->sv_env.en_sw = 0x0000; sxmm->sv_env.en_tw = 0x00; } @@ -359,6 +360,7 @@ process_write_xmmregs(struct proc *p, const struct xmmregs *regs) p->p_md.md_flags |= MDP_USEDFPU; memcpy(&frame->sv_xmm, regs, sizeof(*regs)); + frame->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask; return (0); } diff --git a/sys/arch/i386/include/npx.h b/sys/arch/i386/include/npx.h index 7b92a8693fb..c4171607f67 100644 --- a/sys/arch/i386/include/npx.h +++ b/sys/arch/i386/include/npx.h @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.h,v 1.15 2010/09/29 15:11:31 joshe Exp $ */ +/* $OpenBSD: npx.h,v 1.16 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: npx.h,v 1.11 1994/10/27 04:16:11 cgd Exp $ */ /*- @@ -96,7 +96,7 @@ struct envxmm { uint16_t en_fos; /* FPU Data pointer selector */ uint16_t en_rsvd2; uint32_t en_mxcsr; /* MXCSR Register State */ - uint32_t en_rsvd3; + uint32_t en_mxcsr_mask; /* Mask for valid MXCSR bits (may be 0) */ }; /* FPU regsters in the extended save format. */ @@ -141,7 +141,8 @@ struct emcsts { * The default MXCSR value at reset is 0x1f80, IA-32 Instruction * Set Reference, pg. 3-369. */ -#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf /* * The standard control word from finit is 0x37F, giving: @@ -158,6 +159,8 @@ void process_s87_to_xmm(const struct save87 *, struct savexmm *); struct cpu_info; struct trapframe; +extern uint32_t fpu_mxcsr_mask; + void npxinit(struct cpu_info *); void npxtrap(struct trapframe *); void fpu_kernel_enter(void); diff --git a/sys/arch/i386/isa/npx.c b/sys/arch/i386/isa/npx.c index ade5e5872f2..0699d910b03 100644 --- a/sys/arch/i386/isa/npx.c +++ b/sys/arch/i386/isa/npx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: npx.c,v 1.53 2010/09/29 15:11:31 joshe Exp $ */ +/* $OpenBSD: npx.c,v 1.54 2011/03/20 21:44:08 guenther Exp $ */ /* $NetBSD: npx.c,v 1.57 1996/05/12 23:12:24 mycroft Exp $ */ #if 0 @@ -97,6 +97,11 @@ #define clts() __asm("clts") #define stts() lcr0(rcr0() | CR0_TS) +/* + * The mxcsr_mask for this host, taken from fxsave() on the primary CPU + */ +uint32_t fpu_mxcsr_mask; + int npxintr(void *); static int npxprobe1(struct isa_attach_args *); static int x86fpflags_to_siginfo(u_int32_t); @@ -351,6 +356,16 @@ npxinit(struct cpu_info *ci) printf("%s: WARNING: Pentium FDIV bug detected!\n", ci->ci_dev.dv_xname); } + if (fpu_mxcsr_mask == 0 && i386_use_fxsave) { + struct savexmm xm __attribute__((aligned(16))); + + bzero(&xm, sizeof(xm)); + fxsave(&xm); + if (xm.sv_env.en_mxcsr_mask) + fpu_mxcsr_mask = xm.sv_env.en_mxcsr_mask; + else + fpu_mxcsr_mask = __INITIAL_MXCSR_MASK__; + } lcr0(rcr0() | (CR0_TS)); } |