111d62b6fSEmmanuel Vadot /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
311d62b6fSEmmanuel Vadot *
40b453151SVal Packett * Copyright (c) 2020 Val Packett <val@packett.cool>
511d62b6fSEmmanuel Vadot *
611d62b6fSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
711d62b6fSEmmanuel Vadot * modification, are permitted provided that the following conditions
811d62b6fSEmmanuel Vadot * are met:
911d62b6fSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
1011d62b6fSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
1111d62b6fSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
1211d62b6fSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
1311d62b6fSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
1411d62b6fSEmmanuel Vadot *
1511d62b6fSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1611d62b6fSEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1711d62b6fSEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1811d62b6fSEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1911d62b6fSEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2011d62b6fSEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2111d62b6fSEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2211d62b6fSEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2311d62b6fSEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2411d62b6fSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2511d62b6fSEmmanuel Vadot * SUCH DAMAGE.
2611d62b6fSEmmanuel Vadot */
2711d62b6fSEmmanuel Vadot
2811d62b6fSEmmanuel Vadot #include <sys/types.h>
2911d62b6fSEmmanuel Vadot #include <sys/param.h>
3011d62b6fSEmmanuel Vadot #include <sys/proc.h>
3111d62b6fSEmmanuel Vadot #include <sys/kernel.h>
3211d62b6fSEmmanuel Vadot
33*c0b8047bSVladimir Kondratyev #include <linux/compat.h>
34469884cfSHans Petter Selasky #include <linux/sched.h>
35469884cfSHans Petter Selasky
36469884cfSHans Petter Selasky #include <asm/fpu/api.h>
37469884cfSHans Petter Selasky
38*c0b8047bSVladimir Kondratyev #if defined(__aarch64__) || defined(__arm__) || defined(__amd64__) || \
39*c0b8047bSVladimir Kondratyev defined(__i386__) || defined(__powerpc64__)
40469884cfSHans Petter Selasky
4111d62b6fSEmmanuel Vadot #include <machine/fpu.h>
4211d62b6fSEmmanuel Vadot
43469884cfSHans Petter Selasky /*
44469884cfSHans Petter Selasky * Technically the Linux API isn't supposed to allow nesting sections
45469884cfSHans Petter Selasky * either, but currently used versions of GPU drivers rely on nesting
46469884cfSHans Petter Selasky * working, so we only enter the section on the outermost level.
47469884cfSHans Petter Selasky */
4811d62b6fSEmmanuel Vadot
49469884cfSHans Petter Selasky void
lkpi_kernel_fpu_begin(void)50469884cfSHans Petter Selasky lkpi_kernel_fpu_begin(void)
5111d62b6fSEmmanuel Vadot {
52db65db64SVladimir Kondratyev if ((current->fpu_ctx_level)++ == 0)
53db65db64SVladimir Kondratyev fpu_kern_enter(curthread, NULL, FPU_KERN_NOCTX);
5411d62b6fSEmmanuel Vadot }
5511d62b6fSEmmanuel Vadot
56469884cfSHans Petter Selasky void
lkpi_kernel_fpu_end(void)57469884cfSHans Petter Selasky lkpi_kernel_fpu_end(void)
5811d62b6fSEmmanuel Vadot {
59469884cfSHans Petter Selasky if (--(current->fpu_ctx_level) == 0)
60db65db64SVladimir Kondratyev fpu_kern_leave(curthread, NULL);
6111d62b6fSEmmanuel Vadot }
62469884cfSHans Petter Selasky
63*c0b8047bSVladimir Kondratyev void
lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func,void * ctx)64*c0b8047bSVladimir Kondratyev lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func, void *ctx)
65*c0b8047bSVladimir Kondratyev {
66*c0b8047bSVladimir Kondratyev unsigned int save_fpu_level;
67*c0b8047bSVladimir Kondratyev
68*c0b8047bSVladimir Kondratyev save_fpu_level =
69*c0b8047bSVladimir Kondratyev __current_unallocated(curthread) ? 0 : current->fpu_ctx_level;
70*c0b8047bSVladimir Kondratyev if (__predict_false(save_fpu_level != 0)) {
71*c0b8047bSVladimir Kondratyev current->fpu_ctx_level = 1;
72*c0b8047bSVladimir Kondratyev kernel_fpu_end();
73*c0b8047bSVladimir Kondratyev }
74*c0b8047bSVladimir Kondratyev func(ctx);
75*c0b8047bSVladimir Kondratyev if (__predict_false(save_fpu_level != 0)) {
76*c0b8047bSVladimir Kondratyev kernel_fpu_begin();
77*c0b8047bSVladimir Kondratyev current->fpu_ctx_level = save_fpu_level;
78*c0b8047bSVladimir Kondratyev }
79*c0b8047bSVladimir Kondratyev }
80*c0b8047bSVladimir Kondratyev
81469884cfSHans Petter Selasky #else
82469884cfSHans Petter Selasky
83469884cfSHans Petter Selasky void
lkpi_kernel_fpu_begin(void)84469884cfSHans Petter Selasky lkpi_kernel_fpu_begin(void)
85469884cfSHans Petter Selasky {
86469884cfSHans Petter Selasky }
87469884cfSHans Petter Selasky
88469884cfSHans Petter Selasky void
lkpi_kernel_fpu_end(void)89469884cfSHans Petter Selasky lkpi_kernel_fpu_end(void)
90469884cfSHans Petter Selasky {
91469884cfSHans Petter Selasky }
92469884cfSHans Petter Selasky
93*c0b8047bSVladimir Kondratyev void
lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func,void * ctx)94*c0b8047bSVladimir Kondratyev lkpi_fpu_safe_exec(fpu_safe_exec_cb_t func, void *ctx)
95*c0b8047bSVladimir Kondratyev {
96*c0b8047bSVladimir Kondratyev func(ctx);
97*c0b8047bSVladimir Kondratyev }
98*c0b8047bSVladimir Kondratyev
99469884cfSHans Petter Selasky #endif
100