fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / include / asm-mips / interrupt.h
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  * Copyright (C) 2000 MIPS Technologies, Inc.
10  */
11 #ifndef _ASM_INTERRUPT_H
12 #define _ASM_INTERRUPT_H
13
14 #include <linux/config.h>
15 #include <asm/hazards.h>
16
17 __asm__ (
18         "       .macro  local_irq_enable                                \n"
19         "       .set    push                                            \n"
20         "       .set    reorder                                         \n"
21         "       .set    noat                                            \n"
22 #ifdef CONFIG_CPU_MIPSR2
23         "       .set    mips32r2                                        \n"
24         "       ei                                                      \n"
25         "       .set    mips0                                           \n"
26 #else
27         "       mfc0    $1,$12                                          \n"
28         "       ori     $1,0x1f                                         \n"
29         "       xori    $1,0x1e                                         \n"
30         "       mtc0    $1,$12                                          \n"
31 #endif
32         "       irq_enable_hazard                                       \n"
33         "       .set    pop                                             \n"
34         "       .endm");
35
36 static inline void local_irq_enable(void)
37 {
38         __asm__ __volatile__(
39                 "local_irq_enable"
40                 : /* no outputs */
41                 : /* no inputs */
42                 : "memory");
43 }
44
45 /*
46  * For cli() we have to insert nops to make sure that the new value
47  * has actually arrived in the status register before the end of this
48  * macro.
49  * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
50  * no nops at all.
51  */
52 /*
53  * For TX49, operating only IE bit is not enough.
54  *
55  * If mfc0 $12 follows store and the mfc0 is last instruction of a
56  * page and fetching the next instruction causes TLB miss, the result
57  * of the mfc0 might wrongly contain EXL bit.
58  *
59  * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
60  *
61  * Workaround: mask EXL bit of the result or place a nop before mfc0.
62  */
63 __asm__ (
64         "       .macro  local_irq_disable\n"
65         "       .set    push                                            \n"
66         "       .set    noat                                            \n"
67 #ifdef CONFIG_CPU_MIPSR2
68         "       .set    mips32r2                                        \n"
69         "       di                                                      \n"
70         "       .set    mips0                                           \n"
71 #else
72         "       mfc0    $1,$12                                          \n"
73         "       ori     $1,0x1f                                         \n"
74         "       xori    $1,0x1f                                         \n"
75         "       .set    noreorder                                       \n"
76         "       mtc0    $1,$12                                          \n"
77 #endif
78         "       irq_disable_hazard                                      \n"
79         "       .set    pop                                             \n"
80         "       .endm                                                   \n");
81
82 static inline void local_irq_disable(void)
83 {
84         __asm__ __volatile__(
85                 "local_irq_disable"
86                 : /* no outputs */
87                 : /* no inputs */
88                 : "memory");
89 }
90
91 __asm__ (
92         "       .macro  local_save_flags flags                          \n"
93         "       .set    push                                            \n"
94         "       .set    reorder                                         \n"
95         "       mfc0    \\flags, $12                                    \n"
96         "       .set    pop                                             \n"
97         "       .endm                                                   \n");
98
99 #define local_save_flags(x)                                             \
100 __asm__ __volatile__(                                                   \
101         "local_save_flags %0"                                           \
102         : "=r" (x))
103
104 __asm__ (
105         "       .macro  local_irq_save result                           \n"
106         "       .set    push                                            \n"
107         "       .set    reorder                                         \n"
108         "       .set    noat                                            \n"
109 #ifdef CONFIG_CPU_MIPSR2
110         "       .set    mips32r2                                        \n"
111         "       di      \\result                                        \n"
112         "       andi    \\result, 1                                     \n"
113         "       .set    mips0                                           \n"
114 #else
115         "       mfc0    \\result, $12                                   \n"
116         "       ori     $1, \\result, 0x1f                              \n"
117         "       xori    $1, 0x1f                                        \n"
118         "       .set    noreorder                                       \n"
119         "       mtc0    $1, $12                                         \n"
120 #endif
121         "       irq_disable_hazard                                      \n"
122         "       .set    pop                                             \n"
123         "       .endm                                                   \n");
124
125 #define local_irq_save(x)                                               \
126 __asm__ __volatile__(                                                   \
127         "local_irq_save\t%0"                                            \
128         : "=r" (x)                                                      \
129         : /* no inputs */                                               \
130         : "memory")
131
132 __asm__ (
133         "       .macro  local_irq_restore flags                         \n"
134         "       .set    push                                            \n"
135         "       .set    noreorder                                       \n"
136         "       .set    noat                                            \n"
137 #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
138         /*
139          * Slow, but doesn't suffer from a relativly unlikely race
140          * condition we're having since days 1.
141          */
142         "       .set    mips32r2                                        \n"
143         "       beqz    \\flags, 1f                                     \n"
144         "        di                                                     \n"
145         "       ei                                                      \n"
146         "       .set    mips0                                           \n"
147         "1:                                                             \n"
148 #elif defined(CONFIG_CPU_MIPSR2)
149         /*
150          * Fast, dangerous.  Life is fun, life is good.
151          */
152         "       mfc0    $1, $12                                         \n"
153         "       ins     $1, \\flags, 0, 1                               \n"
154         "       mtc0    $1, $12                                         \n"
155 #else
156         "       mfc0    $1, $12                                         \n"
157         "       andi    \\flags, 1                                      \n"
158         "       ori     $1, 0x1f                                        \n"
159         "       xori    $1, 0x1f                                        \n"
160         "       or      \\flags, $1                                     \n"
161         "       mtc0    \\flags, $12                                    \n"
162 #endif
163         "       irq_disable_hazard                                      \n"
164         "       .set    pop                                             \n"
165         "       .endm                                                   \n");
166
167 #define local_irq_restore(flags)                                        \
168 do {                                                                    \
169         unsigned long __tmp1;                                           \
170                                                                         \
171         __asm__ __volatile__(                                           \
172                 "local_irq_restore\t%0"                                 \
173                 : "=r" (__tmp1)                                         \
174                 : "0" (flags)                                           \
175                 : "memory");                                            \
176 } while(0)
177
178 #define irqs_disabled()                                                 \
179 ({                                                                      \
180         unsigned long flags;                                            \
181         local_save_flags(flags);                                        \
182         !(flags & 1);                                                   \
183 })
184
185 #endif /* _ASM_INTERRUPT_H */