add the SSE support
=> context switch stores also the SSE registers
This commit is contained in:
parent
b5066036ab
commit
cdd16a2b9f
5 changed files with 99 additions and 7 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue