Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.18 104 lines 2.7 kB view raw
1/* 2 * Copyright (C) 1994 Linus Torvalds 3 * 4 * Pentium III FXSR, SSE support 5 * General FPU state handling cleanups 6 * Gareth Hughes <gareth@valinux.com>, May 2000 7 * x86-64 work by Andi Kleen 2002 8 */ 9 10#ifndef _ASM_X86_I387_H 11#define _ASM_X86_I387_H 12 13#ifndef __ASSEMBLY__ 14 15#include <linux/sched.h> 16#include <linux/hardirq.h> 17 18struct pt_regs; 19struct user_i387_struct; 20 21extern int init_fpu(struct task_struct *child); 22extern void fpu_finit(struct fpu *fpu); 23extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); 24extern void math_state_restore(void); 25 26extern bool irq_fpu_usable(void); 27 28/* 29 * Careful: __kernel_fpu_begin/end() must be called with preempt disabled 30 * and they don't touch the preempt state on their own. 31 * If you enable preemption after __kernel_fpu_begin(), preempt notifier 32 * should call the __kernel_fpu_end() to prevent the kernel/user FPU 33 * state from getting corrupted. KVM for example uses this model. 34 * 35 * All other cases use kernel_fpu_begin/end() which disable preemption 36 * during kernel FPU usage. 37 */ 38extern void __kernel_fpu_begin(void); 39extern void __kernel_fpu_end(void); 40 41static inline void kernel_fpu_begin(void) 42{ 43 WARN_ON_ONCE(!irq_fpu_usable()); 44 preempt_disable(); 45 __kernel_fpu_begin(); 46} 47 48static inline void kernel_fpu_end(void) 49{ 50 __kernel_fpu_end(); 51 preempt_enable(); 52} 53 54/* 55 * Some instructions like VIA's padlock instructions generate a spurious 56 * DNA fault but don't modify SSE registers. And these instructions 57 * get used from interrupt context as well. To prevent these kernel instructions 58 * in interrupt context interacting wrongly with other user/kernel fpu usage, we 59 * should use them only in the context of irq_ts_save/restore() 60 */ 61static inline int irq_ts_save(void) 62{ 63 /* 64 * If in process context and not atomic, we can take a spurious DNA fault. 65 * Otherwise, doing clts() in process context requires disabling preemption 66 * or some heavy lifting like kernel_fpu_begin() 67 */ 68 if (!in_atomic()) 69 return 0; 70 71 if (read_cr0() & X86_CR0_TS) { 72 clts(); 73 return 1; 74 } 75 76 return 0; 77} 78 79static inline void irq_ts_restore(int TS_state) 80{ 81 if (TS_state) 82 stts(); 83} 84 85/* 86 * The question "does this thread have fpu access?" 87 * is slightly racy, since preemption could come in 88 * and revoke it immediately after the test. 89 * 90 * However, even in that very unlikely scenario, 91 * we can just assume we have FPU access - typically 92 * to save the FP state - we'll just take a #NM 93 * fault and get the FPU access back. 94 */ 95static inline int user_has_fpu(void) 96{ 97 return current->thread.fpu.has_fpu; 98} 99 100extern void unlazy_fpu(struct task_struct *tsk); 101 102#endif /* __ASSEMBLY__ */ 103 104#endif /* _ASM_X86_I387_H */