diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.8/0006-i387-don-t-ever-touch-TS_USEDFPU-directly-use-helper.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.8/0006-i387-don-t-ever-touch-TS_USEDFPU-directly-use-helper.patch | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.8/0006-i387-don-t-ever-touch-TS_USEDFPU-directly-use-helper.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.8/0006-i387-don-t-ever-touch-TS_USEDFPU-directly-use-helper.patch new file mode 100644 index 00000000..7daaa620 --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.8/0006-i387-don-t-ever-touch-TS_USEDFPU-directly-use-helper.patch | |||
@@ -0,0 +1,228 @@ | |||
1 | From 29515b215b9bbbad0368a5039ba6e53ed3fa7f25 Mon Sep 17 00:00:00 2001 | ||
2 | From: Linus Torvalds <torvalds@linux-foundation.org> | ||
3 | Date: Thu, 16 Feb 2012 13:33:12 -0800 | ||
4 | Subject: [PATCH 06/11] i387: don't ever touch TS_USEDFPU directly, use helper | ||
5 | functions | ||
6 | |||
7 | commit 6d59d7a9f5b723a7ac1925c136e93ec83c0c3043 upstream. | ||
8 | |||
9 | This creates three helper functions that do the TS_USEDFPU accesses, and | ||
10 | makes everybody that used to do it by hand use those helpers instead. | ||
11 | |||
12 | In addition, there's a couple of helper functions for the "change both | ||
13 | CR0.TS and TS_USEDFPU at the same time" case, and the places that do | ||
14 | that together have been changed to use those. That means that we have | ||
15 | fewer random places that open-code this situation. | ||
16 | |||
17 | The intent is partly to clarify the code without actually changing any | ||
18 | semantics yet (since we clearly still have some hard to reproduce bug in | ||
19 | this area), but also to make it much easier to use another approach | ||
20 | entirely to caching the CR0.TS bit for software accesses. | ||
21 | |||
22 | Right now we use a bit in the thread-info 'status' variable (this patch | ||
23 | does not change that), but we might want to make it a full field of its | ||
24 | own or even make it a per-cpu variable. | ||
25 | |||
26 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
28 | --- | ||
29 | arch/x86/include/asm/i387.h | 75 +++++++++++++++++++++++++++++++----------- | ||
30 | arch/x86/kernel/traps.c | 2 +- | ||
31 | arch/x86/kernel/xsave.c | 2 +- | ||
32 | arch/x86/kvm/vmx.c | 2 +- | ||
33 | 4 files changed, 58 insertions(+), 23 deletions(-) | ||
34 | |||
35 | diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h | ||
36 | index 55fb3aa..730d7be 100644 | ||
37 | --- a/arch/x86/include/asm/i387.h | ||
38 | +++ b/arch/x86/include/asm/i387.h | ||
39 | @@ -280,6 +280,47 @@ static inline int restore_fpu_checking(struct task_struct *tsk) | ||
40 | } | ||
41 | |||
42 | /* | ||
43 | + * Software FPU state helpers. Careful: these need to | ||
44 | + * be preemption protection *and* they need to be | ||
45 | + * properly paired with the CR0.TS changes! | ||
46 | + */ | ||
47 | +static inline int __thread_has_fpu(struct thread_info *ti) | ||
48 | +{ | ||
49 | + return ti->status & TS_USEDFPU; | ||
50 | +} | ||
51 | + | ||
52 | +/* Must be paired with an 'stts' after! */ | ||
53 | +static inline void __thread_clear_has_fpu(struct thread_info *ti) | ||
54 | +{ | ||
55 | + ti->status &= ~TS_USEDFPU; | ||
56 | +} | ||
57 | + | ||
58 | +/* Must be paired with a 'clts' before! */ | ||
59 | +static inline void __thread_set_has_fpu(struct thread_info *ti) | ||
60 | +{ | ||
61 | + ti->status |= TS_USEDFPU; | ||
62 | +} | ||
63 | + | ||
64 | +/* | ||
65 | + * Encapsulate the CR0.TS handling together with the | ||
66 | + * software flag. | ||
67 | + * | ||
68 | + * These generally need preemption protection to work, | ||
69 | + * do try to avoid using these on their own. | ||
70 | + */ | ||
71 | +static inline void __thread_fpu_end(struct thread_info *ti) | ||
72 | +{ | ||
73 | + __thread_clear_has_fpu(ti); | ||
74 | + stts(); | ||
75 | +} | ||
76 | + | ||
77 | +static inline void __thread_fpu_begin(struct thread_info *ti) | ||
78 | +{ | ||
79 | + clts(); | ||
80 | + __thread_set_has_fpu(ti); | ||
81 | +} | ||
82 | + | ||
83 | +/* | ||
84 | * Signal frame handlers... | ||
85 | */ | ||
86 | extern int save_i387_xstate(void __user *buf); | ||
87 | @@ -287,23 +328,21 @@ extern int restore_i387_xstate(void __user *buf); | ||
88 | |||
89 | static inline void __unlazy_fpu(struct task_struct *tsk) | ||
90 | { | ||
91 | - if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
92 | + if (__thread_has_fpu(task_thread_info(tsk))) { | ||
93 | __save_init_fpu(tsk); | ||
94 | - task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
95 | - stts(); | ||
96 | + __thread_fpu_end(task_thread_info(tsk)); | ||
97 | } else | ||
98 | tsk->fpu_counter = 0; | ||
99 | } | ||
100 | |||
101 | static inline void __clear_fpu(struct task_struct *tsk) | ||
102 | { | ||
103 | - if (task_thread_info(tsk)->status & TS_USEDFPU) { | ||
104 | + if (__thread_has_fpu(task_thread_info(tsk))) { | ||
105 | /* Ignore delayed exceptions from user space */ | ||
106 | asm volatile("1: fwait\n" | ||
107 | "2:\n" | ||
108 | _ASM_EXTABLE(1b, 2b)); | ||
109 | - task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
110 | - stts(); | ||
111 | + __thread_fpu_end(task_thread_info(tsk)); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | @@ -311,14 +350,14 @@ static inline void __clear_fpu(struct task_struct *tsk) | ||
116 | * Were we in an interrupt that interrupted kernel mode? | ||
117 | * | ||
118 | * We can do a kernel_fpu_begin/end() pair *ONLY* if that | ||
119 | - * pair does nothing at all: TS_USEDFPU must be clear (so | ||
120 | + * pair does nothing at all: the thread must not have fpu (so | ||
121 | * that we don't try to save the FPU state), and TS must | ||
122 | * be set (so that the clts/stts pair does nothing that is | ||
123 | * visible in the interrupted kernel thread). | ||
124 | */ | ||
125 | static inline bool interrupted_kernel_fpu_idle(void) | ||
126 | { | ||
127 | - return !(current_thread_info()->status & TS_USEDFPU) && | ||
128 | + return !__thread_has_fpu(current_thread_info()) && | ||
129 | (read_cr0() & X86_CR0_TS); | ||
130 | } | ||
131 | |||
132 | @@ -356,9 +395,9 @@ static inline void kernel_fpu_begin(void) | ||
133 | |||
134 | WARN_ON_ONCE(!irq_fpu_usable()); | ||
135 | preempt_disable(); | ||
136 | - if (me->status & TS_USEDFPU) { | ||
137 | + if (__thread_has_fpu(me)) { | ||
138 | __save_init_fpu(me->task); | ||
139 | - me->status &= ~TS_USEDFPU; | ||
140 | + __thread_clear_has_fpu(me); | ||
141 | /* We do 'stts()' in kernel_fpu_end() */ | ||
142 | } else | ||
143 | clts(); | ||
144 | @@ -422,24 +461,21 @@ static inline void irq_ts_restore(int TS_state) | ||
145 | */ | ||
146 | static inline int user_has_fpu(void) | ||
147 | { | ||
148 | - return current_thread_info()->status & TS_USEDFPU; | ||
149 | + return __thread_has_fpu(current_thread_info()); | ||
150 | } | ||
151 | |||
152 | static inline void user_fpu_end(void) | ||
153 | { | ||
154 | preempt_disable(); | ||
155 | - current_thread_info()->status &= ~TS_USEDFPU; | ||
156 | - stts(); | ||
157 | + __thread_fpu_end(current_thread_info()); | ||
158 | preempt_enable(); | ||
159 | } | ||
160 | |||
161 | static inline void user_fpu_begin(void) | ||
162 | { | ||
163 | preempt_disable(); | ||
164 | - if (!user_has_fpu()) { | ||
165 | - clts(); | ||
166 | - current_thread_info()->status |= TS_USEDFPU; | ||
167 | - } | ||
168 | + if (!user_has_fpu()) | ||
169 | + __thread_fpu_begin(current_thread_info()); | ||
170 | preempt_enable(); | ||
171 | } | ||
172 | |||
173 | @@ -448,11 +484,10 @@ static inline void user_fpu_begin(void) | ||
174 | */ | ||
175 | static inline void save_init_fpu(struct task_struct *tsk) | ||
176 | { | ||
177 | - WARN_ON_ONCE(!(task_thread_info(tsk)->status & TS_USEDFPU)); | ||
178 | + WARN_ON_ONCE(!__thread_has_fpu(task_thread_info(tsk))); | ||
179 | preempt_disable(); | ||
180 | __save_init_fpu(tsk); | ||
181 | - task_thread_info(tsk)->status &= ~TS_USEDFPU; | ||
182 | - stts(); | ||
183 | + __thread_fpu_end(task_thread_info(tsk)); | ||
184 | preempt_enable(); | ||
185 | } | ||
186 | |||
187 | diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c | ||
188 | index 727e6c1..bb5445c 100644 | ||
189 | --- a/arch/x86/kernel/traps.c | ||
190 | +++ b/arch/x86/kernel/traps.c | ||
191 | @@ -579,7 +579,7 @@ void __math_state_restore(void) | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | - thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | ||
196 | + __thread_set_has_fpu(thread); /* clts in caller! */ | ||
197 | tsk->fpu_counter++; | ||
198 | } | ||
199 | |||
200 | diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c | ||
201 | index 86f1f09..a0bcd0d 100644 | ||
202 | --- a/arch/x86/kernel/xsave.c | ||
203 | +++ b/arch/x86/kernel/xsave.c | ||
204 | @@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk) | ||
205 | if (!fx) | ||
206 | return; | ||
207 | |||
208 | - BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU); | ||
209 | + BUG_ON(__thread_has_fpu(task_thread_info(tsk))); | ||
210 | |||
211 | xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv; | ||
212 | |||
213 | diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c | ||
214 | index 579a0b5..b2c612d 100644 | ||
215 | --- a/arch/x86/kvm/vmx.c | ||
216 | +++ b/arch/x86/kvm/vmx.c | ||
217 | @@ -1456,7 +1456,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) | ||
218 | #ifdef CONFIG_X86_64 | ||
219 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | ||
220 | #endif | ||
221 | - if (current_thread_info()->status & TS_USEDFPU) | ||
222 | + if (__thread_has_fpu(current_thread_info())) | ||
223 | clts(); | ||
224 | load_gdt(&__get_cpu_var(host_gdt)); | ||
225 | } | ||
226 | -- | ||
227 | 1.7.7.4 | ||
228 | |||