some code cleanups

=> simplify the handling of FPU exceptions
This commit is contained in:
Stefan Lankes 2012-07-18 20:56:23 +02:00
parent dadc4ce7ed
commit 09ec6dcc3a
3 changed files with 61 additions and 35 deletions

View file

@ -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
}

View file

@ -27,13 +27,13 @@
*/
#include <metalsvm/stdio.h>
#include <metalsvm/string.h>
#include <metalsvm/tasks.h>
#include <asm/irqflags.h>
#include <asm/isrs.h>
#include <asm/irq.h>
#include <asm/apic.h>
#include <asm/idt.h>
#include <asm/io.h>
/*
* 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);

View file

@ -19,6 +19,7 @@
#include <metalsvm/stddef.h>
#include <metalsvm/stdio.h>
#include <metalsvm/string.h>
#include <metalsvm/time.h>
#include <metalsvm/processor.h>
#include <metalsvm/tasks.h>
@ -26,16 +27,64 @@
#include <asm/RCCE_lib.h>
#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;
}