svn commit: r366713 - in head/sys: amd64/amd64 amd64/include i386/i386 i386/include

Konstantin Belousov kib at FreeBSD.org
Wed Oct 14 23:01:43 UTC 2020


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 */


More information about the svn-src-all mailing list