| .. SPDX-License-Identifier: GPL-2.0+ |
| |
| Floating-point API |
| ================== |
| |
| Kernel code is normally prohibited from using floating-point (FP) registers or |
| instructions, including the C float and double data types. This rule reduces |
| system call overhead, because the kernel does not need to save and restore the |
| userspace floating-point register state. |
| |
| However, occasionally drivers or library functions may need to include FP code. |
| This is supported by isolating the functions containing FP code to a separate |
| translation unit (a separate source file), and saving/restoring the FP register |
| state around calls to those functions. This creates "critical sections" of |
| floating-point usage. |
| |
| The reason for this isolation is to prevent the compiler from generating code |
| touching the FP registers outside these critical sections. Compilers sometimes |
| use FP registers to optimize inlined ``memcpy`` or variable assignment, as |
| floating-point registers may be wider than general-purpose registers. |
| |
| Usability of floating-point code within the kernel is architecture-specific. |
| Additionally, because a single kernel may be configured to support platforms |
| both with and without a floating-point unit, FPU availability must be checked |
| both at build time and at run time. |
| |
| Several architectures implement the generic kernel floating-point API from |
| ``linux/fpu.h``, as described below. Some other architectures implement their |
| own unique APIs, which are documented separately. |
| |
| Build-time API |
| -------------- |
| |
| Floating-point code may be built if the option ``ARCH_HAS_KERNEL_FPU_SUPPORT`` |
| is enabled. For C code, such code must be placed in a separate file, and that |
| file must have its compilation flags adjusted using the following pattern:: |
| |
| CFLAGS_foo.o += $(CC_FLAGS_FPU) |
| CFLAGS_REMOVE_foo.o += $(CC_FLAGS_NO_FPU) |
| |
| Architectures are expected to define one or both of these variables in their |
| top-level Makefile as needed. For example:: |
| |
| CC_FLAGS_FPU := -mhard-float |
| |
| or:: |
| |
| CC_FLAGS_NO_FPU := -msoft-float |
| |
| Normal kernel code is assumed to use the equivalent of ``CC_FLAGS_NO_FPU``. |
| |
| Runtime API |
| ----------- |
| |
| The runtime API is provided in ``linux/fpu.h``. This header cannot be included |
| from files implementing FP code (those with their compilation flags adjusted as |
| above). Instead, it must be included when defining the FP critical sections. |
| |
| .. c:function:: bool kernel_fpu_available( void ) |
| |
| This function reports if floating-point code can be used on this CPU or |
| platform. The value returned by this function is not expected to change |
| at runtime, so it only needs to be called once, not before every |
| critical section. |
| |
| .. c:function:: void kernel_fpu_begin( void ) |
| void kernel_fpu_end( void ) |
| |
| These functions create a floating-point critical section. It is only |
| valid to call ``kernel_fpu_begin()`` after a previous call to |
| ``kernel_fpu_available()`` returned ``true``. These functions are only |
| guaranteed to be callable from (preemptible or non-preemptible) process |
| context. |
| |
| Preemption may be disabled inside critical sections, so their size |
| should be minimized. They are *not* required to be reentrant. If the |
| caller expects to nest critical sections, it must implement its own |
| reference counting. |