| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- .. 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.
|