Module Name:    src
Committed By:   riastradh
Date:           Sat Aug  1 02:04:55 UTC 2020

Modified Files:
        src/share/man/man9: kthread.9
        src/sys/kern: kern_kthread.c kern_stub.c
        src/sys/sys: kthread.h lwp.h

Log Message:
New functions kthread_fpu_enter/exit.

The MI definitions don't do anything but maintain a flag, but MD code
can define kthread_fpu_enter/exit_md to actually enable/disable the
FPU.  (These are almost pcu_load/discard on systems that use pcu(9),
except they apply to all PCUs.)

Discussed on tech-kern:
https://mail-index.netbsd.org/tech-kern/2020/06/20/msg026524.html

The proposed kthread flag KTHREAD_FPU is not included because I
couldn't find any particular need for it that would not be covered by
just calling kthread_fpu_enter/exit in the kthread function.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/share/man/man9/kthread.9
cvs rdiff -u -r1.45 -r1.46 src/sys/kern/kern_kthread.c
cvs rdiff -u -r1.49 -r1.50 src/sys/kern/kern_stub.c
cvs rdiff -u -r1.13 -r1.14 src/sys/sys/kthread.h
cvs rdiff -u -r1.210 -r1.211 src/sys/sys/lwp.h

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

Modified files:

Index: src/share/man/man9/kthread.9
diff -u src/share/man/man9/kthread.9:1.28 src/share/man/man9/kthread.9:1.29
--- src/share/man/man9/kthread.9:1.28	Tue Apr 21 11:10:29 2015
+++ src/share/man/man9/kthread.9	Sat Aug  1 02:04:55 2020
@@ -1,4 +1,4 @@
-.\"     $NetBSD: kthread.9,v 1.28 2015/04/21 11:10:29 pooka Exp $
+.\"     $NetBSD: kthread.9,v 1.29 2020/08/01 02:04:55 riastradh Exp $
 .\"
 .\" Copyright (c) 2000, 2007, 2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -33,7 +33,9 @@
 .Sh NAME
 .Nm kthread_create ,
 .Nm kthread_exit ,
-.Nm kthread_join
+.Nm kthread_join ,
+.Nm kthread_fpu_enter ,
+.Nm kthread_fpu_exit
 .Nd kernel threads
 .Sh SYNOPSIS
 .In sys/kthread.h
@@ -44,6 +46,10 @@
 .Fn kthread_exit "int ecode"
 .Ft int
 .Fn kthread_join "lwp_t *l"
+.Ft int
+.Fn kthread_fpu_enter
+.Ft void
+.Fn kthread_fpu_exit "int s"
 .Sh DESCRIPTION
 Kernel threads are light-weight processes which execute entirely
 within the kernel.
@@ -51,6 +57,13 @@ within the kernel.
 Any process can request the creation of a new kernel thread.
 Kernel threads are not swapped out during memory congestion.
 The VM space and limits are shared with proc0 (usually swapper).
+.Pp
+If the machine has any per-CPU floating-point units or SIMD vector
+units that are normally available to user threads, they can be used by
+kthreads between
+.Fn kthread_fpu_enter
+and
+.fn kthread_fpu_exit .
 .Sh FUNCTIONS
 .Bl -tag -width compact
 .It Fn kthread_create "pri" "flags" "ci" "func" "arg" "newlp" "fmt" "..."
@@ -155,6 +168,31 @@ created using the
 .Dv KTHREAD_MUSTJOIN
 flag and would wait on
 .Fa kthread_exit .
+.It Fn kthread_fpu_enter
+Allow the current kthread to use any machine-dependent per-CPU
+floating-point units or SIMD vector units normally available to user
+threads.
+Returns a cookie that must be passed to
+.Fn kthread_fpu_exit
+when done.
+.Pp
+Matching pairs of
+.Fn kthread_fpu_enter
+and
+.Fn kthread_fpu_exit
+may be nested.
+.It Fn kthread_fpu_exit "s"
+Restore the current kthread's access to machine-dependent per-CPU
+floating-point units or SIMD vector units to what it was before the
+call to
+.Fn kthread_fpu_enter
+that returned
+.Fa s .
+.Pp
+On the last
+.Fn kthread_fpu_exit ,
+zero all the units' registers to avoid leaking secrets \(em such units
+are often used for cryptography.
 .El
 .Sh RETURN VALUES
 Upon successful completion,

Index: src/sys/kern/kern_kthread.c
diff -u src/sys/kern/kern_kthread.c:1.45 src/sys/kern/kern_kthread.c:1.46
--- src/sys/kern/kern_kthread.c:1.45	Wed Jan  8 17:38:42 2020
+++ src/sys/kern/kern_kthread.c	Sat Aug  1 02:04:55 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_kthread.c,v 1.45 2020/01/08 17:38:42 ad Exp $	*/
+/*	$NetBSD: kern_kthread.c,v 1.46 2020/08/01 02:04:55 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2007, 2009, 2019 The NetBSD Foundation, Inc.
@@ -31,9 +31,10 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.45 2020/01/08 17:38:42 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.46 2020/08/01 02:04:55 riastradh Exp $");
 
 #include <sys/param.h>
+#include <sys/cpu.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
@@ -216,3 +217,71 @@ kthread_join(lwp_t *l)
 
 	return 0;
 }
+
+/*
+ * kthread_fpu_enter()
+ *
+ *	Allow the current lwp, which must be a kthread, to use the FPU.
+ *	Return a cookie that must be passed to kthread_fpu_exit when
+ *	done.  Must be used only in thread context.  Recursive -- you
+ *	can call kthread_fpu_enter several times in a row as long as
+ *	you pass the cookies in reverse order to kthread_fpu_exit.
+ */
+int
+kthread_fpu_enter(void)
+{
+	struct lwp *l = curlwp;
+	int s;
+
+	KASSERTMSG(!cpu_intr_p(),
+	    "%s is not allowed in interrupt context", __func__);
+	KASSERTMSG(!cpu_softintr_p(),
+	    "%s is not allowed in interrupt context", __func__);
+
+	/*
+	 * Remember whether this thread already had FPU access, and
+	 * mark this thread as having FPU access.
+	 */
+	lwp_lock(l);
+	KASSERTMSG(l->l_flag & LW_SYSTEM,
+	    "%s is allowed only in kthreads", __func__);
+	s = l->l_flag & LW_SYSTEM_FPU;
+	l->l_flag |= LW_SYSTEM_FPU;
+	lwp_unlock(l);
+
+	/* Take MD steps to enable the FPU if necessary.  */
+	if (s == 0)
+		kthread_fpu_enter_md();
+
+	return s;
+}
+
+/*
+ * kthread_fpu_exit(s)
+ *
+ *	Restore the current lwp's FPU access to what it was before the
+ *	matching call to kthread_fpu_enter() that returned s.  Must be
+ *	used only in thread context.
+ */
+void
+kthread_fpu_exit(int s)
+{
+	struct lwp *l = curlwp;
+
+	KASSERT(s == (s & LW_SYSTEM_FPU));
+	KASSERTMSG(!cpu_intr_p(),
+	    "%s is not allowed in interrupt context", __func__);
+	KASSERTMSG(!cpu_softintr_p(),
+	    "%s is not allowed in interrupt context", __func__);
+
+	lwp_lock(l);
+	KASSERTMSG(l->l_flag & LW_SYSTEM,
+	    "%s is allowed only in kthreads", __func__);
+	KASSERT(l->l_flag & LW_SYSTEM_FPU);
+	l->l_flag ^= s ^ LW_SYSTEM_FPU;
+	lwp_unlock(l);
+
+	/* Take MD steps to zero and disable the FPU if necessary.  */
+	if (s == 0)
+		kthread_fpu_exit_md();
+}

Index: src/sys/kern/kern_stub.c
diff -u src/sys/kern/kern_stub.c:1.49 src/sys/kern/kern_stub.c:1.50
--- src/sys/kern/kern_stub.c:1.49	Sat May 23 23:42:43 2020
+++ src/sys/kern/kern_stub.c	Sat Aug  1 02:04:55 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_stub.c,v 1.49 2020/05/23 23:42:43 ad Exp $	*/
+/*	$NetBSD: kern_stub.c,v 1.50 2020/08/01 02:04:55 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.49 2020/05/23 23:42:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.50 2020/08/01 02:04:55 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ktrace.h"
@@ -328,3 +328,7 @@ default_bus_space_is_equal(bus_space_tag
 
 	return memcmp(&t1, &t2, sizeof(t1)) == 0;
 }
+
+/* Stubs for architectures with no kernel FPU access.  */
+__weak_alias(kthread_fpu_enter_md, voidop);
+__weak_alias(kthread_fpu_exit_md, voidop);

Index: src/sys/sys/kthread.h
diff -u src/sys/sys/kthread.h:1.13 src/sys/sys/kthread.h:1.14
--- src/sys/sys/kthread.h:1.13	Tue Apr 21 11:10:29 2015
+++ src/sys/sys/kthread.h	Sat Aug  1 02:04:55 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: kthread.h,v 1.13 2015/04/21 11:10:29 pooka Exp $	*/
+/*	$NetBSD: kthread.h,v 1.14 2020/08/01 02:04:55 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
@@ -56,4 +56,11 @@ int	kthread_create(pri_t, int, struct cp
 void	kthread_exit(int) __dead;
 int	kthread_join(lwp_t *);
 
+int	kthread_fpu_enter(void);
+void	kthread_fpu_exit(int);
+
+/* Internal MD routines -- for use only by kthread_fpu_enter/exit.  */
+void	kthread_fpu_enter_md(void);
+void	kthread_fpu_exit_md(void);
+
 #endif /* _SYS_KTHREAD_H_ */

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.210 src/sys/sys/lwp.h:1.211
--- src/sys/sys/lwp.h:1.210	Sat May 23 20:45:11 2020
+++ src/sys/sys/lwp.h	Sat Aug  1 02:04:55 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lwp.h,v 1.210 2020/05/23 20:45:11 ad Exp $	*/
+/*	$NetBSD: lwp.h,v 1.211 2020/08/01 02:04:55 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010, 2019, 2020
@@ -256,6 +256,7 @@ extern int		maxlwp __read_mostly;	/* max
 #define	LW_STIMO	0x00000040 /* Sleep timed out */
 #define	LW_SINTR	0x00000080 /* Sleep is interruptible. */
 #define	LW_SYSTEM	0x00000200 /* Kernel thread */
+#define	LW_SYSTEM_FPU	0x00000400 /* Kernel thread with vector/FP enabled */
 #define	LW_DBGSUSPEND	0x00010000 /* Suspend by debugger */
 #define	LW_WSUSPEND	0x00020000 /* Suspend before return to user */
 #define	LW_BATCH	0x00040000 /* LWP tends to hog CPU */

Reply via email to