diff --git a/arch/x86/include/asm/tasks_types.h b/arch/x86/include/asm/tasks_types.h index 194a0410..fa65f661 100644 --- a/arch/x86/include/asm/tasks_types.h +++ b/arch/x86/include/asm/tasks_types.h @@ -65,19 +65,11 @@ union fpu_state { i387_fxsave_t fxsave; }; -static inline void save_fpu_state(union fpu_state* state) { - if (has_fxsr()) - asm volatile ("fxsave %0; fnclex" : "=m"((*state).fxsave) :: "memory"); - else - asm volatile ("fnsave %0; fwait" : "=m"((*state).fsave) :: "memory"); -} +typedef void (*handle_fpu_state)(union fpu_state* state); -static inline void restore_fpu_state(union fpu_state* state) { - if (has_fxsr()) - asm volatile ("fxrstor %0" :: "m"(state->fxsave)); - else - asm volatile ("frstor %0" :: "m"(state->fsave)); -} +extern handle_fpu_state save_fpu_state; +extern handle_fpu_state restore_fpu_state; +extern handle_fpu_state fpu_init; #ifdef __cplusplus } diff --git a/arch/x86/kernel/isrs.c b/arch/x86/kernel/isrs.c index 69c59c79..7aa20962 100644 --- a/arch/x86/kernel/isrs.c +++ b/arch/x86/kernel/isrs.c @@ -27,13 +27,13 @@ */ #include -#include #include #include #include #include #include #include +#include /* * These are function prototypes for all of the exception @@ -165,27 +165,6 @@ void isrs_install(void) irq_install_handler(7, fpu_handler); } -static void fpu_init(union fpu_state* fpu) -{ - if (has_fxsr()) { - i387_fxsave_t* fx = &fpu->fxsave; - - memset(fx, 0x00, sizeof(i387_fxsave_t)); - fx->cwd = 0x37f; - if (has_sse()) - fx->mxcsr = 0x1f80; - } else { - i387_fsave_t *fp = &fpu->fsave; - - memset(fp, 0x00, sizeof(i387_fsave_t)); - fp->cwd = 0xffff037fu; - fp->swd = 0xffff0000u; - fp->twd = 0xffffffffu; - fp->fos = 0xffff0000u; - } - -} - static void fpu_handler(struct state *s) { task_t* task = per_core(current_task); diff --git a/arch/x86/kernel/processor.c b/arch/x86/kernel/processor.c index c2c90106..7f6078f3 100644 --- a/arch/x86/kernel/processor.c +++ b/arch/x86/kernel/processor.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -26,16 +27,64 @@ #include #endif -static void default_mb(void) { asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); } +static void default_mb(void) +{ + asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); +} + +static void default_save_fpu_state(union fpu_state* state) +{ + asm volatile ("fnsave %0; fwait" : "=m"((*state).fsave) :: "memory"); +} + +static void default_restore_fpu_state(union fpu_state* state) +{ + asm volatile ("frstor %0" :: "m"(state->fsave)); +} + +static void default_fpu_init(union fpu_state* fpu) +{ + i387_fsave_t *fp = &fpu->fsave; + + memset(fp, 0x00, sizeof(i387_fsave_t)); + fp->cwd = 0xffff037fu; + fp->swd = 0xffff0000u; + fp->twd = 0xffffffffu; + fp->fos = 0xffff0000u; +} + func_memory_barrier mb = default_mb; func_memory_barrier rmb = default_mb; func_memory_barrier wmb = default_mb; +handle_fpu_state save_fpu_state = default_save_fpu_state; +handle_fpu_state restore_fpu_state = default_restore_fpu_state; +handle_fpu_state fpu_init = default_fpu_init; static void mfence(void) { asm volatile("mfence" ::: "memory"); } static void lfence(void) { asm volatile("lfence" ::: "memory"); } static void sfence(void) { asm volatile("sfence" ::: "memory"); } +static void save_fpu_state_fxsr(union fpu_state* state) +{ + asm volatile ("fxsave %0; fnclex" : "=m"((*state).fxsave) :: "memory"); +} + +static void restore_fpu_state_fxsr(union fpu_state* state) +{ + asm volatile ("fxrstor %0" :: "m"(state->fxsave)); +} + +static void fpu_init_fxsr(union fpu_state* fpu) +{ + i387_fxsave_t* fx = &fpu->fxsave; + + memset(fx, 0x00, sizeof(i387_fxsave_t)); + fx->cwd = 0x37f; + if (BUILTIN_EXPECT(has_sse(), 1)) + fx->mxcsr = 0x1f80; +} + cpu_info_t cpu_info = { 0, 0 }; static uint32_t cpu_freq = 0; @@ -72,6 +121,12 @@ int cpu_detection(void) asm volatile ("fninit"); } + if (has_fxsr()) { + save_fpu_state = save_fpu_state_fxsr; + restore_fpu_state = restore_fpu_state_fxsr; + fpu_init = fpu_init_fxsr; + } + return 0; }