]> git.proxmox.com Git - mirror_zfs.git/commitdiff
FreeBSD: Don't save user FPU context in kernel threads
authorMatthew Macy <mmacy@freebsd.org>
Wed, 23 Sep 2020 18:09:48 +0000 (11:09 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Sep 2020 18:09:48 +0000 (11:09 -0700)
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Ryan Moeller <freqlabs@FreeBSD.org>
Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Closes #10899

include/os/freebsd/spl/sys/simd_x86.h
module/os/freebsd/spl/spl_taskq.c

index a35e205d5a3b17ace5f82f0b46a3a1247c8356c0..63d6017b79e0a5694881cea6c39d364b0809dc3e 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <sys/systm.h>
+#include <sys/proc.h>
 #ifdef __i386__
 #include <x86/fpu.h>
 #else
 #define        kfpu_allowed()          1
 #define        kfpu_initialize(tsk)    do {} while (0)
 
-#define        kfpu_begin() {                                                  \
-       critical_enter();                                       \
-       fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX); \
+#define        kfpu_begin() {                                  \
+       if (__predict_false(!is_fpu_kern_thread(0)))            \
+               fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);\
 }
 
-#define        kfpu_end()                                              \
-       {                                                \
-               fpu_kern_leave(curthread, NULL); \
-               critical_exit();                             \
-       }
+#define        kfpu_end()      {                       \
+       if (__predict_false(curpcb->pcb_flags & PCB_FPUNOSAVE)) \
+               fpu_kern_leave(curthread, NULL);        \
+}
 
 /*
  * Check if OS supports AVX and AVX2 by checking XCR0
index 049e889cf304ef249476415635161cacb0c26193..cc025de959e39e2ab3531f87a81ed6ec6d20df56 100644 (file)
@@ -169,6 +169,10 @@ taskq_tsd_set(void *context)
 {
        taskq_t *tq = context;
 
+#if defined(__amd64__) || defined(__i386__) || defined(__aarch64__)
+       if (context != NULL && tsd_get(taskq_tsd) == NULL)
+               fpu_kern_thread(FPU_KERN_NORMAL);
+#endif
        tsd_set(taskq_tsd, tq);
 }