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