Module Name:    src
Committed By:   maxv
Date:           Wed Nov 27 06:24:33 UTC 2019

Modified Files:
        src/sys/arch/x86/include: cpu.h fpu.h
        src/sys/arch/x86/x86: cpu.c fpu.c

Log Message:
Add a small API for in-kernel FPU operations.

        fpu_kern_enter();
        /* do FPU stuff */
        fpu_kern_leave();


To generate a diff of this commit:
cvs rdiff -u -r1.113 -r1.114 src/sys/arch/x86/include/cpu.h
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/x86/include/fpu.h
cvs rdiff -u -r1.176 -r1.177 src/sys/arch/x86/x86/cpu.c
cvs rdiff -u -r1.59 -r1.60 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/include/cpu.h
diff -u src/sys/arch/x86/include/cpu.h:1.113 src/sys/arch/x86/include/cpu.h:1.114
--- src/sys/arch/x86/include/cpu.h:1.113	Sat Nov 23 19:40:37 2019
+++ src/sys/arch/x86/include/cpu.h	Wed Nov 27 06:24:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.113 2019/11/23 19:40:37 ad Exp $	*/
+/*	$NetBSD: cpu.h,v 1.114 2019/11/27 06:24:33 maxv Exp $	*/
 
 /*
  * Copyright (c) 1990 The Regents of the University of California.
@@ -139,6 +139,8 @@ struct cpu_info {
 	uintptr_t ci_pmap_data[64 / sizeof(uintptr_t)];
 	struct kcpuset *ci_tlb_cpuset;
 
+	int ci_kfpu_spl;
+
 #ifndef XENPV
 	struct intrsource *ci_isources[MAX_INTR_SOURCES];
 #endif

Index: src/sys/arch/x86/include/fpu.h
diff -u src/sys/arch/x86/include/fpu.h:1.19 src/sys/arch/x86/include/fpu.h:1.20
--- src/sys/arch/x86/include/fpu.h:1.19	Sat Oct 12 06:31:03 2019
+++ src/sys/arch/x86/include/fpu.h	Wed Nov 27 06:24:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.h,v 1.19 2019/10/12 06:31:03 maxv Exp $	*/
+/*	$NetBSD: fpu.h,v 1.20 2019/11/27 06:24:33 maxv Exp $	*/
 
 #ifndef	_X86_FPU_H_
 #define	_X86_FPU_H_
@@ -30,6 +30,9 @@ void fpu_sigreset(struct lwp *);
 void fpu_lwp_fork(struct lwp *, struct lwp *);
 void fpu_lwp_abandon(struct lwp *l);
 
+void fpu_kern_enter(void);
+void fpu_kern_leave(void);
+
 void process_write_fpregs_xmm(struct lwp *, const struct fxsave *);
 void process_write_fpregs_s87(struct lwp *, const struct save87 *);
 

Index: src/sys/arch/x86/x86/cpu.c
diff -u src/sys/arch/x86/x86/cpu.c:1.176 src/sys/arch/x86/x86/cpu.c:1.177
--- src/sys/arch/x86/x86/cpu.c:1.176	Sat Nov 23 19:40:37 2019
+++ src/sys/arch/x86/x86/cpu.c	Wed Nov 27 06:24:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.176 2019/11/23 19:40:37 ad Exp $	*/
+/*	$NetBSD: cpu.c,v 1.177 2019/11/27 06:24:33 maxv Exp $	*/
 
 /*
  * Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.176 2019/11/23 19:40:37 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.177 2019/11/27 06:24:33 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"		/* for MPDEBUG */
@@ -376,6 +376,7 @@ cpu_attach(device_t parent, device_t sel
 	ci->ci_acpiid = caa->cpu_id;
 	ci->ci_cpuid = caa->cpu_number;
 	ci->ci_func = caa->cpu_func;
+	ci->ci_kfpu_spl = -1;
 	aprint_normal("\n");
 
 	/* Must be before mi_cpu_attach(). */

Index: src/sys/arch/x86/x86/fpu.c
diff -u src/sys/arch/x86/x86/fpu.c:1.59 src/sys/arch/x86/x86/fpu.c:1.60
--- src/sys/arch/x86/x86/fpu.c:1.59	Wed Oct 30 16:32:04 2019
+++ src/sys/arch/x86/x86/fpu.c	Wed Nov 27 06:24:33 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.c,v 1.59 2019/10/30 16:32:04 maxv Exp $	*/
+/*	$NetBSD: fpu.c,v 1.60 2019/11/27 06:24:33 maxv 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.59 2019/10/30 16:32:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.60 2019/11/27 06:24:33 maxv Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -146,14 +146,9 @@ fpu_lwp_area(struct lwp *l)
 	return area;
 }
 
-/*
- * Bring curlwp's FPU state in memory. It will get installed back in the CPU
- * when returning to userland.
- */
-void
-fpu_save(void)
+static inline void
+fpu_save_lwp(struct lwp *l)
 {
-	struct lwp *l = curlwp;
 	struct pcb *pcb = lwp_getpcb(l);
 	union savefpu *area = &pcb->pcb_savefpu;
 
@@ -166,6 +161,16 @@ fpu_save(void)
 	kpreempt_enable();
 }
 
+/*
+ * Bring curlwp's FPU state in memory. It will get installed back in the CPU
+ * when returning to userland.
+ */
+void
+fpu_save(void)
+{
+	fpu_save_lwp(curlwp);
+}
+
 void
 fpuinit(struct cpu_info *ci)
 {
@@ -338,6 +343,45 @@ fpu_lwp_abandon(struct lwp *l)
 
 /* -------------------------------------------------------------------------- */
 
+void
+fpu_kern_enter(void)
+{
+	struct lwp *l = curlwp;
+	struct cpu_info *ci;
+	int s;
+
+	s = splhigh();
+
+	ci = curcpu();
+	KASSERT(ci->ci_kfpu_spl == -1);
+	ci->ci_kfpu_spl = s;
+
+	/*
+	 * If we are in a softint and have a pinned lwp, the fpu state is that
+	 * of the pinned lwp, so save it there.
+	 */
+	if ((l->l_pflag & LP_INTR) && (l->l_switchto != NULL)) {
+		fpu_save_lwp(l->l_switchto);
+	} else {
+		fpu_save_lwp(l);
+	}
+}
+
+void
+fpu_kern_leave(void)
+{
+	struct cpu_info *ci = curcpu();
+	int s;
+
+	KASSERT(ci->ci_ilevel == IPL_HIGH);
+	KASSERT(ci->ci_kfpu_spl != -1);
+	s = ci->ci_kfpu_spl;
+	ci->ci_kfpu_spl = -1;
+	splx(s);
+}
+
+/* -------------------------------------------------------------------------- */
+
 /*
  * The following table is used to ensure that the FPE_... value
  * that is passed as a trapcode to the signal handler of the user

Reply via email to