Module Name:    src
Committed By:   riastradh
Date:           Mon Jul 20 16:41:18 UTC 2020

Modified Files:
        src/sys/arch/x86/x86: fpu.c

Log Message:
Save fpu state at IPL_VM to exclude fpu_kern_enter/leave.

This way fpu_kern_enter/leave cannot interrupt the transition, so the
transition from state-on-CPU to state-in-memory (with TS set) is
atomic whether in an interrupt or not.

(I am not 100% convinced that this is necessary, but it makes
reasoning about the transition simpler.)


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/sys/arch/x86/x86/fpu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/fpu.c
diff -u src/sys/arch/x86/x86/fpu.c:1.70 src/sys/arch/x86/x86/fpu.c:1.71
--- src/sys/arch/x86/x86/fpu.c:1.70	Mon Jul 20 16:38:47 2020
+++ src/sys/arch/x86/x86/fpu.c	Mon Jul 20 16:41:18 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.c,v 1.70 2020/07/20 16:38:47 riastradh Exp $	*/
+/*	$NetBSD: fpu.c,v 1.71 2020/07/20 16:41:18 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2008, 2019 The NetBSD Foundation, Inc.  All
@@ -96,7 +96,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.70 2020/07/20 16:38:47 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.71 2020/07/20 16:41:18 riastradh Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -151,14 +151,15 @@ fpu_save_lwp(struct lwp *l)
 {
 	struct pcb *pcb = lwp_getpcb(l);
 	union savefpu *area = &pcb->pcb_savefpu;
+	int s;
 
-	kpreempt_disable();
+	s = splvm();
 	if (l->l_md.md_flags & MDL_FPU_IN_CPU) {
 		KASSERT((l->l_flag & LW_SYSTEM) == 0);
 		fpu_area_save(area, x86_xsave_features);
 		l->l_md.md_flags &= ~MDL_FPU_IN_CPU;
 	}
-	kpreempt_enable();
+	splx(s);
 }
 
 /*
@@ -299,8 +300,12 @@ fpu_handle_deferred(void)
 void
 fpu_switch(struct lwp *oldlwp, struct lwp *newlwp)
 {
+	struct cpu_info *ci __diagused = curcpu();
 	struct pcb *pcb;
 
+	KASSERTMSG(ci->ci_ilevel >= IPL_SCHED, "cpu%d ilevel=%d",
+	    cpu_index(ci), ci->ci_ilevel);
+
 	if (oldlwp->l_md.md_flags & MDL_FPU_IN_CPU) {
 		KASSERT(!(oldlwp->l_flag & LW_SYSTEM));
 		pcb = lwp_getpcb(oldlwp);
@@ -334,11 +339,13 @@ fpu_lwp_fork(struct lwp *l1, struct lwp 
 void
 fpu_lwp_abandon(struct lwp *l)
 {
+	int s;
+
 	KASSERT(l == curlwp);
-	kpreempt_disable();
+	s = splvm();
 	l->l_md.md_flags &= ~MDL_FPU_IN_CPU;
 	stts();
-	kpreempt_enable();
+	splx(s);
 }
 
 /* -------------------------------------------------------------------------- */

Reply via email to