source: svn/newcon3bcm2_21bu/toolchain/mips-linux-uclibc/include/asm/system.h @ 22

Last change on this file since 22 was 22, checked in by phkim, 11 years ago
  1. phkim
  2. newcon3sk 를 kctv 로 브랜치 함
  • Property svn:executable set to *
File size: 10.5 KB
Line 
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
7 * Copyright (C) 1996 by Paul M. Antoine
8 * Copyright (C) 1999 Silicon Graphics
9 * Kevin D. Kissell, kevink@mips.org and Carsten Langgaard, carstenl@mips.com
10 * Copyright (C) 2000 MIPS Technologies, Inc.
11 */
12#ifndef _ASM_SYSTEM_H
13#define _ASM_SYSTEM_H
14
15#include <linux/types.h>
16
17#include <asm/addrspace.h>
18#include <asm/cpu-features.h>
19#include <asm/ptrace.h>
20#include <asm/war.h>
21#include <asm/interrupt.h>
22
23/*
24 * read_barrier_depends - Flush all pending reads that subsequents reads
25 * depend on.
26 *
27 * No data-dependent reads from memory-like regions are ever reordered
28 * over this barrier.  All reads preceding this primitive are guaranteed
29 * to access memory (but not necessarily other CPUs' caches) before any
30 * reads following this primitive that depend on the data return by
31 * any of the preceding reads.  This primitive is much lighter weight than
32 * rmb() on most CPUs, and is never heavier weight than is
33 * rmb().
34 *
35 * These ordering constraints are respected by both the local CPU
36 * and the compiler.
37 *
38 * Ordering is not guaranteed by anything other than these primitives,
39 * not even by data dependencies.  See the documentation for
40 * memory_barrier() for examples and URLs to more information.
41 *
42 * For example, the following code would force ordering (the initial
43 * value of "a" is zero, "b" is one, and "p" is "&a"):
44 *
45 * <programlisting>
46 *      CPU 0                           CPU 1
47 *
48 *      b = 2;
49 *      memory_barrier();
50 *      p = &b;                         q = p;
51 *                                      read_barrier_depends();
52 *                                      d = *q;
53 * </programlisting>
54 *
55 * because the read of "*q" depends on the read of "p" and these
56 * two reads are separated by a read_barrier_depends().  However,
57 * the following code, with the same initial values for "a" and "b":
58 *
59 * <programlisting>
60 *      CPU 0                           CPU 1
61 *
62 *      a = 2;
63 *      memory_barrier();
64 *      b = 3;                          y = b;
65 *                                      read_barrier_depends();
66 *                                      x = a;
67 * </programlisting>
68 *
69 * does not enforce ordering, since there is no data dependency between
70 * the read of "a" and the read of "b".  Therefore, on some CPUs, such
71 * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
72 * in cases like thiswhere there are no data dependencies.
73 */
74
75#define read_barrier_depends()  do { } while(0)
76
77#ifdef CONFIG_CPU_HAS_SYNC
78#define __sync()                                \
79        __asm__ __volatile__(                   \
80                ".set   push\n\t"               \
81                ".set   noreorder\n\t"          \
82                ".set   mips2\n\t"              \
83                "sync\n\t"                      \
84                ".set   pop"                    \
85                : /* no output */               \
86                : /* no input */                \
87                : "memory")
88#else
89#define __sync()        do { } while(0)
90#endif
91
92#define __fast_iob()                            \
93        __asm__ __volatile__(                   \
94                ".set   push\n\t"               \
95                ".set   noreorder\n\t"          \
96                "lw     $0,%0\n\t"              \
97                "nop\n\t"                       \
98                ".set   pop"                    \
99                : /* no output */               \
100                : "m" (*(int *)CKSEG1)          \
101                : "memory")
102
103#define fast_wmb()      __sync()
104#define fast_rmb()      __sync()
105#define fast_mb()       __sync()
106#define fast_iob()                              \
107        do {                                    \
108                __sync();                       \
109                __fast_iob();                   \
110        } while (0)
111
112#ifdef CONFIG_CPU_HAS_WB
113
114#include <asm/wbflush.h>
115
116#define wmb()           fast_wmb()
117#define rmb()           fast_rmb()
118#define mb()            wbflush()
119#define iob()           wbflush()
120
121#else /* !CONFIG_CPU_HAS_WB */
122
123#define wmb()           fast_wmb()
124#define rmb()           fast_rmb()
125#define mb()            fast_mb()
126#define iob()           fast_iob()
127
128#endif /* !CONFIG_CPU_HAS_WB */
129
130#ifdef CONFIG_SMP
131#define smp_mb()        mb()
132#define smp_rmb()       rmb()
133#define smp_wmb()       wmb()
134#define smp_read_barrier_depends()      read_barrier_depends()
135#else
136#define smp_mb()        barrier()
137#define smp_rmb()       barrier()
138#define smp_wmb()       barrier()
139#define smp_read_barrier_depends()      do { } while(0)
140#endif
141
142#define set_mb(var, value) \
143do { var = value; mb(); } while (0)
144
145#define set_wmb(var, value) \
146do { var = value; wmb(); } while (0)
147
148/*
149 * switch_to(n) should switch tasks to task nr n, first
150 * checking that n isn't the current task, in which case it does nothing.
151 */
152extern asmlinkage void *resume(void *last, void *next, void *next_ti);
153
154struct task_struct;
155
156#define switch_to(prev,next,last) \
157do { \
158        (last) = resume(prev, next, next->thread_info); \
159} while(0)
160
161#define ROT_IN_PIECES                                                   \
162        "       .set    noreorder       \n"                             \
163        "       .set    reorder         \n"
164
165static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
166{
167        __u32 retval;
168
169        if (cpu_has_llsc && R10000_LLSC_WAR) {
170                unsigned long dummy;
171
172                __asm__ __volatile__(
173                "1:     ll      %0, %3                  # xchg_u32      \n"
174                "       move    %2, %z4                                 \n"
175                "       sc      %2, %1                                  \n"
176                "       beqzl   %2, 1b                                  \n"
177                ROT_IN_PIECES
178#ifdef CONFIG_SMP
179                "       sync                                            \n"
180#endif
181                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
182                : "R" (*m), "Jr" (val)
183                : "memory");
184        } else if (cpu_has_llsc) {
185                unsigned long dummy;
186
187                __asm__ __volatile__(
188                "1:     ll      %0, %3                  # xchg_u32      \n"
189                "       move    %2, %z4                                 \n"
190                "       sc      %2, %1                                  \n"
191                "       beqz    %2, 1b                                  \n"
192#ifdef CONFIG_SMP
193                "       sync                                            \n"
194#endif
195                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
196                : "R" (*m), "Jr" (val)
197                : "memory");
198        } else {
199                unsigned long flags;
200
201                local_irq_save(flags);
202                retval = *m;
203                *m = val;
204                local_irq_restore(flags);       /* implies memory barrier  */
205        }
206
207        return retval;
208}
209
210#ifdef __mips64
211static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
212{
213        __u64 retval;
214
215        if (cpu_has_llsc && R10000_LLSC_WAR) {
216                unsigned long dummy;
217
218                __asm__ __volatile__(
219                "1:     lld     %0, %3                  # xchg_u64      \n"
220                "       move    %2, %z4                                 \n"
221                "       scd     %2, %1                                  \n"
222                "       beqzl   %2, 1b                                  \n"
223                ROT_IN_PIECES
224#ifdef CONFIG_SMP
225                "       sync                                            \n"
226#endif
227                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
228                : "R" (*m), "Jr" (val)
229                : "memory");
230        } else if (cpu_has_llsc) {
231                unsigned long dummy;
232
233                __asm__ __volatile__(
234                "1:     lld     %0, %3                  # xchg_u64      \n"
235                "       move    %2, %z4                                 \n"
236                "       scd     %2, %1                                  \n"
237                "       beqz    %2, 1b                                  \n"
238#ifdef CONFIG_SMP
239                "       sync                                            \n"
240#endif
241                : "=&r" (retval), "=m" (*m), "=&r" (dummy)
242                : "R" (*m), "Jr" (val)
243                : "memory");
244        } else {
245                unsigned long flags;
246
247                local_irq_save(flags);
248                retval = *m;
249                *m = val;
250                local_irq_restore(flags);       /* implies memory barrier  */
251        }
252
253        return retval;
254}
255#else
256extern __u64 __xchg_u64_unsupported_on_32bit_kernels(volatile __u64 * m, __u64 val);
257#define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels
258#endif
259
260/* This function doesn't exist, so you'll get a linker error
261   if something tries to do an invalid xchg().  */
262extern void __xchg_called_with_bad_pointer(void);
263
264static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
265{
266        switch (size) {
267                case 4:
268                        return __xchg_u32(ptr, x);
269                case 8:
270                        return __xchg_u64(ptr, x);
271        }
272        __xchg_called_with_bad_pointer();
273        return x;
274}
275
276#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
277#define tas(ptr) (xchg((ptr),1))
278
279#define __HAVE_ARCH_CMPXCHG 1
280
281static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
282        unsigned long new)
283{
284        __u32 retval;
285
286        if (cpu_has_llsc && R10000_LLSC_WAR) {
287                __asm__ __volatile__(
288                "       .set    noat                                    \n"
289                "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
290                "       bne     %0, %z3, 2f                             \n"
291                "       move    $1, %z4                                 \n"
292                "       sc      $1, %1                                  \n"
293                "       beqzl   $1, 1b                                  \n"
294                ROT_IN_PIECES
295#ifdef CONFIG_SMP
296                "       sync                                            \n"
297#endif
298                "2:                                                     \n"
299                "       .set    at                                      \n"
300                : "=&r" (retval), "=m" (*m)
301                : "R" (*m), "Jr" (old), "Jr" (new)
302                : "memory");
303        } else if (cpu_has_llsc) {
304                __asm__ __volatile__(
305                "       .set    noat                                    \n"
306                "1:     ll      %0, %2                  # __cmpxchg_u32 \n"
307                "       bne     %0, %z3, 2f                             \n"
308                "       move    $1, %z4                                 \n"
309                "       sc      $1, %1                                  \n"
310                "       beqz    $1, 1b                                  \n"
311#ifdef CONFIG_SMP
312                "       sync                                            \n"
313#endif
314                "2:                                                     \n"
315                "       .set    at                                      \n"
316                : "=&r" (retval), "=m" (*m)
317                : "R" (*m), "Jr" (old), "Jr" (new)
318                : "memory");
319        } else {
320                unsigned long flags;
321
322                local_irq_save(flags);
323                retval = *m;
324                if (retval == old)
325                        *m = new;
326                local_irq_restore(flags);       /* implies memory barrier  */
327        }
328
329        return retval;
330}
331
332#ifdef __mips64
333static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old,
334        unsigned long new)
335{
336        __u64 retval;
337
338        if (cpu_has_llsc) {
339                __asm__ __volatile__(
340                "       .set    noat                                    \n"
341                "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
342                "       bne     %0, %z3, 2f                             \n"
343                "       move    $1, %z4                                 \n"
344                "       scd     $1, %1                                  \n"
345                "       beqzl   $1, 1b                                  \n"
346                ROT_IN_PIECES
347#ifdef CONFIG_SMP
348                "       sync                                            \n"
349#endif
350                "2:                                                     \n"
351                "       .set    at                                      \n"
352                : "=&r" (retval), "=m" (*m)
353                : "R" (*m), "Jr" (old), "Jr" (new)
354                : "memory");
355        } else if (cpu_has_llsc) {
356                __asm__ __volatile__(
357                "       .set    noat                                    \n"
358                "1:     lld     %0, %2                  # __cmpxchg_u64 \n"
359                "       bne     %0, %z3, 2f                             \n"
360                "       move    $1, %z4                                 \n"
361                "       scd     $1, %1                                  \n"
362                "       beqz    $1, 1b                                  \n"
363#ifdef CONFIG_SMP
364                "       sync                                            \n"
365#endif
366                "2:                                                     \n"
367                "       .set    at                                      \n"
368                : "=&r" (retval), "=m" (*m)
369                : "R" (*m), "Jr" (old), "Jr" (new)
370                : "memory");
371        } else {
372                unsigned long flags;
373
374                local_irq_save(flags);
375                retval = *m;
376                if (retval == old)
377                        *m = new;
378                local_irq_restore(flags);       /* implies memory barrier  */
379        }
380
381        return retval;
382}
383#else
384extern unsigned long __cmpxchg_u64_unsupported_on_32bit_kernels(
385        volatile int * m, unsigned long old, unsigned long new);
386#define __cmpxchg_u64 __cmpxchg_u64_unsupported_on_32bit_kernels
387#endif
388
389/* This function doesn't exist, so you'll get a linker error
390   if something tries to do an invalid cmpxchg().  */
391extern void __cmpxchg_called_with_bad_pointer(void);
392
393static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
394        unsigned long new, int size)
395{
396        switch (size) {
397        case 4:
398                return __cmpxchg_u32(ptr, old, new);
399        case 8:
400                return __cmpxchg_u64(ptr, old, new);
401        }
402        __cmpxchg_called_with_bad_pointer();
403        return old;
404}
405
406#define cmpxchg(ptr,old,new) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(old), (unsigned long)(new),sizeof(*(ptr))))
407
408extern void *set_except_vector(int n, void *addr);
409extern void per_cpu_trap_init(void);
410
411extern NORET_TYPE void __die(const char *, struct pt_regs *, const char *file,
412        const char *func, unsigned long line);
413extern void __die_if_kernel(const char *, struct pt_regs *, const char *file,
414        const char *func, unsigned long line);
415
416#define die(msg, regs)                                                  \
417        __die(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
418#define die_if_kernel(msg, regs)                                        \
419        __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
420
421extern int stop_a_enabled;
422
423/*
424 * Taken from include/asm-ia64/system.h; prevents deadlock on SMP
425 * systems.
426 */
427#define prepare_arch_switch(rq, next)           \
428do {                                            \
429        spin_lock(&(next)->switch_lock);        \
430        spin_unlock(&(rq)->lock);               \
431} while (0)
432#define finish_arch_switch(rq, prev)    spin_unlock_irq(&(prev)->switch_lock)
433#define task_running(rq, p)             ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
434
435#define arch_align_stack(x) (x)
436
437#endif /* _ASM_SYSTEM_H */
Note: See TracBrowser for help on using the repository browser.