1#ifndef _ASM_X86_SYSTEM_H_
2#define _ASM_X86_SYSTEM_H_
3
4#include <asm/asm.h>
5#include <asm/segment.h>
6#include <asm/cpufeature.h>
7#include <asm/cmpxchg.h>
8#include <asm/nops.h>
9
10#include <linux/kernel.h>
11#include <linux/irqflags.h>
12
13
14#ifdef CONFIG_IA32_EMULATION
15# define AT_VECTOR_SIZE_ARCH 2
16#else
17# define AT_VECTOR_SIZE_ARCH 1
18#endif
19
20#ifdef CONFIG_X86_32
21
22struct task_struct;
23struct task_struct *__switch_to(struct task_struct *prev,
24 struct task_struct *next);
25
26
27
28
29
30#define switch_to(prev, next, last) do { \
31 unsigned long esi, edi; \
32 asm volatile("pushfl\n\t" \
33 "pushl %%ebp\n\t" \
34 "movl %%esp,%0\n\t" \
35 "movl %5,%%esp\n\t" \
36 "movl $1f,%1\n\t" \
37 "pushl %6\n\t" \
38 "jmp __switch_to\n" \
39 "1:\t" \
40 "popl %%ebp\n\t" \
41 "popfl" \
42 :"=m" (prev->thread.sp), "=m" (prev->thread.ip), \
43 "=a" (last), "=S" (esi), "=D" (edi) \
44 :"m" (next->thread.sp), "m" (next->thread.ip), \
45 "2" (prev), "d" (next)); \
46} while (0)
47
48
49
50
51#define HAVE_DISABLE_HLT
52#else
53#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
54#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
55
56
57#define SAVE_CONTEXT "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
58#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
59
60#define __EXTRA_CLOBBER \
61 , "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
62 "r12", "r13", "r14", "r15"
63
64
65#define switch_to(prev, next, last) \
66 asm volatile(SAVE_CONTEXT \
67 "movq %%rsp,%P[threadrsp](%[prev])\n\t" \
68 "movq %P[threadrsp](%[next]),%%rsp\n\t" \
69 "call __switch_to\n\t" \
70 ".globl thread_return\n" \
71 "thread_return:\n\t" \
72 "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \
73 "movq %P[thread_info](%%rsi),%%r8\n\t" \
74 LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
75 "movq %%rax,%%rdi\n\t" \
76 "jc ret_from_fork\n\t" \
77 RESTORE_CONTEXT \
78 : "=a" (last) \
79 : [next] "S" (next), [prev] "D" (prev), \
80 [threadrsp] "i" (offsetof(struct task_struct, thread.sp)), \
81 [ti_flags] "i" (offsetof(struct thread_info, flags)), \
82 [tif_fork] "i" (TIF_FORK), \
83 [thread_info] "i" (offsetof(struct task_struct, stack)), \
84 [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \
85 : "memory", "cc" __EXTRA_CLOBBER)
86#endif
87
88#ifdef __KERNEL__
89#define _set_base(addr, base) do { unsigned long __pr; \
90__asm__ __volatile__ ("movw %%dx,%1\n\t" \
91 "rorl $16,%%edx\n\t" \
92 "movb %%dl,%2\n\t" \
93 "movb %%dh,%3" \
94 :"=&d" (__pr) \
95 :"m" (*((addr)+2)), \
96 "m" (*((addr)+4)), \
97 "m" (*((addr)+7)), \
98 "0" (base) \
99 ); } while (0)
100
101#define _set_limit(addr, limit) do { unsigned long __lr; \
102__asm__ __volatile__ ("movw %%dx,%1\n\t" \
103 "rorl $16,%%edx\n\t" \
104 "movb %2,%%dh\n\t" \
105 "andb $0xf0,%%dh\n\t" \
106 "orb %%dh,%%dl\n\t" \
107 "movb %%dl,%2" \
108 :"=&d" (__lr) \
109 :"m" (*(addr)), \
110 "m" (*((addr)+6)), \
111 "0" (limit) \
112 ); } while (0)
113
114#define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base))
115#define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1))
116
117extern void load_gs_index(unsigned);
118
119
120
121
122
123#define loadsegment(seg, value) \
124 asm volatile("\n" \
125 "1:\t" \
126 "movl %k0,%%" #seg "\n" \
127 "2:\n" \
128 ".section .fixup,\"ax\"\n" \
129 "3:\t" \
130 "movl %k1, %%" #seg "\n\t" \
131 "jmp 2b\n" \
132 ".previous\n" \
133 _ASM_EXTABLE(1b,3b) \
134 : :"r" (value), "r" (0))
135
136
137
138
139
140#define savesegment(seg, value) \
141 asm volatile("mov %%" #seg ",%0":"=rm" (value))
142
143static inline unsigned long get_limit(unsigned long segment)
144{
145 unsigned long __limit;
146 __asm__("lsll %1,%0"
147 :"=r" (__limit):"r" (segment));
148 return __limit+1;
149}
150
151static inline void native_clts(void)
152{
153 asm volatile ("clts");
154}
155
156
157
158
159
160
161
162
163static unsigned long __force_order;
164
165static inline unsigned long native_read_cr0(void)
166{
167 unsigned long val;
168 asm volatile("mov %%cr0,%0\n\t" :"=r" (val), "=m" (__force_order));
169 return val;
170}
171
172static inline void native_write_cr0(unsigned long val)
173{
174 asm volatile("mov %0,%%cr0": :"r" (val), "m" (__force_order));
175}
176
177static inline unsigned long native_read_cr2(void)
178{
179 unsigned long val;
180 asm volatile("mov %%cr2,%0\n\t" :"=r" (val), "=m" (__force_order));
181 return val;
182}
183
184static inline void native_write_cr2(unsigned long val)
185{
186 asm volatile("mov %0,%%cr2": :"r" (val), "m" (__force_order));
187}
188
189static inline unsigned long native_read_cr3(void)
190{
191 unsigned long val;
192 asm volatile("mov %%cr3,%0\n\t" :"=r" (val), "=m" (__force_order));
193 return val;
194}
195
196static inline void native_write_cr3(unsigned long val)
197{
198 asm volatile("mov %0,%%cr3": :"r" (val), "m" (__force_order));
199}
200
201static inline unsigned long native_read_cr4(void)
202{
203 unsigned long val;
204 asm volatile("mov %%cr4,%0\n\t" :"=r" (val), "=m" (__force_order));
205 return val;
206}
207
208static inline unsigned long native_read_cr4_safe(void)
209{
210 unsigned long val;
211
212
213#ifdef CONFIG_X86_32
214 asm volatile("1: mov %%cr4, %0\n"
215 "2:\n"
216 _ASM_EXTABLE(1b,2b)
217 : "=r" (val), "=m" (__force_order) : "0" (0));
218#else
219 val = native_read_cr4();
220#endif
221 return val;
222}
223
224static inline void native_write_cr4(unsigned long val)
225{
226 asm volatile("mov %0,%%cr4": :"r" (val), "m" (__force_order));
227}
228
229#ifdef CONFIG_X86_64
230static inline unsigned long native_read_cr8(void)
231{
232 unsigned long cr8;
233 asm volatile("movq %%cr8,%0" : "=r" (cr8));
234 return cr8;
235}
236
237static inline void native_write_cr8(unsigned long val)
238{
239 asm volatile("movq %0,%%cr8" :: "r" (val) : "memory");
240}
241#endif
242
243static inline void native_wbinvd(void)
244{
245 asm volatile("wbinvd": : :"memory");
246}
247#ifdef CONFIG_PARAVIRT
248#include <asm/paravirt.h>
249#else
250#define read_cr0() (native_read_cr0())
251#define write_cr0(x) (native_write_cr0(x))
252#define read_cr2() (native_read_cr2())
253#define write_cr2(x) (native_write_cr2(x))
254#define read_cr3() (native_read_cr3())
255#define write_cr3(x) (native_write_cr3(x))
256#define read_cr4() (native_read_cr4())
257#define read_cr4_safe() (native_read_cr4_safe())
258#define write_cr4(x) (native_write_cr4(x))
259#define wbinvd() (native_wbinvd())
260#ifdef CONFIG_X86_64
261#define read_cr8() (native_read_cr8())
262#define write_cr8(x) (native_write_cr8(x))
263#endif
264
265
266#define clts() (native_clts())
267
268#endif
269
270#define stts() write_cr0(8 | read_cr0())
271
272#endif
273
274static inline void clflush(volatile void *__p)
275{
276 asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
277}
278
279#define nop() __asm__ __volatile__ ("nop")
280
281void disable_hlt(void);
282void enable_hlt(void);
283
284extern int es7000_plat;
285void cpu_idle_wait(void);
286
287extern unsigned long arch_align_stack(unsigned long sp);
288extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
289
290void default_idle(void);
291
292
293
294
295
296
297#ifdef CONFIG_X86_32
298
299
300
301
302
303
304
305
306
307
308
309
310
311#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
312#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
313#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
314#else
315#define mb() asm volatile("mfence":::"memory")
316#define rmb() asm volatile("lfence":::"memory")
317#define wmb() asm volatile("sfence" ::: "memory")
318#endif
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372#define read_barrier_depends() do { } while (0)
373
374#ifdef CONFIG_SMP
375#define smp_mb() mb()
376#ifdef CONFIG_X86_PPRO_FENCE
377# define smp_rmb() rmb()
378#else
379# define smp_rmb() barrier()
380#endif
381#ifdef CONFIG_X86_OOSTORE
382# define smp_wmb() wmb()
383#else
384# define smp_wmb() barrier()
385#endif
386#define smp_read_barrier_depends() read_barrier_depends()
387#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
388#else
389#define smp_mb() barrier()
390#define smp_rmb() barrier()
391#define smp_wmb() barrier()
392#define smp_read_barrier_depends() do { } while (0)
393#define set_mb(var, value) do { var = value; barrier(); } while (0)
394#endif
395
396
397
398
399
400
401
402
403static inline void rdtsc_barrier(void)
404{
405 alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
406 alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
407}
408
409#endif
410