AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
fpu.c File Reference

x86: the FPU and SSE registers, switched lazily between threads. More...

#include <core/system.h>
#include <core/panic.h>
#include <core/assert.h>
#include <core/arch.h>
#include <core/string.h>
#include <cpu/cpu.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/signal.h>

Go to the source code of this file.

Macros

#define CPUID_EDX_FXSR   _BV(24)
#define CPUID_EDX_SSE   _BV(25)
#define last_fpu_thread   (curcpu()->arch.fpu_thread)

Functions

void x86_fpu_setup (void)
 Sets up the FPU on the running CPU, at boot: CR0.TS set so that the first FPU or SSE instruction raises #NM (x86_fpu_trap()), SSE turned on if the CPU has it, and the clean starting state recorded.
void x86_fpu_enable (void)
 Lets the running CPU use the FPU without trapping (clears CR0.TS).
void x86_fpu_disable (void)
 Makes the next FPU instruction trap (sets CR0.TS).
void x86_fpu_init (void)
 Loads the clean starting state into the FPU, for a thread's first use of it.
static void fpu_save (void)
 Saves the FPU's state into fpu_context.
static void fpu_restore (void)
 Loads the FPU's state from fpu_context.
void x86_fpu_trap (void)
 Handles #NM, the current thread's first FPU or SSE instruction since it was switched in: it saves the previous owner's state, and gives the FPU to this thread, with its own state or a clean one.
void x86_fpu_switch_out (void)
 Saves the current thread's FPU state when it is switched out, if the FPU holds it, because the thread may run on another CPU next.
int x86_fpu_save_to (void *buf)
 Copies the current thread's FPU state, for a signal handler's frame (sys/signal.c).
void x86_fpu_reset (void)
 Makes the current thread start with a clean FPU state at its next use of the FPU, as a signal handler does.
void x86_fpu_load_from (const void *buf, int valid)
 Gives the current thread back the FPU state saved in a signal frame, at sigreturn.

Variables

static char fpu_context [512]
static int fpu_fxsr = 0
static uint32_t mxcsr_mask = 0xFFBF
static char fpu_clean [512]

Detailed Description

x86: the FPU and SSE registers, switched lazily between threads.

Saving and restoring the FPU's 512 bytes on every thread switch would be costly, and most threads never use it. So the switch only sets CR0.TS; the first FPU or SSE instruction a thread runs afterwards raises #NM, and x86_fpu_trap() saves the previous owner's state and loads this thread's. A thread that never touches the FPU never pays for it.

Definition in file fpu.c.

Macro Definition Documentation

◆ CPUID_EDX_FXSR

#define CPUID_EDX_FXSR   _BV(24)

Definition at line 24 of file fpu.c.

Referenced by x86_fpu_setup().

◆ CPUID_EDX_SSE

#define CPUID_EDX_SSE   _BV(25)

Definition at line 25 of file fpu.c.

Referenced by x86_fpu_setup().

◆ last_fpu_thread

#define last_fpu_thread   (curcpu()->arch.fpu_thread)

Definition at line 32 of file fpu.c.

Referenced by x86_fpu_reset(), x86_fpu_save_to(), x86_fpu_switch_out(), and x86_fpu_trap().

Function Documentation

◆ fpu_restore()

void fpu_restore ( void )
inlinestatic

Loads the FPU's state from fpu_context.

Definition at line 117 of file fpu.c.

References fpu_context, fpu_fxsr, and fpu_restore().

Referenced by fpu_restore(), and x86_fpu_trap().

◆ fpu_save()

void fpu_save ( void )
inlinestatic

Saves the FPU's state into fpu_context.

Definition at line 108 of file fpu.c.

References fpu_context, fpu_fxsr, and fpu_save().

Referenced by fpu_save(), x86_fpu_save_to(), x86_fpu_switch_out(), and x86_fpu_trap().

◆ x86_fpu_disable()

void x86_fpu_disable ( void )

Makes the next FPU instruction trap (sets CR0.TS).

Definition at line 88 of file fpu.c.

References CR0_TS, and x86_fpu_disable().

Referenced by arch_thread_spawn(), arch_thread_switch(), x86_fpu_disable(), x86_fpu_reset(), and x86_fpu_setup().

◆ x86_fpu_enable()

void x86_fpu_enable ( void )

Lets the running CPU use the FPU without trapping (clears CR0.TS).

Definition at line 82 of file fpu.c.

References x86_fpu_enable().

Referenced by x86_fpu_enable(), x86_fpu_save_to(), x86_fpu_setup(), x86_fpu_switch_out(), and x86_fpu_trap().

◆ x86_fpu_init()

void x86_fpu_init ( void )

Loads the clean starting state into the FPU, for a thread's first use of it.

Definition at line 95 of file fpu.c.

References assert_alignof, fpu_clean, fpu_context, fpu_fxsr, memcpy(), and x86_fpu_init().

Referenced by x86_fpu_init(), and x86_fpu_trap().

◆ x86_fpu_load_from()

void x86_fpu_load_from ( const void * buf,
int valid )

Gives the current thread back the FPU state saved in a signal frame, at sigreturn.

It is loaded at the thread's next use of the FPU, with the MXCSR bits the CPU doesn't accept cleared.

Parameters
bufthe saved state: 512 bytes
validwhether the frame has a state (the thread had used the FPU); if not, the thread starts afresh

Definition at line 239 of file fpu.c.

References curthread, x86_thread::fpu_context, x86_thread::fpu_enabled, fpu_fxsr, kmalloc(), memcpy(), mxcsr_mask, x86_fpu_load_from(), and x86_fpu_reset().

Referenced by arch_sigreturn(), and x86_fpu_load_from().

◆ x86_fpu_reset()

void x86_fpu_reset ( void )

Makes the current thread start with a clean FPU state at its next use of the FPU, as a signal handler does.

Definition at line 218 of file fpu.c.

References curthread, x86_thread::fpu_enabled, last_fpu_thread, NULL, x86_fpu_disable(), and x86_fpu_reset().

Referenced by deliver(), x86_fpu_load_from(), and x86_fpu_reset().

◆ x86_fpu_save_to()

int x86_fpu_save_to ( void * buf)

Copies the current thread's FPU state, for a signal handler's frame (sys/signal.c).

Parameters
bufwhere to copy it: 512 bytes, 16-byte aligned
Returns
1 if the state was copied, or 0 if the thread never used the FPU

Definition at line 198 of file fpu.c.

References curthread, fpu_context, x86_thread::fpu_context, x86_thread::fpu_enabled, fpu_save(), last_fpu_thread, memcpy(), x86_fpu_enable(), and x86_fpu_save_to().

Referenced by arch_proc_fork(), deliver(), and x86_fpu_save_to().

◆ x86_fpu_setup()

void x86_fpu_setup ( void )

Sets up the FPU on the running CPU, at boot: CR0.TS set so that the first FPU or SSE instruction raises #NM (x86_fpu_trap()), SSE turned on if the CPU has it, and the clean starting state recorded.

CR0.EM must stay clear, or SSE instructions would raise #UD instead.

Definition at line 50 of file fpu.c.

References CPUID_EDX_FXSR, CPUID_EDX_SSE, CR0_EM, CR0_MP, CR0_NE, CR0_TS, CR4_OSFXSR, CR4_OSXMMEXCPT, fpu_clean, fpu_fxsr, memset(), mxcsr_mask, read_cr4(), write_cr4(), x86_fpu_disable(), x86_fpu_enable(), and x86_fpu_setup().

Referenced by x86_cpu_init(), and x86_fpu_setup().

◆ x86_fpu_switch_out()

void x86_fpu_switch_out ( void )

Saves the current thread's FPU state when it is switched out, if the FPU holds it, because the thread may run on another CPU next.

Afterwards, the FPU belongs to no thread.

Definition at line 178 of file fpu.c.

References curthread, fpu_context, x86_thread::fpu_context, fpu_save(), last_fpu_thread, memcpy(), NULL, x86_fpu_enable(), and x86_fpu_switch_out().

Referenced by x86_fpu_switch_out(), and x86_thread_saved().

◆ x86_fpu_trap()

void x86_fpu_trap ( void )

Handles #NM, the current thread's first FPU or SSE instruction since it was switched in: it saves the previous owner's state, and gives the FPU to this thread, with its own state or a clean one.

If there's no memory for the thread's save area, the process is killed.

Definition at line 131 of file fpu.c.

References curproc, curthread, fpu_context, x86_thread::fpu_context, x86_thread::fpu_enabled, fpu_restore(), fpu_save(), kmalloc(), last_fpu_thread, memcpy(), panic, signal_proc_send(), x86_fpu_enable(), x86_fpu_init(), and x86_fpu_trap().

Referenced by isr_dispatch(), and x86_fpu_trap().

Variable Documentation

◆ fpu_clean

char fpu_clean[512]
static

Definition at line 42 of file fpu.c.

Referenced by x86_fpu_init(), and x86_fpu_setup().

◆ fpu_context

char fpu_context[512]
static

◆ fpu_fxsr

int fpu_fxsr = 0
static

Definition at line 29 of file fpu.c.

Referenced by fpu_restore(), fpu_save(), x86_fpu_init(), x86_fpu_load_from(), and x86_fpu_setup().

◆ mxcsr_mask

uint32_t mxcsr_mask = 0xFFBF
static

Definition at line 37 of file fpu.c.

Referenced by x86_fpu_load_from(), and x86_fpu_setup().