add the SSE support

=> context switch stores also the SSE registers
This commit is contained in:
Stefan Lankes 2011-05-28 23:35:46 +02:00
parent b5066036ab
commit cdd16a2b9f
5 changed files with 99 additions and 7 deletions

View file

@ -39,6 +39,45 @@
extern "C" {
#endif
// feature list 1
#define CPU_FEATURE_FPU (1 << 0)
#define CPU_FEATURE_MMX (1 << 23)
#define CPU_FEATURE_FXSR (1 << 24)
#define CPU_FEATURE_SSE (1 << 25)
#define CPU_FEATURE_SSE2 (1 << 26)
// feature list 2
#define CPU_FEATURE_AVX (1 << 28)
typedef struct {
uint32_t feature1, feature2;
} cpu_info_t;
extern cpu_info_t cpu_info;
// determine the cpu features
int cpu_detection(void);
inline static uint32_t has_fpu(void)
{
return (cpu_info.feature1 & CPU_FEATURE_FPU);
}
inline static uint32_t has_fxsr(void)
{
return (cpu_info.feature1 & CPU_FEATURE_FXSR);
}
inline static uint32_t has_xmm(void)
{
return (cpu_info.feature1 & CPU_FEATURE_SSE);
}
inline static uint32_t has_avx(void)
{
return (cpu_info.feature2 & CPU_FEATURE_AVX);
}
/** @brief Read out time stamp counter
*
* The rdtsc asm command puts a 64 bit time stamp value
@ -250,6 +289,8 @@ inline static int system_init(void)
#ifdef CONFIG_PCI
pci_init();
#endif
cpu_detection();
return 0;
}

View file

@ -22,6 +22,7 @@
#define __ARCH_TASKS_TYPES__
#include <metalsvm/stddef.h>
#include <asm/processor.h>
#ifdef __cplusplus
extern "C" {
@ -61,7 +62,10 @@ union fpu_state {
};
static inline void save_fpu_state(union fpu_state* state) {
asm volatile ("fsave %0; fwait" : "=m"((*state).fsave));
if (has_fxsr())
asm volatile ("fxsave %0; fnclex" : "=m"((*state).fxsave));
else
asm volatile ("fsave %0; fwait" : "=m"((*state).fsave));
}
#ifdef __cplusplus

View file

@ -165,6 +165,26 @@ 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, 0, sizeof(union fpu_state));
fx->cwd = 0x37f;
if (has_xmm)
fx->mxcsr = 0x1f80;
} else {
i387_fsave_t *fp = &fpu->fsave;
memset(fp, 0, sizeof(union fpu_state));
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);
@ -172,13 +192,16 @@ static void fpu_handler(struct state *s)
asm volatile ("clts"); // clear the TS flag of cr0
if (!(task->flags & TASK_FPU_INIT)) {
// use the FPU at the first time => Initialize FPU
asm volatile ("finit");
task->flags = task->flags|TASK_FPU_INIT|TASK_FPU_USED;
} else {
// restore the FPU context
asm volatile ("frstor %0" :: "m"(task->fpu.fsave)); // restore fpu state
task->flags |= TASK_FPU_USED;
fpu_init(&task->fpu);
task->flags |= TASK_FPU_INIT;
}
// restore the FPU context
if (has_fxsr())
asm volatile ("fxrstor %0" :: "m"(task->fpu.fxsave));
else
asm volatile ("frstor %0" :: "m"(task->fpu.fsave));
task->flags |= TASK_FPU_USED;
}
/** @brief Exception messages

View file

@ -25,8 +25,31 @@
#include <asm/RCCE_lib.h>
#endif
cpu_info_t cpu_info = { 0, 0 };
static uint32_t cpu_freq = 0;
int cpu_detection(void)
{
uint32_t a, b, cr4;
cpuid(1, &a, &b, &cpu_info.feature2, &cpu_info.feature1);
cr4 = read_cr4();
if (has_fxsr())
cr4 |= 0x200; // set the OSFXSR bit
if (has_xmm())
cr4 |= 0x400; // set the OSXMMEXCPT bit
write_cr4(cr4);
if (has_avx())
kprintf("The CPU owns the Advanced Vector Extensions (AVX). However, MetalSVM doesn't support AVX!\n");
if (has_fpu())
asm volatile ("fninit");
return 0;
}
uint32_t detect_cpu_frequency(void)
{
#ifdef CONFIG_ROCKCREEK

View file

@ -133,6 +133,7 @@ int test_init(void)
//create_user_task(NULL, "/bin/hello", argv);
create_user_task(NULL, "/bin/tests", argv);
//create_user_task(NULL, "/bin/jacobi", argv);
//create_user_task(NULL, "/bin/jacobi", argv);
return 0;
}