svn commit: r366673 - in head/sys/i386: i386 include

John Baldwin jhb at FreeBSD.org
Tue Oct 13 17:27:38 UTC 2020


Author: jhb
Date: Tue Oct 13 17:27:37 2020
New Revision: 366673
URL: https://svnweb.freebsd.org/changeset/base/366673

Log:
  Add support for FPU_KERN_NOCTX.
  
  This mirrors the implementation on amd64.
  
  Reviewed by:	kib
  Sponsored by:	Netflix
  Differential Revision:	https://reviews.freebsd.org/D26754

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

Modified: head/sys/i386/i386/npx.c
==============================================================================
--- head/sys/i386/i386/npx.c	Tue Oct 13 17:26:12 2020	(r366672)
+++ head/sys/i386/i386/npx.c	Tue Oct 13 17:27:37 2020	(r366673)
@@ -886,6 +886,9 @@ npxdna(void)
 		return (0);
 	td = curthread;
 	critical_enter();
+
+	KASSERT((curpcb->pcb_flags & PCB_NPXNOSAVE) == 0,
+	    ("npxdna while in fpu_kern_enter(FPU_KERN_NOCTX)"));
 	if (__predict_false(PCPU_GET(fpcurthread) == td)) {
 		/*
 		 * Some virtual machines seems to set %cr0.TS at
@@ -1390,8 +1393,34 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx 
 {
 	struct pcb *pcb;
 
-	KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("using inuse ctx"));
+	pcb = td->td_pcb;
+	KASSERT((flags & FPU_KERN_NOCTX) != 0 || ctx != NULL,
+	    ("ctx is required when !FPU_KERN_NOCTX"));
+	KASSERT(ctx == NULL || (ctx->flags & FPU_KERN_CTX_INUSE) == 0,
+	    ("using inuse ctx"));
+	KASSERT((pcb->pcb_flags & PCB_NPXNOSAVE) == 0,
+	    ("recursive fpu_kern_enter while in PCB_NPXNOSAVE state"));
 
+	if ((flags & FPU_KERN_NOCTX) != 0) {
+		critical_enter();
+		stop_emulating();
+		if (curthread == PCPU_GET(fpcurthread)) {
+			fpusave(curpcb->pcb_save);
+			PCPU_SET(fpcurthread, NULL);
+		} else {
+			KASSERT(PCPU_GET(fpcurthread) == NULL,
+			    ("invalid fpcurthread"));
+		}
+
+		/*
+		 * This breaks XSAVEOPT tracker, but
+		 * PCB_NPXNOSAVE state is supposed to never need to
+		 * save FPU context at all.
+		 */
+		fpurstor(npx_initialstate);
+		pcb->pcb_flags |= PCB_KERNNPX | PCB_NPXNOSAVE | PCB_NPXINITDONE;
+		return;
+	}
 	if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) {
 		ctx->flags = FPU_KERN_CTX_DUMMY | FPU_KERN_CTX_INUSE;
 		return;
@@ -1416,17 +1445,32 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx 
 {
 	struct pcb *pcb;
 
-	KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
-	    ("leaving not inuse ctx"));
-	ctx->flags &= ~FPU_KERN_CTX_INUSE;
-
-	if (is_fpu_kern_thread(0) && (ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
-		return (0);
 	pcb = td->td_pcb;
-	critical_enter();
-	if (curthread == PCPU_GET(fpcurthread))
-		npxdrop();
-	pcb->pcb_save = ctx->prev;
+
+	if ((pcb->pcb_flags & PCB_NPXNOSAVE) != 0) {
+		KASSERT(ctx == NULL, ("non-null ctx after FPU_KERN_NOCTX"));
+		KASSERT(PCPU_GET(fpcurthread) == NULL,
+		    ("non-NULL fpcurthread for PCB_NPXNOSAVE"));
+		CRITICAL_ASSERT(td);
+
+		pcb->pcb_flags &= ~(PCB_NPXNOSAVE | PCB_NPXINITDONE);
+		start_emulating();
+	} else {
+		KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
+		    ("leaving not inuse ctx"));
+		ctx->flags &= ~FPU_KERN_CTX_INUSE;
+
+		if (is_fpu_kern_thread(0) &&
+		    (ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
+			return (0);
+		KASSERT((ctx->flags & FPU_KERN_CTX_DUMMY) == 0,
+		    ("dummy ctx"));
+		critical_enter();
+		if (curthread == PCPU_GET(fpcurthread))
+			npxdrop();
+		pcb->pcb_save = ctx->prev;
+	}
+
 	if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
 		if ((pcb->pcb_flags & PCB_NPXUSERINITDONE) != 0)
 			pcb->pcb_flags |= PCB_NPXINITDONE;

Modified: head/sys/i386/include/npx.h
==============================================================================
--- head/sys/i386/include/npx.h	Tue Oct 13 17:26:12 2020	(r366672)
+++ head/sys/i386/include/npx.h	Tue Oct 13 17:27:37 2020	(r366673)
@@ -92,6 +92,7 @@ void	fpu_save_area_reset(union savefpu *fsa);
 #define	FPU_KERN_NORMAL	0x0000
 #define	FPU_KERN_NOWAIT	0x0001
 #define	FPU_KERN_KTHR	0x0002
+#define	FPU_KERN_NOCTX	0x0004
 
 #endif
 

Modified: head/sys/i386/include/pcb.h
==============================================================================
--- head/sys/i386/include/pcb.h	Tue Oct 13 17:26:12 2020	(r366672)
+++ head/sys/i386/include/pcb.h	Tue Oct 13 17:27:37 2020	(r366673)
@@ -86,6 +86,7 @@ struct pcb {
 #define	PCB_VM86CALL	0x10	/* in vm86 call */
 #define	PCB_NPXUSERINITDONE 0x20 /* user fpu state is initialized */
 #define	PCB_KERNNPX	0x40	/* kernel uses npx */
+#define	PCB_NPXNOSAVE	0x80	/* no save area for current FPU ctx */
 
 	uint16_t pcb_initial_npxcw;
 


More information about the svn-src-all mailing list