kernel - Fix floating point save state structure and minor npx issues
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 22 Dec 2011 19:21:41 +0000 (11:21 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 22 Dec 2011 19:21:41 +0000 (11:21 -0800)
* The floating point save structure(s) used by the kernel and possibly
  also userland were too large for x86-64 due to a porting error where
  'long' variables were left intact that should have been turned into
  32-bit variables.

  No known adverse effect to the too-large structures but we have to get
  it right.

* npxexit() was not being called in a kernel thread exit case.  Kernel
  threads do not use the FP unit so the case was never hit, but fix it
  anyway.

* Move a critical section to cover a flags test to handle a very rare
  preemptive thread switch issue.  Since the preempting thread is a
  kernel thread which does not use the FP unit this case was never hit,
  but fix it anyway.

sys/cpu/x86_64/include/npx.h
sys/platform/pc32/i386/vm_machdep.c
sys/platform/pc64/x86_64/npx.c
sys/platform/pc64/x86_64/vm_machdep.c
sys/platform/vkernel/i386/vm_machdep.c
sys/platform/vkernel64/x86_64/vm_machdep.c

index 35f8184..2c36be7 100644 (file)
 
 /* Environment information of floating point unit */
 struct env87 {
-       long    en_cw;          /* control word (16bits) */
-       long    en_sw;          /* status word (16bits) */
-       long    en_tw;          /* tag word (16bits) */
-       long    en_fip;         /* floating point instruction pointer */
+       int32_t en_cw;          /* control word (16bits) */
+       int32_t en_sw;          /* status word (16bits) */
+       int32_t en_tw;          /* tag word (16bits) */
+       int32_t en_fip;         /* floating point instruction pointer */
        u_short en_fcs;         /* floating code segment selector */
        u_short en_opcode;      /* opcode last executed (11 bits ) */
-       long    en_foo;         /* floating operand offset */
-       long    en_fos;         /* floating operand segment selector */
+       int32_t en_foo;         /* floating operand offset */
+       int32_t en_fos;         /* floating operand segment selector */
 };
 
 /* Contents of each floating point accumulator */
 struct fpacc87 {
 #ifdef dontdef /* too unportable */
-       u_long  fp_mantlo;      /* mantissa low (31:0) */
-       u_long  fp_manthi;      /* mantissa high (63:32) */
+       u_int32_t fp_mantlo;    /* mantissa low (31:0) */
+       u_int32_t fp_manthi;    /* mantissa high (63:32) */
        int     fp_exp:15;      /* exponent */
        int     fp_sgn:1;       /* mantissa sign */
 #else
@@ -78,7 +78,7 @@ struct        fpacc87 {
 struct save87 {
        struct  env87 sv_env;   /* floating point control/status */
        struct  fpacc87 sv_ac[8];       /* accumulator contents, 0-7 */
-       u_long  sv_unused001;
+       u_int32_t       sv_unused001;
        /*
         * Bogus padding for emulators.  Emulators should use their own
         * struct and arrange to store into this struct (ending here)
@@ -120,7 +120,7 @@ struct  savexmm {
                u_char          fp_pad[6];      /* 6  (padding) */
        } sv_fp[8];
        struct xmmacc   sv_xmm[8];              /* 128 */
-       u_long sv_unused001;
+       u_int32_t       sv_unused001;
        u_char sv_pad[220];
 } __attribute__((aligned(16)));
 
index c8cd5f8..a1040c1 100644 (file)
@@ -274,10 +274,6 @@ cpu_lwp_exit(void)
        struct pcb *pcb;
        struct pcb_ext *ext;
 
-#if NNPX > 0
-       npxexit();
-#endif /* NNPX */
-
        /*
         * If we were using a private TSS do a forced-switch to ourselves
         * to switch back to the common TSS before freeing it.
@@ -320,6 +316,9 @@ cpu_lwp_exit(void)
 void
 cpu_thread_exit(void)
 {
+#if NNPX > 0
+       npxexit();
+#endif
        curthread->td_switch = cpu_exit_switch;
        curthread->td_flags |= TDF_EXITING;
        lwkt_switch();
index e3de3c8..5920a75 100644 (file)
@@ -328,6 +328,7 @@ npxdna(void)
         * used the FP unit.  This also occurs when a thread pushes a
         * signal handler and uses FP in the handler.
         */
+       crit_enter();
        if ((td->td_flags & (TDF_USINGFP | TDF_KERNELFP)) == 0) {
                td->td_flags |= TDF_USINGFP;
                npxinit(__INITIAL_NPXCW__);
@@ -341,7 +342,6 @@ npxdna(void)
         * and then restore the garbage rather then the originally saved
         * fpstate.
         */
-       crit_enter();
        stop_emulating();
        /*
         * Record new context early in case frstor causes an IRQ13.
index 0a3797d..890ccc1 100644 (file)
@@ -254,7 +254,6 @@ cpu_lwp_exit(void)
        struct thread *td = curthread;
        struct pcb *pcb;
 
-       npxexit();
        pcb = td->td_pcb;
 
        /* Some i386 functionality was dropped */
@@ -289,6 +288,7 @@ cpu_lwp_exit(void)
 void
 cpu_thread_exit(void)
 {
+       npxexit();
        curthread->td_switch = cpu_exit_switch;
        curthread->td_flags |= TDF_EXITING;
        lwkt_switch();
index a6408f7..3f25eb1 100644 (file)
@@ -274,10 +274,6 @@ cpu_lwp_exit(void)
        struct pcb *pcb;
        struct pcb_ext *ext;
 
-#if NNPX > 0
-       npxexit();
-#endif /* NNPX */
-
        /*
         * If we were using a private TSS do a forced-switch to ourselves
         * to switch back to the common TSS before freeing it.
@@ -320,6 +316,9 @@ cpu_lwp_exit(void)
 void
 cpu_thread_exit(void)
 {
+#if NNPX > 0
+       npxexit();
+#endif
        curthread->td_switch = cpu_exit_switch;
        curthread->td_flags |= TDF_EXITING;
        lwkt_switch();
index dcab929..5191810 100644 (file)
@@ -254,7 +254,7 @@ cpu_lwp_exit(void)
 {
        struct thread *td = curthread;
        struct pcb *pcb;
-       npxexit();
+
        pcb = td->td_pcb;
 
        /* Some i386 functionality was dropped */
@@ -289,6 +289,7 @@ cpu_lwp_exit(void)
 void
 cpu_thread_exit(void)
 {
+       npxexit();
        curthread->td_switch = cpu_exit_switch;
        curthread->td_flags |= TDF_EXITING;
        lwkt_switch();