1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

x86: fix FPU lazy swap

The ucontext->x86_fxsave is initialize as 512 bytes of zeros, but it
is not a valid value to be set onto FPU registers, causing a General
Protection Fault:

Interrupt 0x0d (General Protection Fault) while handling 0x07 (Device not available)
EAX=0012f4c0  ECX=001336e4  EDX=001334ac  EBX=001336e0
ESP=00123784  EBP=001237c8  ESI=00000200  EDI=00000000
Error code=00000000
CR0=80010031  CR2=00000000  CR3=0012d000  CR4=000001e0
EIP=0000:80010031  EFLAGS=0012d000
<stack trace>
00000000
???
</stack trace>
Halting.

So lets copy the initial state of FPU registers before FPU is used
and set it as the initial state of FPU to new threads(coroutine).
This commit is contained in:
José Roberto de Souza 2015-01-30 13:37:00 -02:00
parent 56f5a836a8
commit 684b081a16

View File

@ -55,6 +55,8 @@ static kernel_pid_t fpu_owner = KERNEL_PID_UNDEF;
//static ucontext_t *cur_ctx, *isr_ctx;
static struct x86_fxsave initial_fpu_state;
int inISR(void)
{
return x86_in_isr;
@ -169,6 +171,7 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_sta
p->uc_stack.ss_size = stacksize;
p->uc_link = &end_context;
p->uc_context.flags |= X86_IF;
p->__fxsave = initial_fpu_state;
makecontext(p, (makecontext_fun_t) task_func, 1, arg);
return (char *) p;
@ -218,6 +221,7 @@ void x86_init_threading(void)
makecontext(&end_context, x86_thread_exit, 0);
x86_interrupt_handler_set(X86_INT_NM, fpu_used_interrupt);
asm volatile ("fxsave (%0)" :: "r"(&initial_fpu_state));
DEBUG("Threading initialized\n");
}