Module: xenomai-gch Branch: for-forge Commit: e687de2525f651c8fac2c4a00916e2ed67da25db URL: http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=e687de2525f651c8fac2c4a00916e2ed67da25db
Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org> Date: Sun Sep 29 22:43:03 2013 +0200 x86: handle preemption in kernel_fpu_begin/kernel_fpu_end section --- .../cobalt/arch/x86/include/asm/xenomai/thread.h | 2 + kernel/cobalt/arch/x86/thread.c | 42 +++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h index 3e0e8be..5d4c7ca 100644 --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h @@ -36,6 +36,8 @@ struct xnarchtcb { unsigned long *ipp; x86_fpustate *fpup; unsigned int is_root: 1; + unsigned int root_kfpu: 1; + unsigned int root_used_math: 1; struct { unsigned long ip; unsigned long ax; diff --git a/kernel/cobalt/arch/x86/thread.c b/kernel/cobalt/arch/x86/thread.c index dc7e5fa..e66cb72 100644 --- a/kernel/cobalt/arch/x86/thread.c +++ b/kernel/cobalt/arch/x86/thread.c @@ -83,17 +83,6 @@ static inline void do_switch_threads(struct xnarchtcb *out_tcb, #endif /* CONFIG_X86_64 */ -void xnarch_leave_root(struct xnarchtcb *rootcb) -{ - struct task_struct *p = current; - -#ifdef CONFIG_X86_64 - rootcb->spp = &p->thread.sp; - rootcb->ipp = &p->thread.rip; -#endif - rootcb->fpup = x86_fpustate_ptr(&p->thread); -} - void xnarch_switch_to(struct xnarchtcb *out_tcb, struct xnarchtcb *in_tcb) { unsigned long __maybe_unused fs, gs; @@ -255,6 +244,25 @@ int xnarch_handle_fpu_fault(struct xnarchtcb *tcb) return 1; } +void xnarch_leave_root(struct xnarchtcb *rootcb) +{ + struct task_struct *p = current; + +#ifdef CONFIG_X86_64 + rootcb->spp = &p->thread.sp; + rootcb->ipp = &p->thread.rip; +#endif + rootcb->fpup = x86_fpustate_ptr(&p->thread); + rootcb->root_kfpu = + (read_cr0() & 8) == 0 && wrap_test_fpu_used(p) == 0; + if (rootcb->root_kfpu) { + rootcb->root_used_math = tsk_used_math(p) != 0; + memcpy(&rootcb->i387, rootcb->fpup, xstate_size); + wrap_set_fpu_used(p); + set_stopped_child_used_math(p); + } +} + void xnarch_save_fpu(struct xnarchtcb *tcb) { /* Already saved by __switch_to */ @@ -264,7 +272,7 @@ void xnarch_restore_fpu(struct xnarchtcb *tcb) { struct task_struct *p = tcb->core.host_task; - if (tcb->is_root || tsk_used_math(p) == 0) + if (tcb->root_kfpu == 0 && (tsk_used_math(p) == 0 || tcb->is_root)) /* Restore lazy mode */ return; @@ -275,7 +283,13 @@ void xnarch_restore_fpu(struct xnarchtcb *tcb) clts(); __do_restore_i387(tcb->fpup); - wrap_set_fpu_used(p); + if (tcb->root_kfpu) { + memcpy(tcb->fpup, &tcb->i387, xstate_size); + wrap_clear_fpu_used(p); + if (tcb->root_used_math == 0) + clear_stopped_child_used_math(p); + } else + wrap_set_fpu_used(p); } void xnarch_enable_fpu(struct xnarchtcb *tcb) @@ -292,6 +306,7 @@ void xnarch_init_root_tcb(struct xnarchtcb *tcb) tcb->ipp = &tcb->ip; tcb->is_root = 1; tcb->fpup = NULL; + tcb->root_kfpu = 0; } void xnarch_init_shadow_tcb(struct xnarchtcb *tcb) @@ -306,6 +321,7 @@ void xnarch_init_shadow_tcb(struct xnarchtcb *tcb) tcb->ipp = &p->thread.rip; /* <!> raw naming intended. */ #endif tcb->fpup = x86_fpustate_ptr(&p->thread); + tcb->root_kfpu = 0; } int xnarch_escalate(void) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git