Hi,
As once discussed with Heikki, and after a first missed attempt, here is a patch for x86 which attempts to cope correctly with Linux (non real-time) drivers using FPU in kernel-space. I tested it on my laptop without drivers using FPU, and it appears to work correctly, but it would be nice if people that had problems with the previous attempt (if I remember correctly, on old pentiums and on AMD processors) could test this patch. Thanks in advance. -- Gilles Chanteperdrix
Index: include/asm-i386/system.h =================================================================== --- include/asm-i386/system.h (revision 1704) +++ include/asm-i386/system.h (working copy) @@ -69,6 +69,7 @@ /* FPU context bits for root thread. */ unsigned is_root: 1; unsigned ts_usedfpu: 1; + unsigned cr0_ts: 1; } xnarchtcb_t; Index: include/asm-i386/bits/pod.h =================================================================== --- include/asm-i386/bits/pod.h (revision 1704) +++ include/asm-i386/bits/pod.h (working copy) @@ -44,6 +44,7 @@ /* Remember the preempted Linux task pointer. */ rootcb->user_task = rootcb->active_task = current; rootcb->ts_usedfpu = wrap_test_fpu_used(current) != 0; + rootcb->cr0_ts = (read_cr0() & 8) != 0; /* So that xnarch_save_fpu() will operate on the right FPU area. */ rootcb->fpup = &rootcb->user_task->thread.i387; } @@ -265,12 +266,21 @@ { struct task_struct *task = tcb->user_task; - if (task) { - if (!wrap_test_fpu_used(task)) + if (!tcb->is_root) { + if (task) { + /* fpu not used or already saved by __switch_to. */ + if (!wrap_test_fpu_used(task)) + return; + + /* Tell Linux that we already saved the state of the FPU + hardware of this task. */ + wrap_clear_fpu_used(task); + } + } else { + if (tcb->cr0_ts || + (tcb->ts_usedfpu && !wrap_test_fpu_used(task))) return; - /* Tell Linux that we already saved the state of the FPU - hardware of this task. */ wrap_clear_fpu_used(task); } @@ -298,13 +308,14 @@ wrap_set_fpu_used(task); } } else { - /* Restore state of FPU if TS_USEFPU bit was armed. */ - if (!tcb->ts_usedfpu) { + /* Restore state of FPU only if TS bit in cr0 was clear. */ + if (tcb->cr0_ts) { stts(); return; } - wrap_set_fpu_used(task); + if (tcb->ts_usedfpu) + wrap_set_fpu_used(task); } /* Restore the FPU hardware with valid fp registers from a @@ -336,7 +347,7 @@ } } } else { - if (!tcb->ts_usedfpu) + if (tcb->cr0_ts) return; xnarch_restore_fpu(tcb);
_______________________________________________ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core