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
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.
11 #include <asm/irqflags.h>
12 #include <asm/hazards.h>
13 #include <linux/compiler.h>
14 #include <linux/preempt.h>
15 #include <linux/export.h>
16 #include <linux/stringify.h>
18 #if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
21 * For cli() we have to insert nops to make sure that the new value
22 * has actually arrived in the status register before the end of this
24 * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
28 * For TX49, operating only IE bit is not enough.
30 * If mfc0 $12 follows store and the mfc0 is last instruction of a
31 * page and fetching the next instruction causes TLB miss, the result
32 * of the mfc0 might wrongly contain EXL bit.
34 * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
36 * Workaround: mask EXL bit of the result or place a nop before mfc0.
38 notrace
void arch_local_irq_disable(void)
45 #ifdef CONFIG_MIPS_MT_SMTC
50 #elif defined(CONFIG_CPU_MIPSR2)
51 /* see irqflags.h for inline function */
59 " " __stringify(__irq_disable_hazard
) " \n"
67 EXPORT_SYMBOL(arch_local_irq_disable
);
70 notrace
unsigned long arch_local_irq_save(void)
80 #ifdef CONFIG_MIPS_MT_SMTC
81 " mfc0 %[flags], $2, 1 \n"
82 " ori $1, %[flags], 0x400 \n"
85 " andi %[flags], %[flags], 0x400 \n"
86 #elif defined(CONFIG_CPU_MIPSR2)
87 /* see irqflags.h for inline function */
89 " mfc0 %[flags], $12 \n"
90 " ori $1, %[flags], 0x1f \n"
95 " " __stringify(__irq_disable_hazard
) " \n"
97 : [flags
] "=r" (flags
)
105 EXPORT_SYMBOL(arch_local_irq_save
);
107 notrace
void arch_local_irq_restore(unsigned long flags
)
109 unsigned long __tmp1
;
111 #ifdef CONFIG_MIPS_MT_SMTC
113 * SMTC kernel needs to do a software replay of queued
114 * IPIs, at the cost of branch and call overhead on each
115 * local_irq_restore()
117 if (unlikely(!(flags
& 0x0400)))
122 __asm__
__volatile__(
126 #ifdef CONFIG_MIPS_MT_SMTC
128 " andi %[flags], 0x400 \n"
131 " or %[flags], $1 \n"
132 " mtc0 %[flags], $2, 1 \n"
133 #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
134 /* see irqflags.h for inline function */
135 #elif defined(CONFIG_CPU_MIPSR2)
136 /* see irqflags.h for inline function */
139 " andi %[flags], 1 \n"
142 " or %[flags], $1 \n"
143 " mtc0 %[flags], $12 \n"
145 " " __stringify(__irq_disable_hazard
) " \n"
147 : [flags
] "=r" (__tmp1
)
153 EXPORT_SYMBOL(arch_local_irq_restore
);
156 notrace
void __arch_local_irq_restore(unsigned long flags
)
158 unsigned long __tmp1
;
162 __asm__
__volatile__(
166 #ifdef CONFIG_MIPS_MT_SMTC
168 " andi %[flags], 0x400 \n"
171 " or %[flags], $1 \n"
172 " mtc0 %[flags], $2, 1 \n"
173 #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
174 /* see irqflags.h for inline function */
175 #elif defined(CONFIG_CPU_MIPSR2)
176 /* see irqflags.h for inline function */
179 " andi %[flags], 1 \n"
182 " or %[flags], $1 \n"
183 " mtc0 %[flags], $12 \n"
185 " " __stringify(__irq_disable_hazard
) " \n"
187 : [flags
] "=r" (__tmp1
)
193 EXPORT_SYMBOL(__arch_local_irq_restore
);
195 #endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */