Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * include/asm-i386/i387.h | |
3 | * | |
4 | * Copyright (C) 1994 Linus Torvalds | |
5 | * | |
6 | * Pentium III FXSR, SSE support | |
7 | * General FPU state handling cleanups | |
8 | * Gareth Hughes <gareth@valinux.com>, May 2000 | |
9 | */ | |
10 | ||
11 | #ifndef __ASM_I386_I387_H | |
12 | #define __ASM_I386_I387_H | |
13 | ||
14 | #include <linux/sched.h> | |
15 | #include <linux/init.h> | |
16 | #include <asm/processor.h> | |
17 | #include <asm/sigcontext.h> | |
18 | #include <asm/user.h> | |
19 | ||
20 | extern void mxcsr_feature_mask_init(void); | |
21 | extern void init_fpu(struct task_struct *); | |
8ed1383f | 22 | |
1da177e4 LT |
23 | /* |
24 | * FPU lazy state save handling... | |
25 | */ | |
8ed1383f LT |
26 | |
27 | /* | |
28 | * The "nop" is needed to make the instructions the same | |
29 | * length. | |
30 | */ | |
31 | #define restore_fpu(tsk) \ | |
32 | alternative_input( \ | |
33 | "nop ; frstor %1", \ | |
34 | "fxrstor %1", \ | |
35 | X86_FEATURE_FXSR, \ | |
2847e347 | 36 | "m" ((tsk)->thread.i387.fxsave)) |
1da177e4 LT |
37 | |
38 | extern void kernel_fpu_begin(void); | |
39 | #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0) | |
40 | ||
41 | /* | |
42 | * These must be called with preempt disabled | |
43 | */ | |
44 | static inline void __save_init_fpu( struct task_struct *tsk ) | |
45 | { | |
2847e347 LT |
46 | alternative_input( |
47 | "fnsave %1 ; fwait ;" GENERIC_NOP2, | |
48 | "fxsave %1 ; fnclex", | |
49 | X86_FEATURE_FXSR, | |
50 | "m" (tsk->thread.i387.fxsave) | |
51 | :"memory"); | |
1da177e4 LT |
52 | tsk->thread_info->status &= ~TS_USEDFPU; |
53 | } | |
54 | ||
55 | #define __unlazy_fpu( tsk ) do { \ | |
56 | if ((tsk)->thread_info->status & TS_USEDFPU) \ | |
57 | save_init_fpu( tsk ); \ | |
58 | } while (0) | |
59 | ||
60 | #define __clear_fpu( tsk ) \ | |
61 | do { \ | |
62 | if ((tsk)->thread_info->status & TS_USEDFPU) { \ | |
63 | asm volatile("fnclex ; fwait"); \ | |
64 | (tsk)->thread_info->status &= ~TS_USEDFPU; \ | |
65 | stts(); \ | |
66 | } \ | |
67 | } while (0) | |
68 | ||
69 | ||
70 | /* | |
71 | * These disable preemption on their own and are safe | |
72 | */ | |
73 | static inline void save_init_fpu( struct task_struct *tsk ) | |
74 | { | |
75 | preempt_disable(); | |
76 | __save_init_fpu(tsk); | |
77 | stts(); | |
78 | preempt_enable(); | |
79 | } | |
80 | ||
81 | #define unlazy_fpu( tsk ) do { \ | |
82 | preempt_disable(); \ | |
83 | __unlazy_fpu(tsk); \ | |
84 | preempt_enable(); \ | |
85 | } while (0) | |
86 | ||
87 | #define clear_fpu( tsk ) do { \ | |
88 | preempt_disable(); \ | |
89 | __clear_fpu( tsk ); \ | |
90 | preempt_enable(); \ | |
91 | } while (0) | |
92 | \ | |
93 | /* | |
94 | * FPU state interaction... | |
95 | */ | |
96 | extern unsigned short get_fpu_cwd( struct task_struct *tsk ); | |
97 | extern unsigned short get_fpu_swd( struct task_struct *tsk ); | |
98 | extern unsigned short get_fpu_mxcsr( struct task_struct *tsk ); | |
99 | ||
100 | /* | |
101 | * Signal frame handlers... | |
102 | */ | |
103 | extern int save_i387( struct _fpstate __user *buf ); | |
104 | extern int restore_i387( struct _fpstate __user *buf ); | |
105 | ||
106 | /* | |
107 | * ptrace request handers... | |
108 | */ | |
109 | extern int get_fpregs( struct user_i387_struct __user *buf, | |
110 | struct task_struct *tsk ); | |
111 | extern int set_fpregs( struct task_struct *tsk, | |
112 | struct user_i387_struct __user *buf ); | |
113 | ||
114 | extern int get_fpxregs( struct user_fxsr_struct __user *buf, | |
115 | struct task_struct *tsk ); | |
116 | extern int set_fpxregs( struct task_struct *tsk, | |
117 | struct user_fxsr_struct __user *buf ); | |
118 | ||
119 | /* | |
120 | * FPU state for core dumps... | |
121 | */ | |
122 | extern int dump_fpu( struct pt_regs *regs, | |
123 | struct user_i387_struct *fpu ); | |
124 | ||
125 | #endif /* __ASM_I386_I387_H */ |