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