Author: kib
Date: Wed Oct 14 23:01:41 2020
New Revision: 366713
URL: https://svnweb.freebsd.org/changeset/base/366713

Log:
  Fix for mis-interpretation of PCB_KERNFPU.
  
  RIght now PCB_KERNFPU is used both as indication that kernel prepared
  hardware FPU context to use and that the thread is fpu-kern
  thread.  This also breaks fpu_kern_enter(FPU_KERN_NOCTX), since
  fpu_kern_leave() then clears PCB_KERNFPU.
  
  Introduce new flag PCB_KERNFPU_THR which indicates that the thread is
  fpu-kern.  Do not clear PCB_KERNFPU if fpu-kern thread leaves noctx
  fpu region.
  
  Reported and tested by:       jhb (amd64)
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week
  Differential revision:        https://reviews.freebsd.org/D25511

Modified:
  head/sys/amd64/amd64/fpu.c
  head/sys/amd64/include/pcb.h
  head/sys/i386/i386/npx.c
  head/sys/i386/include/pcb.h

Modified: head/sys/amd64/amd64/fpu.c
==============================================================================
--- head/sys/amd64/amd64/fpu.c  Wed Oct 14 22:57:50 2020        (r366712)
+++ head/sys/amd64/amd64/fpu.c  Wed Oct 14 23:01:41 2020        (r366713)
@@ -1230,8 +1230,9 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx 
        if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
                if ((pcb->pcb_flags & PCB_USERFPUINITDONE) != 0) {
                        set_pcb_flags(pcb, PCB_FPUINITDONE);
-                       clear_pcb_flags(pcb, PCB_KERNFPU);
-               } else
+                       if ((pcb->pcb_flags & PCB_KERNFPU_THR) == 0)
+                               clear_pcb_flags(pcb, PCB_KERNFPU);
+               } else if ((pcb->pcb_flags & PCB_KERNFPU_THR) == 0)
                        clear_pcb_flags(pcb, PCB_FPUINITDONE | PCB_KERNFPU);
        } else {
                if ((ctx->flags & FPU_KERN_CTX_FPUINITDONE) != 0)
@@ -1254,7 +1255,7 @@ fpu_kern_thread(u_int flags)
            ("mangled pcb_save"));
        KASSERT(PCB_USER_FPU(curpcb), ("recursive call"));
 
-       set_pcb_flags(curpcb, PCB_KERNFPU);
+       set_pcb_flags(curpcb, PCB_KERNFPU | PCB_KERNFPU_THR);
        return (0);
 }
 
@@ -1264,7 +1265,7 @@ is_fpu_kern_thread(u_int flags)
 
        if ((curthread->td_pflags & TDP_KTHREAD) == 0)
                return (0);
-       return ((curpcb->pcb_flags & PCB_KERNFPU) != 0);
+       return ((curpcb->pcb_flags & PCB_KERNFPU_THR) != 0);
 }
 
 /*

Modified: head/sys/amd64/include/pcb.h
==============================================================================
--- head/sys/amd64/include/pcb.h        Wed Oct 14 22:57:50 2020        
(r366712)
+++ head/sys/amd64/include/pcb.h        Wed Oct 14 23:01:41 2020        
(r366713)
@@ -84,6 +84,7 @@ struct pcb {
 #define        PCB_KERNFPU     0x04    /* kernel uses fpu */
 #define        PCB_FPUINITDONE 0x08    /* fpu state is initialized */
 #define        PCB_USERFPUINITDONE 0x10 /* fpu user state is initialized */
+#define        PCB_KERNFPU_THR 0x20    /* fpu_kern_thread() */
 #define        PCB_32BIT       0x40    /* process has 32 bit context (segs 
etc) */
 #define        PCB_FPUNOSAVE   0x80    /* no save area for current FPU ctx */
 

Modified: head/sys/i386/i386/npx.c
==============================================================================
--- head/sys/i386/i386/npx.c    Wed Oct 14 22:57:50 2020        (r366712)
+++ head/sys/i386/i386/npx.c    Wed Oct 14 23:01:41 2020        (r366713)
@@ -1472,11 +1472,12 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx 
        }
 
        if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
-               if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0)
+               if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0) {
                        pcb->pcb_flags |= PCB_NPXINITDONE;
-               else
-                       pcb->pcb_flags &= ~PCB_NPXINITDONE;
-               pcb->pcb_flags &= ~PCB_KERNNPX;
+                       if ((pcb->pcb_flags & PCB_KERNNPX_THR) == 0)
+                               pcb->pcb_flags |= ~PCB_KERNNPX;
+               } else if ((pcb->pcb_flags & PCB_KERNNPX_THR) == 0)
+                       pcb->pcb_flags &= ~(PCB_NPXINITDONE | PCB_KERNNPX);
        } else {
                if ((ctx->flags & FPU_KERN_CTX_NPXINITDONE) != 0)
                        pcb->pcb_flags |= PCB_NPXINITDONE;
@@ -1498,7 +1499,7 @@ fpu_kern_thread(u_int flags)
            ("mangled pcb_save"));
        KASSERT(PCB_USER_FPU(curpcb), ("recursive call"));
 
-       curpcb->pcb_flags |= PCB_KERNNPX;
+       curpcb->pcb_flags |= PCB_KERNNPX | PCB_KERNNPX_THR;
        return (0);
 }
 
@@ -1508,7 +1509,7 @@ is_fpu_kern_thread(u_int flags)
 
        if ((curthread->td_pflags & TDP_KTHREAD) == 0)
                return (0);
-       return ((curpcb->pcb_flags & PCB_KERNNPX) != 0);
+       return ((curpcb->pcb_flags & PCB_KERNNPX_THR) != 0);
 }
 
 /*

Modified: head/sys/i386/include/pcb.h
==============================================================================
--- head/sys/i386/include/pcb.h Wed Oct 14 22:57:50 2020        (r366712)
+++ head/sys/i386/include/pcb.h Wed Oct 14 23:01:41 2020        (r366713)
@@ -82,6 +82,7 @@ struct pcb {
 
        u_int   pcb_flags;
 #define        PCB_DBREGS      0x02    /* process using debug registers */
+#define        PCB_KERNNPX_THR 0x04    /* fpu_kern_thread() */
 #define        PCB_NPXINITDONE 0x08    /* fpu state is initialized */
 #define        PCB_VM86CALL    0x10    /* in vm86 call */
 #define        PCB_NPXUSERINITDONE 0x20 /* user fpu state is initialized */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to