1
2
3
4
5
6
7
8
9
10
11
12#ifndef _ASM_SYSTEM_H
13#define _ASM_SYSTEM_H
14
15#include <linux/config.h>
16#include <asm/sgidefs.h>
17
18#include <linux/kernel.h>
19
20#include <asm/addrspace.h>
21#include <asm/ptrace.h>
22#include <asm/hazards.h>
23
24__asm__ (
25 ".macro\tlocal_irq_enable\n\t"
26 ".set\tpush\n\t"
27 ".set\treorder\n\t"
28 ".set\tnoat\n\t"
29 "mfc0\t$1,$12\n\t"
30 "ori\t$1,0x1f\n\t"
31 "xori\t$1,0x1e\n\t"
32 "mtc0\t$1,$12\n\t"
33 "irq_enable_hazard\n\t"
34 ".set\tpop\n\t"
35 ".endm");
36
37static inline void local_irq_enable(void)
38{
39 __asm__ __volatile__(
40 "local_irq_enable"
41 :
42 :
43 : "memory");
44}
45
46
47
48
49
50
51
52
53__asm__ (
54 ".macro\tlocal_irq_disable\n\t"
55 ".set\tpush\n\t"
56 ".set\tnoat\n\t"
57 "mfc0\t$1,$12\n\t"
58 "ori\t$1,1\n\t"
59 "xori\t$1,1\n\t"
60 ".set\tnoreorder\n\t"
61 "mtc0\t$1,$12\n\t"
62 "irq_disable_hazard\n\t"
63 ".set\tpop\n\t"
64 ".endm");
65
66static inline void local_irq_disable(void)
67{
68 __asm__ __volatile__(
69 "local_irq_disable"
70 :
71 :
72 : "memory");
73}
74
75__asm__ (
76 ".macro\tlocal_save_flags flags\n\t"
77 ".set\tpush\n\t"
78 ".set\treorder\n\t"
79 "mfc0\t\\flags, $12\n\t"
80 ".set\tpop\n\t"
81 ".endm");
82
83#define local_save_flags(x) \
84__asm__ __volatile__( \
85 "local_save_flags %0" \
86 : "=r" (x))
87
88__asm__ (
89 ".macro\tlocal_irq_save result\n\t"
90 ".set\tpush\n\t"
91 ".set\treorder\n\t"
92 ".set\tnoat\n\t"
93 "mfc0\t\\result, $12\n\t"
94 "ori\t$1, \\result, 1\n\t"
95 "xori\t$1, 1\n\t"
96 ".set\tnoreorder\n\t"
97 "mtc0\t$1, $12\n\t"
98 "irq_disable_hazard\n\t"
99 ".set\tpop\n\t"
100 ".endm");
101
102#define local_irq_save(x) \
103__asm__ __volatile__( \
104 "local_irq_save\t%0" \
105 : "=r" (x) \
106 : \
107 : "memory")
108
109__asm__ (
110 ".macro\tlocal_irq_restore flags\n\t"
111 ".set\tnoreorder\n\t"
112 ".set\tnoat\n\t"
113 "mfc0\t$1, $12\n\t"
114 "andi\t\\flags, 1\n\t"
115 "ori\t$1, 1\n\t"
116 "xori\t$1, 1\n\t"
117 "or\t\\flags, $1\n\t"
118 "mtc0\t\\flags, $12\n\t"
119 "irq_disable_hazard\n\t"
120 ".set\tat\n\t"
121 ".set\treorder\n\t"
122 ".endm");
123
124#define local_irq_restore(flags) \
125do { \
126 unsigned long __tmp1; \
127 \
128 __asm__ __volatile__( \
129 "local_irq_restore\t%0" \
130 : "=r" (__tmp1) \
131 : "0" (flags) \
132 : "memory"); \
133} while(0)
134
135#define irqs_disabled() \
136({ \
137 unsigned long flags; \
138 local_save_flags(flags); \
139 !(flags & 1); \
140})
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194#define read_barrier_depends() do { } while(0)
195
196#ifdef CONFIG_CPU_HAS_SYNC
197#define __sync() \
198 __asm__ __volatile__( \
199 ".set push\n\t" \
200 ".set noreorder\n\t" \
201 ".set mips2\n\t" \
202 "sync\n\t" \
203 ".set pop" \
204 : \
205 : \
206 : "memory")
207#else
208#define __sync() do { } while(0)
209#endif
210
211#define __fast_iob() \
212 __asm__ __volatile__( \
213 ".set push\n\t" \
214 ".set noreorder\n\t" \
215 "lw $0,%0\n\t" \
216 "nop\n\t" \
217 ".set pop" \
218 : \
219 : "m" (*(int *)CKSEG1) \
220 : "memory")
221
222#define fast_wmb() __sync()
223#define fast_rmb() __sync()
224#define fast_mb() __sync()
225#define fast_iob() \
226 do { \
227 __sync(); \
228 __fast_iob(); \
229 } while (0)
230
231#ifdef CONFIG_CPU_HAS_WB
232
233#include <asm/wbflush.h>
234
235#define wmb() fast_wmb()
236#define rmb() fast_rmb()
237#define mb() wbflush()
238#define iob() wbflush()
239
240#else
241
242#define wmb() fast_wmb()
243#define rmb() fast_rmb()
244#define mb() fast_mb()
245#define iob() fast_iob()
246
247#endif
248
249#ifdef CONFIG_SMP
250#define smp_mb() mb()
251#define smp_rmb() rmb()
252#define smp_wmb() wmb()
253#define smp_read_barrier_depends() read_barrier_depends()
254#else
255#define smp_mb() barrier()
256#define smp_rmb() barrier()
257#define smp_wmb() barrier()
258#define smp_read_barrier_depends() do { } while(0)
259#endif
260
261#define set_mb(var, value) \
262do { var = value; mb(); } while (0)
263
264#define set_wmb(var, value) \
265do { var = value; wmb(); } while (0)
266
267
268
269
270
271extern asmlinkage void *resume(void *last, void *next, void *next_ti);
272
273struct task_struct;
274
275#define switch_to(prev,next,last) \
276do { \
277 (last) = resume(prev, next, next->thread_info); \
278} while(0)
279
280static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
281{
282 __u32 retval;
283
284#ifdef CONFIG_CPU_HAS_LLSC
285 unsigned long dummy;
286
287 __asm__ __volatile__(
288 ".set\tpush\t\t\t\t# xchg_u32\n\t"
289 ".set\tnoreorder\n\t"
290 ".set\tnomacro\n\t"
291 "ll\t%0, %3\n"
292 "1:\tmove\t%2, %z4\n\t"
293 "sc\t%2, %1\n\t"
294 "beqzl\t%2, 1b\n\t"
295 " ll\t%0, %3\n\t"
296#ifdef CONFIG_SMP
297 "sync\n\t"
298#endif
299 ".set\tpop"
300 : "=&r" (retval), "=m" (*m), "=&r" (dummy)
301 : "R" (*m), "Jr" (val)
302 : "memory");
303#else
304 unsigned long flags;
305
306 local_irq_save(flags);
307 retval = *m;
308 *m = val;
309 local_irq_restore(flags);
310#endif
311
312 return retval;
313}
314
315#ifdef CONFIG_MIPS64
316static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
317{
318 __u64 retval;
319
320#ifdef CONFIG_CPU_HAS_LLDSCD
321 unsigned long dummy;
322
323 __asm__ __volatile__(
324 ".set\tpush\t\t\t\t# xchg_u64\n\t"
325 ".set\tnoreorder\n\t"
326 ".set\tnomacro\n\t"
327 "lld\t%0, %3\n"
328 "1:\tmove\t%2, %z4\n\t"
329 "scd\t%2, %1\n\t"
330 "beqzl\t%2, 1b\n\t"
331 " lld\t%0, %3\n\t"
332#ifdef CONFIG_SMP
333 "sync\n\t"
334#endif
335 ".set\tpop"
336 : "=&r" (retval), "=m" (*m), "=&r" (dummy)
337 : "R" (*m), "Jr" (val)
338 : "memory");
339#else
340 unsigned long flags;
341
342 local_irq_save(flags);
343 retval = *m;
344 *m = val;
345 local_irq_restore(flags);
346#endif
347
348 return retval;
349}
350#else
351extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
352#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
353#endif
354
355
356
357extern void __xchg_called_with_bad_pointer(void);
358
359static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
360{
361 switch (size) {
362 case 4:
363 return __xchg_u32(ptr, x);
364 case 8:
365 return __xchg_u64(ptr, x);
366 }
367 __xchg_called_with_bad_pointer();
368 return x;
369}
370
371#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
372#define tas(ptr) (xchg((ptr),1))
373
374#define __HAVE_ARCH_CMPXCHG 1
375
376static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
377 unsigned long new)
378{
379 __u32 retval;
380
381#ifdef CONFIG_CPU_HAS_LLSC
382 __asm__ __volatile__(
383 " .set noat \n"
384 "1: ll %0, %2 # __cmpxchg_u32 \n"
385 " bne %0, %z3, 2f \n"
386 " move $1, %z4 \n"
387 " sc $1, %1 \n"
388 " beqz $1, 1b \n"
389#ifdef CONFIG_SMP
390 " sync \n"
391#endif
392 "2: \n"
393 " .set at \n"
394 : "=&r" (retval), "=m" (*m)
395 : "R" (*m), "Jr" (old), "Jr" (new)
396 : "memory");
397#else
398 unsigned long flags;
399
400 local_irq_save(flags);
401 retval = *m;
402 if (retval == old)
403 *m = new;
404 local_irq_restore(flags);
405#endif
406
407 return retval;
408}
409
410#ifdef CONFIG_MIPS64
411static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
412 unsigned long new)
413{
414 __u64 retval;
415
416#ifdef CONFIG_CPU_HAS_LLDSCD
417 __asm__ __volatile__(
418 " .set noat \n"
419 "1: lld %0, %2 # __cmpxchg_u64 \n"
420 " bne %0, %z3, 2f \n"
421 " move $1, %z4 \n"
422 " scd $1, %1 \n"
423 " beqz $1, 1b \n"
424#ifdef CONFIG_SMP
425 " sync \n"
426#endif
427 "2: \n"
428 " .set at \n"
429 : "=&r" (retval), "=m" (*m)
430 : "R" (*m), "Jr" (old), "Jr" (new)
431 : "memory");
432#else
433 unsigned long flags;
434
435 local_irq_save(flags);
436 retval = *m;
437 if (retval == old)
438 *m = new;
439 local_irq_restore(flags);
440#endif
441
442 return retval;
443}
444#else
445extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
446 volatile int * m, unsigned long old, unsigned long new);
447#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
448#endif
449
450
451
452extern void __cmpxchg_called_with_bad_pointer(void);
453
454static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
455 unsigned long new, int size)
456{
457 switch (size) {
458 case 4:
459 return __cmpxchg_u32(ptr, old, new);
460 case 8:
461 return __cmpxchg_u64(ptr, old, new);
462 }
463 __cmpxchg_called_with_bad_pointer();
464 return old;
465}
466
467#define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
468
469extern void *set_except_vector(int n, void *addr);
470extern void per_cpu_trap_init(void);
471
472extern NORET_TYPE void __die(const char *, struct pt_regs *, const char *file,
473 const char *func, unsigned long line);
474extern void __die_if_kernel(const char *, struct pt_regs *, const char *file,
475 const char *func, unsigned long line);
476
477#define die(msg, regs) \
478 __die(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
479#define die_if_kernel(msg, regs) \
480 __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
481
482extern int serial_console;
483extern int stop_a_enabled;
484
485static __inline__ int con_is_present(void)
486{
487 return serial_console ? 0 : 1;
488}
489
490
491
492
493
494#define prepare_arch_switch(rq, next) \
495do { \
496 spin_lock(&(next)->switch_lock); \
497 spin_unlock(&(rq)->lock); \
498} while (0)
499#define finish_arch_switch(rq, prev) spin_unlock_irq(&(prev)->switch_lock)
500#define task_running(rq, p) ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
501
502#endif
503