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 v4.0 108 lines 2.8 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 preempt_disable(); 44 WARN_ON_ONCE(!irq_fpu_usable()); 45 __kernel_fpu_begin(); 46} 47 48static inline void kernel_fpu_end(void) 49{ 50 __kernel_fpu_end(); 51 preempt_enable(); 52} 53 54/* Must be called with preempt disabled */ 55extern void kernel_fpu_disable(void); 56extern void kernel_fpu_enable(void); 57 58/* 59 * Some instructions like VIA's padlock instructions generate a spurious 60 * DNA fault but don't modify SSE registers. And these instructions 61 * get used from interrupt context as well. To prevent these kernel instructions 62 * in interrupt context interacting wrongly with other user/kernel fpu usage, we 63 * should use them only in the context of irq_ts_save/restore() 64 */ 65static inline int irq_ts_save(void) 66{ 67 /* 68 * If in process context and not atomic, we can take a spurious DNA fault. 69 * Otherwise, doing clts() in process context requires disabling preemption 70 * or some heavy lifting like kernel_fpu_begin() 71 */ 72 if (!in_atomic()) 73 return 0; 74 75 if (read_cr0() & X86_CR0_TS) { 76 clts(); 77 return 1; 78 } 79 80 return 0; 81} 82 83static inline void irq_ts_restore(int TS_state) 84{ 85 if (TS_state) 86 stts(); 87} 88 89/* 90 * The question "does this thread have fpu access?" 91 * is slightly racy, since preemption could come in 92 * and revoke it immediately after the test. 93 * 94 * However, even in that very unlikely scenario, 95 * we can just assume we have FPU access - typically 96 * to save the FP state - we'll just take a #NM 97 * fault and get the FPU access back. 98 */ 99static inline int user_has_fpu(void) 100{ 101 return current->thread.fpu.has_fpu; 102} 103 104extern void unlazy_fpu(struct task_struct *tsk); 105 106#endif /* __ASSEMBLY__ */ 107 108#endif /* _ASM_X86_I387_H */