|
| 1 | +.. SPDX-License-Identifier: GPL-2.0+ |
| 2 | +
|
| 3 | +Floating-point API |
| 4 | +================== |
| 5 | + |
| 6 | +Kernel code is normally prohibited from using floating-point (FP) registers or |
| 7 | +instructions, including the C float and double data types. This rule reduces |
| 8 | +system call overhead, because the kernel does not need to save and restore the |
| 9 | +userspace floating-point register state. |
| 10 | + |
| 11 | +However, occasionally drivers or library functions may need to include FP code. |
| 12 | +This is supported by isolating the functions containing FP code to a separate |
| 13 | +translation unit (a separate source file), and saving/restoring the FP register |
| 14 | +state around calls to those functions. This creates "critical sections" of |
| 15 | +floating-point usage. |
| 16 | + |
| 17 | +The reason for this isolation is to prevent the compiler from generating code |
| 18 | +touching the FP registers outside these critical sections. Compilers sometimes |
| 19 | +use FP registers to optimize inlined ``memcpy`` or variable assignment, as |
| 20 | +floating-point registers may be wider than general-purpose registers. |
| 21 | + |
| 22 | +Usability of floating-point code within the kernel is architecture-specific. |
| 23 | +Additionally, because a single kernel may be configured to support platforms |
| 24 | +both with and without a floating-point unit, FPU availability must be checked |
| 25 | +both at build time and at run time. |
| 26 | + |
| 27 | +Several architectures implement the generic kernel floating-point API from |
| 28 | +``linux/fpu.h``, as described below. Some other architectures implement their |
| 29 | +own unique APIs, which are documented separately. |
| 30 | + |
| 31 | +Build-time API |
| 32 | +-------------- |
| 33 | + |
| 34 | +Floating-point code may be built if the option ``ARCH_HAS_KERNEL_FPU_SUPPORT`` |
| 35 | +is enabled. For C code, such code must be placed in a separate file, and that |
| 36 | +file must have its compilation flags adjusted using the following pattern:: |
| 37 | + |
| 38 | + CFLAGS_foo.o += $(CC_FLAGS_FPU) |
| 39 | + CFLAGS_REMOVE_foo.o += $(CC_FLAGS_NO_FPU) |
| 40 | + |
| 41 | +Architectures are expected to define one or both of these variables in their |
| 42 | +top-level Makefile as needed. For example:: |
| 43 | + |
| 44 | + CC_FLAGS_FPU := -mhard-float |
| 45 | + |
| 46 | +or:: |
| 47 | + |
| 48 | + CC_FLAGS_NO_FPU := -msoft-float |
| 49 | + |
| 50 | +Normal kernel code is assumed to use the equivalent of ``CC_FLAGS_NO_FPU``. |
| 51 | + |
| 52 | +Runtime API |
| 53 | +----------- |
| 54 | + |
| 55 | +The runtime API is provided in ``linux/fpu.h``. This header cannot be included |
| 56 | +from files implementing FP code (those with their compilation flags adjusted as |
| 57 | +above). Instead, it must be included when defining the FP critical sections. |
| 58 | + |
| 59 | +.. c:function:: bool kernel_fpu_available( void ) |
| 60 | +
|
| 61 | + This function reports if floating-point code can be used on this CPU or |
| 62 | + platform. The value returned by this function is not expected to change |
| 63 | + at runtime, so it only needs to be called once, not before every |
| 64 | + critical section. |
| 65 | +
|
| 66 | +.. c:function:: void kernel_fpu_begin( void ) |
| 67 | + void kernel_fpu_end( void ) |
| 68 | +
|
| 69 | + These functions create a floating-point critical section. It is only |
| 70 | + valid to call ``kernel_fpu_begin()`` after a previous call to |
| 71 | + ``kernel_fpu_available()`` returned ``true``. These functions are only |
| 72 | + guaranteed to be callable from (preemptible or non-preemptible) process |
| 73 | + context. |
| 74 | +
|
| 75 | + Preemption may be disabled inside critical sections, so their size |
| 76 | + should be minimized. They are *not* required to be reentrant. If the |
| 77 | + caller expects to nest critical sections, it must implement its own |
| 78 | + reference counting. |
0 commit comments