mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
79 lines
3.3 KiB
ReStructuredText
79 lines
3.3 KiB
ReStructuredText
|
.. 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.
|