1#ifndef __ASM_SYSTEM_H
2#define __ASM_SYSTEM_H
3
4#include <linux/config.h>
5#include <linux/kernel.h>
6#include <asm/segment.h>
7#include <asm/cpufeature.h>
8#include <linux/bitops.h>
9
10#ifdef __KERNEL__
11
12struct task_struct;
13extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
14
15#define switch_to(prev,next,last) do { \
16 unsigned long esi,edi; \
17 asm volatile("pushfl\n\t" \
18 "pushl %%ebp\n\t" \
19 "movl %%esp,%0\n\t" \
20 "movl %5,%%esp\n\t" \
21 "movl $1f,%1\n\t" \
22 "pushl %6\n\t" \
23 "jmp __switch_to\n" \
24 "1:\t" \
25 "popl %%ebp\n\t" \
26 "popfl" \
27 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
28 "=a" (last),"=S" (esi),"=D" (edi) \
29 :"m" (next->thread.esp),"m" (next->thread.eip), \
30 "2" (prev), "d" (next)); \
31} while (0)
32
33#define _set_base(addr,base) do { unsigned long __pr; \
34__asm__ __volatile__ ("movw %%dx,%1\n\t" \
35 "rorl $16,%%edx\n\t" \
36 "movb %%dl,%2\n\t" \
37 "movb %%dh,%3" \
38 :"=&d" (__pr) \
39 :"m" (*((addr)+2)), \
40 "m" (*((addr)+4)), \
41 "m" (*((addr)+7)), \
42 "0" (base) \
43 ); } while(0)
44
45#define _set_limit(addr,limit) do { unsigned long __lr; \
46__asm__ __volatile__ ("movw %%dx,%1\n\t" \
47 "rorl $16,%%edx\n\t" \
48 "movb %2,%%dh\n\t" \
49 "andb $0xf0,%%dh\n\t" \
50 "orb %%dh,%%dl\n\t" \
51 "movb %%dl,%2" \
52 :"=&d" (__lr) \
53 :"m" (*(addr)), \
54 "m" (*((addr)+6)), \
55 "0" (limit) \
56 ); } while(0)
57
58#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
59#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 )
60
61static inline unsigned long _get_base(char * addr)
62{
63 unsigned long __base;
64 __asm__("movb %3,%%dh\n\t"
65 "movb %2,%%dl\n\t"
66 "shll $16,%%edx\n\t"
67 "movw %1,%%dx"
68 :"=&d" (__base)
69 :"m" (*((addr)+2)),
70 "m" (*((addr)+4)),
71 "m" (*((addr)+7)));
72 return __base;
73}
74
75#define get_base(ldt) _get_base( ((char *)&(ldt)) )
76
77
78
79
80
81#define loadsegment(seg,value) \
82 asm volatile("\n" \
83 "1:\t" \
84 "movl %0,%%" #seg "\n" \
85 "2:\n" \
86 ".section .fixup,\"ax\"\n" \
87 "3:\t" \
88 "pushl $0\n\t" \
89 "popl %%" #seg "\n\t" \
90 "jmp 2b\n" \
91 ".previous\n" \
92 ".section __ex_table,\"a\"\n\t" \
93 ".align 4\n\t" \
94 ".long 1b,3b\n" \
95 ".previous" \
96 : :"m" (*(unsigned int *)&(value)))
97
98
99
100
101#define savesegment(seg, value) \
102 asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
103
104
105
106
107#define clts() __asm__ __volatile__ ("clts")
108#define read_cr0() ({ \
109 unsigned int __dummy; \
110 __asm__( \
111 "movl %%cr0,%0\n\t" \
112 :"=r" (__dummy)); \
113 __dummy; \
114})
115#define write_cr0(x) \
116 __asm__("movl %0,%%cr0": :"r" (x));
117
118#define read_cr4() ({ \
119 unsigned int __dummy; \
120 __asm__( \
121 "movl %%cr4,%0\n\t" \
122 :"=r" (__dummy)); \
123 __dummy; \
124})
125#define write_cr4(x) \
126 __asm__("movl %0,%%cr4": :"r" (x));
127#define stts() write_cr0(8 | read_cr0())
128
129#endif
130
131#define wbinvd() \
132 __asm__ __volatile__ ("wbinvd": : :"memory");
133
134static inline unsigned long get_limit(unsigned long segment)
135{
136 unsigned long __limit;
137 __asm__("lsll %1,%0"
138 :"=r" (__limit):"r" (segment));
139 return __limit+1;
140}
141
142#define nop() __asm__ __volatile__ ("nop")
143
144#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
145
146#define tas(ptr) (xchg((ptr),1))
147
148struct __xchg_dummy { unsigned long a[100]; };
149#define __xg(x) ((struct __xchg_dummy *)(x))
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166static inline void __set_64bit (unsigned long long * ptr,
167 unsigned int low, unsigned int high)
168{
169 __asm__ __volatile__ (
170 "\n1:\t"
171 "movl (%0), %%eax\n\t"
172 "movl 4(%0), %%edx\n\t"
173 "lock cmpxchg8b (%0)\n\t"
174 "jnz 1b"
175 :
176 : "D"(ptr),
177 "b"(low),
178 "c"(high)
179 : "ax","dx","memory");
180}
181
182static inline void __set_64bit_constant (unsigned long long *ptr,
183 unsigned long long value)
184{
185 __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
186}
187#define ll_low(x) *(((unsigned int*)&(x))+0)
188#define ll_high(x) *(((unsigned int*)&(x))+1)
189
190static inline void __set_64bit_var (unsigned long long *ptr,
191 unsigned long long value)
192{
193 __set_64bit(ptr,ll_low(value), ll_high(value));
194}
195
196#define set_64bit(ptr,value) \
197(__builtin_constant_p(value) ? \
198 __set_64bit_constant(ptr, value) : \
199 __set_64bit_var(ptr, value) )
200
201#define _set_64bit(ptr,value) \
202(__builtin_constant_p(value) ? \
203 __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
204 __set_64bit(ptr, ll_low(value), ll_high(value)) )
205
206
207
208
209
210
211static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
212{
213 switch (size) {
214 case 1:
215 __asm__ __volatile__("xchgb %b0,%1"
216 :"=q" (x)
217 :"m" (*__xg(ptr)), "0" (x)
218 :"memory");
219 break;
220 case 2:
221 __asm__ __volatile__("xchgw %w0,%1"
222 :"=r" (x)
223 :"m" (*__xg(ptr)), "0" (x)
224 :"memory");
225 break;
226 case 4:
227 __asm__ __volatile__("xchgl %0,%1"
228 :"=r" (x)
229 :"m" (*__xg(ptr)), "0" (x)
230 :"memory");
231 break;
232 }
233 return x;
234}
235
236
237
238
239
240
241
242#ifdef CONFIG_X86_CMPXCHG
243#define __HAVE_ARCH_CMPXCHG 1
244#endif
245
246static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
247 unsigned long new, int size)
248{
249 unsigned long prev;
250 switch (size) {
251 case 1:
252 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
253 : "=a"(prev)
254 : "q"(new), "m"(*__xg(ptr)), "0"(old)
255 : "memory");
256 return prev;
257 case 2:
258 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
259 : "=a"(prev)
260 : "q"(new), "m"(*__xg(ptr)), "0"(old)
261 : "memory");
262 return prev;
263 case 4:
264 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
265 : "=a"(prev)
266 : "q"(new), "m"(*__xg(ptr)), "0"(old)
267 : "memory");
268 return prev;
269 }
270 return old;
271}
272
273#define cmpxchg(ptr,o,n)\
274 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
275 (unsigned long)(n),sizeof(*(ptr))))
276
277#ifdef __KERNEL__
278struct alt_instr {
279 __u8 *instr;
280 __u8 *replacement;
281 __u8 cpuid;
282 __u8 instrlen;
283 __u8 replacementlen;
284 __u8 pad;
285};
286#endif
287
288
289
290
291
292
293
294
295
296
297
298
299
300#define alternative(oldinstr, newinstr, feature) \
301 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
302 ".section .altinstructions,\"a\"\n" \
303 " .align 4\n" \
304 " .long 661b\n" \
305 " .long 663f\n" \
306 " .byte %c0\n" \
307 " .byte 662b-661b\n" \
308 " .byte 664f-663f\n" \
309 ".previous\n" \
310 ".section .altinstr_replacement,\"ax\"\n" \
311 "663:\n\t" newinstr "\n664:\n" \
312 ".previous" :: "i" (feature) : "memory")
313
314
315
316
317
318
319
320
321
322
323
324#define alternative_input(oldinstr, newinstr, feature, input) \
325 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
326 ".section .altinstructions,\"a\"\n" \
327 " .align 4\n" \
328 " .long 661b\n" \
329 " .long 663f\n" \
330 " .byte %c0\n" \
331 " .byte 662b-661b\n" \
332 " .byte 664f-663f\n" \
333 ".previous\n" \
334 ".section .altinstr_replacement,\"ax\"\n" \
335 "663:\n\t" newinstr "\n664:\n" \
336 ".previous" :: "i" (feature), input)
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#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
363#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417#define read_barrier_depends() do { } while(0)
418
419#ifdef CONFIG_X86_OOSTORE
420
421
422#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
423#else
424#define wmb() __asm__ __volatile__ ("": : :"memory")
425#endif
426
427#ifdef CONFIG_SMP
428#define smp_mb() mb()
429#define smp_rmb() rmb()
430#define smp_wmb() wmb()
431#define smp_read_barrier_depends() read_barrier_depends()
432#define set_mb(var, value) do { xchg(&var, value); } while (0)
433#else
434#define smp_mb() barrier()
435#define smp_rmb() barrier()
436#define smp_wmb() barrier()
437#define smp_read_barrier_depends() do { } while(0)
438#define set_mb(var, value) do { var = value; barrier(); } while (0)
439#endif
440
441#define set_wmb(var, value) do { var = value; wmb(); } while (0)
442
443
444#define local_save_flags(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushfl ; popl %0":"=g" (x): ); } while (0)
445#define local_irq_restore(x) do { typecheck(unsigned long,x); __asm__ __volatile__("pushl %0 ; popfl": :"g" (x):"memory", "cc"); } while (0)
446#define local_irq_disable() __asm__ __volatile__("cli": : :"memory")
447#define local_irq_enable() __asm__ __volatile__("sti": : :"memory")
448
449#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory")
450
451#define irqs_disabled() \
452({ \
453 unsigned long flags; \
454 local_save_flags(flags); \
455 !(flags & (1<<9)); \
456})
457
458
459#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): :"memory")
460
461
462
463
464#define HAVE_DISABLE_HLT
465void disable_hlt(void);
466void enable_hlt(void);
467
468extern int es7000_plat;
469
470#endif
471