> Originally worked out by joshe@; this corrects the timing of the call to
> fpuinit() for the primary CPU on amd64 so that the saved mask value is
> initialized correctly.
Hmm, I'm not too happy about moving fpuinit() out of cpu_hatch() on
amd64, while leaving npxinit() in there for i386.
Also:
> Index: sys/arch/amd64/amd64/cpu.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/amd64/cpu.c,v
> retrieving revision 1.40
> diff -u -p -r1.40 cpu.c
> --- sys/arch/amd64/amd64/cpu.c 27 Nov 2010 13:03:04 -0000 1.40
> +++ sys/arch/amd64/amd64/cpu.c 25 Dec 2010 19:38:48 -0000
> @@ -103,6 +105,16 @@ fpuinit(struct cpu_info *ci)
> {
> lcr0(rcr0() & ~(CR0_EM|CR0_TS));
> fninit();
> + if (CPU_IS_PRIMARY(ci)) {
> + 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));
> }
This function will be run again upon resume. Now overwriting
fpu_mxcsr_mask shouldn't hurt, but perhaps replacing:
if (CPU_IS_PRIMARY(ci)) {
with
if (fpu_mxcsr_mask == 0) {
would be better?
> Index: sys/arch/i386/i386/process_machdep.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/i386/i386/process_machdep.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 process_machdep.c
> --- sys/arch/i386/i386/process_machdep.c 29 Sep 2010 15:11:31 -0000
> 1.25
> +++ sys/arch/i386/i386/process_machdep.c 25 Dec 2010 19:38:52 -0000
> @@ -308,6 +309,7 @@ process_write_fpregs(struct proc *p, str
> /* XXX Yuck. */
> memcpy(&s87, regs, sizeof(*regs));
> process_s87_to_xmm(&s87, &frame->sv_xmm);
> + frame->sv_xmm.sv_env.en_mxcsr &= fpu_mxcsr_mask;
> } else
> memcpy(&frame->sv_87, regs, sizeof(*regs));
Oh, this actually points out an interesting problem. The MXCSR
register isn't initialized from data passed to us by userland.
However, if a user calls ptrace(PT_SETFPREGS, ...) on a process that
didn't use the FPU yet, it isn't quite clear what we initialize the
XMM state to. While your approach will make sure we won't cause a
segfault, we might still be leaking stuff from the kernel to userland.
I think the diff below is a better way to address the issue.
Index: process_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/process_machdep.c,v
retrieving revision 1.25
diff -u -p -r1.25 process_machdep.c
--- process_machdep.c 29 Sep 2010 15:11:31 -0000 1.25
+++ process_machdep.c 26 Dec 2010 15:23:33 -0000
@@ -299,8 +299,15 @@ process_write_fpregs(struct proc *p, str
#if NNPX > 0
npxsave_proc(p, 0);
#endif
- } else
+ } else {
+ /*
+ * Make sure MXCSR and the XMM registers are
+ * initialized to sane defaults.
+ */
+ if (i386_use_fxsave)
+ process_fninit_xmm(&frame->sv_xmm);
p->p_md.md_flags |= MDP_USEDFPU;
+ }
if (i386_use_fxsave) {
struct save87 s87;