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_IRQFLAGS_H
12 #define _ASM_IRQFLAGS_H
13
14 #ifndef __ASSEMBLY__
15
16 #include <linux/compiler.h>
17 #include <linux/stringify.h>
18 #include <asm/compiler.h>
19 #include <asm/hazards.h>
20
21 #if defined(CONFIG_CPU_HAS_DIEI)
22
arch_local_irq_disable(void)23 static inline void arch_local_irq_disable(void)
24 {
25 __asm__ __volatile__(
26 " .set push \n"
27 " .set noat \n"
28 " di \n"
29 " " __stringify(__irq_disable_hazard) " \n"
30 " .set pop \n"
31 : /* no outputs */
32 : /* no inputs */
33 : "memory");
34 }
35
arch_local_irq_save(void)36 static inline unsigned long arch_local_irq_save(void)
37 {
38 unsigned long flags;
39
40 asm __volatile__(
41 " .set push \n"
42 " .set reorder \n"
43 " .set noat \n"
44 #if defined(CONFIG_CPU_LOONGSON64) || defined(CONFIG_CPU_LOONGSON32)
45 " mfc0 %[flags], $12 \n"
46 " di \n"
47 #else
48 " di %[flags] \n"
49 #endif
50 " andi %[flags], 1 \n"
51 " " __stringify(__irq_disable_hazard) " \n"
52 " .set pop \n"
53 : [flags] "=r" (flags)
54 : /* no inputs */
55 : "memory");
56
57 return flags;
58 }
59
arch_local_irq_restore(unsigned long flags)60 static inline void arch_local_irq_restore(unsigned long flags)
61 {
62 unsigned long __tmp1;
63
64 __asm__ __volatile__(
65 " .set push \n"
66 " .set noreorder \n"
67 " .set noat \n"
68 #if defined(CONFIG_IRQ_MIPS_CPU)
69 /*
70 * Slow, but doesn't suffer from a relatively unlikely race
71 * condition we're having since days 1.
72 */
73 " beqz %[flags], 1f \n"
74 " di \n"
75 " ei \n"
76 "1: \n"
77 #else
78 /*
79 * Fast, dangerous. Life is fun, life is good.
80 */
81 " mfc0 $1, $12 \n"
82 " ins $1, %[flags], 0, 1 \n"
83 " mtc0 $1, $12 \n"
84 #endif
85 " " __stringify(__irq_disable_hazard) " \n"
86 " .set pop \n"
87 : [flags] "=r" (__tmp1)
88 : "0" (flags)
89 : "memory");
90 }
91
92 #else
93 /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
94 void arch_local_irq_disable(void);
95 unsigned long arch_local_irq_save(void);
96 void arch_local_irq_restore(unsigned long flags);
97 #endif /* CONFIG_CPU_HAS_DIEI */
98
arch_local_irq_enable(void)99 static inline void arch_local_irq_enable(void)
100 {
101 __asm__ __volatile__(
102 " .set push \n"
103 " .set reorder \n"
104 " .set noat \n"
105 #if defined(CONFIG_CPU_HAS_DIEI)
106 " ei \n"
107 #else
108 " mfc0 $1,$12 \n"
109 " ori $1,0x1f \n"
110 " xori $1,0x1e \n"
111 " mtc0 $1,$12 \n"
112 #endif
113 " " __stringify(__irq_enable_hazard) " \n"
114 " .set pop \n"
115 : /* no outputs */
116 : /* no inputs */
117 : "memory");
118 }
119
arch_local_save_flags(void)120 static inline unsigned long arch_local_save_flags(void)
121 {
122 unsigned long flags;
123
124 asm __volatile__(
125 " .set push \n"
126 " .set reorder \n"
127 " mfc0 %[flags], $12 \n"
128 " .set pop \n"
129 : [flags] "=r" (flags));
130
131 return flags;
132 }
133
134
arch_irqs_disabled_flags(unsigned long flags)135 static inline int arch_irqs_disabled_flags(unsigned long flags)
136 {
137 return !(flags & 1);
138 }
139
arch_irqs_disabled(void)140 static inline int arch_irqs_disabled(void)
141 {
142 return arch_irqs_disabled_flags(arch_local_save_flags());
143 }
144
145 #endif /* #ifndef __ASSEMBLY__ */
146
147 /*
148 * Do the CPU's IRQ-state tracing from assembly code.
149 */
150 #ifdef CONFIG_TRACE_IRQFLAGS
151 /* Reload some registers clobbered by trace_hardirqs_on */
152 #ifdef CONFIG_64BIT
153 # define TRACE_IRQS_RELOAD_REGS \
154 LONG_L $11, PT_R11(sp); \
155 LONG_L $10, PT_R10(sp); \
156 LONG_L $9, PT_R9(sp); \
157 LONG_L $8, PT_R8(sp); \
158 LONG_L $7, PT_R7(sp); \
159 LONG_L $6, PT_R6(sp); \
160 LONG_L $5, PT_R5(sp); \
161 LONG_L $4, PT_R4(sp); \
162 LONG_L $2, PT_R2(sp)
163 #else
164 # define TRACE_IRQS_RELOAD_REGS \
165 LONG_L $7, PT_R7(sp); \
166 LONG_L $6, PT_R6(sp); \
167 LONG_L $5, PT_R5(sp); \
168 LONG_L $4, PT_R4(sp); \
169 LONG_L $2, PT_R2(sp)
170 #endif
171 # define TRACE_IRQS_ON \
172 CLI; /* make sure trace_hardirqs_on() is called in kernel level */ \
173 jal trace_hardirqs_on
174 # define TRACE_IRQS_ON_RELOAD \
175 TRACE_IRQS_ON; \
176 TRACE_IRQS_RELOAD_REGS
177 # define TRACE_IRQS_OFF \
178 jal trace_hardirqs_off
179 #else
180 # define TRACE_IRQS_ON
181 # define TRACE_IRQS_ON_RELOAD
182 # define TRACE_IRQS_OFF
183 #endif
184
185 #endif /* _ASM_IRQFLAGS_H */
186