/SPARTAN/trunk/include/fpu_context.h |
---|
10,7 → 10,7 |
extern void fpu_context_restore(fpu_context_t *); |
extern void fpu_lazy_context_save(fpu_context_t *); |
extern void fpu_lazy_context_restore(fpu_context_t *); |
extern void fpu_init(void); |
#endif /*fpu_context_h*/ |
/SPARTAN/trunk/include/proc/thread.h |
---|
74,6 → 74,9 |
context_t saved_context; |
context_t sleep_timeout_context; |
fpu_context_t saved_fpu_context; |
int fpu_context_exists; |
int fpu_context_engaged; /* Defined only if thread doesn't run. It means that fpu context is in CPU |
that last time executes this thread. This disables migration */ |
waitq_t *sleep_queue; |
/SPARTAN/trunk/doc/TODO |
---|
11,6 → 11,7 |
+ save/restore floating point context on context switch |
+ [ia32] lazy context switch using TS flag |
+ [ia32] MMX,SSE1-.. initialization |
+ [ia32] review privilege separation |
+ zero IOPL in EFLAGS |
+ before IRET (from SYSCALL), zero NT in EFLAGS |
18,3 → 19,5 |
+ [ia32] zero the alignment exception bit in EFLAGS |
+ make emulated architectures also work on real hardware |
+ bring in support for other architectures (e.g. PowerPC) |
/SPARTAN/trunk/src/proc/scheduler.c |
---|
267,6 → 267,11 |
spinlock_lock(&threads_lock); |
list_remove(&THREAD->threads_link); |
spinlock_unlock(&threads_lock); |
spinlock_lock(&THREAD->cpu->lock); |
if(THREAD->cpu->arch.fpu_owner==THREAD) THREAD->cpu->arch.fpu_owner=NULL; |
spinlock_unlock(&THREAD->cpu->lock); |
free(THREAD); |
427,9 → 432,10 |
/* |
* We don't want to steal CPU-wired threads neither threads already stolen. |
* The latter prevents threads from migrating between CPU's without ever being run. |
*/ |
* We don't want to steal threads whose FPU context is still in CPU |
*/ |
spinlock_lock(&t->lock); |
if (!(t->flags & (X_WIRED | X_STOLEN))) { |
if ( (!(t->flags & (X_WIRED | X_STOLEN))) && (!(t->fpu_context_engaged)) ) { |
/* |
* Remove t from r. |
*/ |
/SPARTAN/trunk/src/proc/thread.c |
---|
189,6 → 189,9 |
t->task = task; |
t->fpu_context_exists=0; |
t->fpu_context_engaged=0; |
/* |
* Register this thread in the system-wide list. |
*/ |
/SPARTAN/trunk/arch/ia32/include/interrupt.h |
---|
76,6 → 76,7 |
extern void null_interrupt(__u8 n, __u32 stack[]); |
extern void gp_fault(__u8 n, __u32 stack[]); |
extern void nm_fault(__u8 n, __u32 stack[]); |
extern void page_fault(__u8 n, __u32 stack[]); |
extern void syscall(__u8 n, __u32 stack[]); |
extern void tlb_shootdown_ipi(__u8 n, __u32 stack[]); |
/SPARTAN/trunk/arch/ia32/src/fpu_context.c |
---|
40,29 → 40,39 |
void fpu_context_restore(fpu_context_t *fctx) |
{ |
if(THREAD==CPU->arch.fpu_owner) reset_TS_flag(); |
else set_TS_flag(); |
if(THREAD==CPU->arch.fpu_owner) {reset_TS_flag(); } |
else {set_TS_flag(); ((CPU->arch).fpu_owner)->fpu_context_engaged=1;} |
} |
void fpu_lazy_context_save(fpu_context_t *fctx) |
{ |
/* |
pushl %eax |
mov 8(%esp),%eax |
fxsave (%eax) |
popl %eax |
ret |
*/ |
asm( |
"mov %0,%%eax;" |
"fxsave (%%eax);" |
"ret;" |
:"=m"(fctx) |
: |
:"%eax" |
); |
} |
void fpu_lazy_context_restore(fpu_context_t *fctx) |
{ |
/* |
pushl %eax |
mov 8(%esp),%eax |
fxrstor (%eax) |
popl %eax |
ret |
*/ |
asm( |
"mov %0,%%eax;" |
"fxrstor (%%eax);" |
"ret;" |
:"=m"(fctx) |
: |
:"%eax" |
); |
} |
void fpu_init(void) |
{ |
asm( |
"fninit;" |
); |
} |
/SPARTAN/trunk/arch/ia32/src/pm.c |
---|
120,6 → 120,7 |
trap_register(i, null_interrupt); |
} |
trap_register(13, gp_fault); |
trap_register( 7, nm_fault); |
} |
/SPARTAN/trunk/arch/ia32/src/interrupt.c |
---|
85,6 → 85,27 |
panic("general protection fault\n"); |
} |
void nm_fault(__u8 n, __u32 stack[]) |
{ |
if (((CPU->arch).fpu_owner)!=NULL) |
{ |
fpu_lazy_context_save(&(((CPU->arch).fpu_owner)->saved_fpu_context)); |
((CPU->arch).fpu_owner)->fpu_context_engaged=0; /* Enables migration */ |
} |
if(THREAD->fpu_context_exists) fpu_lazy_context_restore(&(THREAD->saved_fpu_context)); |
else {fpu_init();THREAD->fpu_context_exists=1;} |
(CPU->arch).fpu_owner=THREAD; |
reset_TS_flag(); |
// panic("#NM fault\n"); |
} |
void page_fault(__u8 n, __u32 stack[]) |
{ |
printf("page fault address: %X\n", cpu_read_cr2()); |