xref: /openbmc/linux/arch/mips/include/asm/irqflags.h (revision 99dc56fe)
1384740dcSRalf Baechle /*
2384740dcSRalf Baechle  * This file is subject to the terms and conditions of the GNU General Public
3384740dcSRalf Baechle  * License.  See the file "COPYING" in the main directory of this archive
4384740dcSRalf Baechle  * for more details.
5384740dcSRalf Baechle  *
6384740dcSRalf Baechle  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
7384740dcSRalf Baechle  * Copyright (C) 1996 by Paul M. Antoine
8384740dcSRalf Baechle  * Copyright (C) 1999 Silicon Graphics
9384740dcSRalf Baechle  * Copyright (C) 2000 MIPS Technologies, Inc.
10384740dcSRalf Baechle  */
11384740dcSRalf Baechle #ifndef _ASM_IRQFLAGS_H
12384740dcSRalf Baechle #define _ASM_IRQFLAGS_H
13384740dcSRalf Baechle 
14384740dcSRalf Baechle #ifndef __ASSEMBLY__
15384740dcSRalf Baechle 
16384740dcSRalf Baechle #include <linux/compiler.h>
1702b849f7SRalf Baechle #include <linux/stringify.h>
188716a763SMarkos Chandras #include <asm/compiler.h>
19384740dcSRalf Baechle #include <asm/hazards.h>
20384740dcSRalf Baechle 
21ba9196d2SJiaxun Yang #if defined(CONFIG_CPU_HAS_DIEI)
22e97c5b60SJim Quinlan 
arch_local_irq_disable(void)23e97c5b60SJim Quinlan static inline void arch_local_irq_disable(void)
24e97c5b60SJim Quinlan {
25e97c5b60SJim Quinlan 	__asm__ __volatile__(
2602b849f7SRalf Baechle 	"	.set	push						\n"
2702b849f7SRalf Baechle 	"	.set	noat						\n"
2802b849f7SRalf Baechle 	"	di							\n"
2902b849f7SRalf Baechle 	"	" __stringify(__irq_disable_hazard) "			\n"
3002b849f7SRalf Baechle 	"	.set	pop						\n"
31e97c5b60SJim Quinlan 	: /* no outputs */
32e97c5b60SJim Quinlan 	: /* no inputs */
33e97c5b60SJim Quinlan 	: "memory");
34e97c5b60SJim Quinlan }
35e97c5b60SJim Quinlan 
arch_local_irq_save(void)36e97c5b60SJim Quinlan static inline unsigned long arch_local_irq_save(void)
37e97c5b60SJim Quinlan {
38e97c5b60SJim Quinlan 	unsigned long flags;
3902b849f7SRalf Baechle 
4002b849f7SRalf Baechle 	asm __volatile__(
4102b849f7SRalf Baechle 	"	.set	push						\n"
4202b849f7SRalf Baechle 	"	.set	reorder						\n"
4302b849f7SRalf Baechle 	"	.set	noat						\n"
44b2afb64cSHuacai Chen #if defined(CONFIG_CPU_LOONGSON64) || defined(CONFIG_CPU_LOONGSON32)
451e820da3SHuacai Chen 	"	mfc0	%[flags], $12					\n"
461e820da3SHuacai Chen 	"	di							\n"
471e820da3SHuacai Chen #else
4802b849f7SRalf Baechle 	"	di	%[flags]					\n"
491e820da3SHuacai Chen #endif
5002b849f7SRalf Baechle 	"	andi	%[flags], 1					\n"
5102b849f7SRalf Baechle 	"	" __stringify(__irq_disable_hazard) "			\n"
5202b849f7SRalf Baechle 	"	.set	pop						\n"
5302b849f7SRalf Baechle 	: [flags] "=r" (flags)
54e97c5b60SJim Quinlan 	: /* no inputs */
55e97c5b60SJim Quinlan 	: "memory");
5602b849f7SRalf Baechle 
57e97c5b60SJim Quinlan 	return flags;
58e97c5b60SJim Quinlan }
59e97c5b60SJim Quinlan 
arch_local_irq_restore(unsigned long flags)6002b849f7SRalf Baechle static inline void arch_local_irq_restore(unsigned long flags)
6102b849f7SRalf Baechle {
6202b849f7SRalf Baechle 	unsigned long __tmp1;
63e97c5b60SJim Quinlan 
6402b849f7SRalf Baechle 	__asm__ __volatile__(
65e97c5b60SJim Quinlan 	"	.set	push						\n"
66e97c5b60SJim Quinlan 	"	.set	noreorder					\n"
67e97c5b60SJim Quinlan 	"	.set	noat						\n"
6867e38cf2SRalf Baechle #if defined(CONFIG_IRQ_MIPS_CPU)
69e97c5b60SJim Quinlan 	/*
70e97c5b60SJim Quinlan 	 * Slow, but doesn't suffer from a relatively unlikely race
71e97c5b60SJim Quinlan 	 * condition we're having since days 1.
72e97c5b60SJim Quinlan 	 */
7302b849f7SRalf Baechle 	"	beqz	%[flags], 1f					\n"
74e97c5b60SJim Quinlan 	"	di							\n"
75e97c5b60SJim Quinlan 	"	ei							\n"
76e97c5b60SJim Quinlan 	"1:								\n"
77e97c5b60SJim Quinlan #else
78e97c5b60SJim Quinlan 	/*
79e97c5b60SJim Quinlan 	 * Fast, dangerous.  Life is fun, life is good.
80e97c5b60SJim Quinlan 	 */
81e97c5b60SJim Quinlan 	"	mfc0	$1, $12						\n"
8202b849f7SRalf Baechle 	"	ins	$1, %[flags], 0, 1				\n"
83e97c5b60SJim Quinlan 	"	mtc0	$1, $12						\n"
84e97c5b60SJim Quinlan #endif
8502b849f7SRalf Baechle 	"	" __stringify(__irq_disable_hazard) "			\n"
86e97c5b60SJim Quinlan 	"	.set	pop						\n"
8702b849f7SRalf Baechle 	: [flags] "=r" (__tmp1)
88e97c5b60SJim Quinlan 	: "0" (flags)
89e97c5b60SJim Quinlan 	: "memory");
90e97c5b60SJim Quinlan }
91e97c5b60SJim Quinlan 
92e97c5b60SJim Quinlan #else
93e97c5b60SJim Quinlan /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
94e97c5b60SJim Quinlan void arch_local_irq_disable(void);
95e97c5b60SJim Quinlan unsigned long arch_local_irq_save(void);
96e97c5b60SJim Quinlan void arch_local_irq_restore(unsigned long flags);
97ba9196d2SJiaxun Yang #endif /* CONFIG_CPU_HAS_DIEI */
9802b849f7SRalf Baechle 
arch_local_irq_enable(void)9902b849f7SRalf Baechle static inline void arch_local_irq_enable(void)
10002b849f7SRalf Baechle {
10102b849f7SRalf Baechle 	__asm__ __volatile__(
102384740dcSRalf Baechle 	"	.set	push						\n"
103384740dcSRalf Baechle 	"	.set	reorder						\n"
104384740dcSRalf Baechle 	"	.set	noat						\n"
105ba9196d2SJiaxun Yang #if defined(CONFIG_CPU_HAS_DIEI)
106384740dcSRalf Baechle 	"	ei							\n"
107384740dcSRalf Baechle #else
108384740dcSRalf Baechle 	"	mfc0	$1,$12						\n"
109384740dcSRalf Baechle 	"	ori	$1,0x1f						\n"
110384740dcSRalf Baechle 	"	xori	$1,0x1e						\n"
111384740dcSRalf Baechle 	"	mtc0	$1,$12						\n"
112384740dcSRalf Baechle #endif
11302b849f7SRalf Baechle 	"	" __stringify(__irq_enable_hazard) "			\n"
114384740dcSRalf Baechle 	"	.set	pop						\n"
115384740dcSRalf Baechle 	: /* no outputs */
116384740dcSRalf Baechle 	: /* no inputs */
117384740dcSRalf Baechle 	: "memory");
118384740dcSRalf Baechle }
119384740dcSRalf Baechle 
arch_local_save_flags(void)120df9ee292SDavid Howells static inline unsigned long arch_local_save_flags(void)
121df9ee292SDavid Howells {
122df9ee292SDavid Howells 	unsigned long flags;
12302b849f7SRalf Baechle 
12402b849f7SRalf Baechle 	asm __volatile__(
12502b849f7SRalf Baechle 	"	.set	push						\n"
12602b849f7SRalf Baechle 	"	.set	reorder						\n"
12702b849f7SRalf Baechle 	"	mfc0	%[flags], $12					\n"
12802b849f7SRalf Baechle 	"	.set	pop						\n"
12902b849f7SRalf Baechle 	: [flags] "=r" (flags));
13002b849f7SRalf Baechle 
131df9ee292SDavid Howells 	return flags;
132df9ee292SDavid Howells }
133384740dcSRalf Baechle 
134384740dcSRalf Baechle 
arch_irqs_disabled_flags(unsigned long flags)135df9ee292SDavid Howells static inline int arch_irqs_disabled_flags(unsigned long flags)
136384740dcSRalf Baechle {
137384740dcSRalf Baechle 	return !(flags & 1);
138384740dcSRalf Baechle }
139384740dcSRalf Baechle 
arch_irqs_disabled(void)14099dc56feSPeter Zijlstra static inline int arch_irqs_disabled(void)
14199dc56feSPeter Zijlstra {
14299dc56feSPeter Zijlstra 	return arch_irqs_disabled_flags(arch_local_save_flags());
14399dc56feSPeter Zijlstra }
14499dc56feSPeter Zijlstra 
145e97c5b60SJim Quinlan #endif /* #ifndef __ASSEMBLY__ */
146384740dcSRalf Baechle 
147384740dcSRalf Baechle /*
148384740dcSRalf Baechle  * Do the CPU's IRQ-state tracing from assembly code.
149384740dcSRalf Baechle  */
150384740dcSRalf Baechle #ifdef CONFIG_TRACE_IRQFLAGS
151384740dcSRalf Baechle /* Reload some registers clobbered by trace_hardirqs_on */
152384740dcSRalf Baechle #ifdef CONFIG_64BIT
153384740dcSRalf Baechle # define TRACE_IRQS_RELOAD_REGS						\
154384740dcSRalf Baechle 	LONG_L	$11, PT_R11(sp);					\
155384740dcSRalf Baechle 	LONG_L	$10, PT_R10(sp);					\
156384740dcSRalf Baechle 	LONG_L	$9, PT_R9(sp);						\
157384740dcSRalf Baechle 	LONG_L	$8, PT_R8(sp);						\
158384740dcSRalf Baechle 	LONG_L	$7, PT_R7(sp);						\
159384740dcSRalf Baechle 	LONG_L	$6, PT_R6(sp);						\
160384740dcSRalf Baechle 	LONG_L	$5, PT_R5(sp);						\
161384740dcSRalf Baechle 	LONG_L	$4, PT_R4(sp);						\
162384740dcSRalf Baechle 	LONG_L	$2, PT_R2(sp)
163384740dcSRalf Baechle #else
164384740dcSRalf Baechle # define TRACE_IRQS_RELOAD_REGS						\
165384740dcSRalf Baechle 	LONG_L	$7, PT_R7(sp);						\
166384740dcSRalf Baechle 	LONG_L	$6, PT_R6(sp);						\
167384740dcSRalf Baechle 	LONG_L	$5, PT_R5(sp);						\
168384740dcSRalf Baechle 	LONG_L	$4, PT_R4(sp);						\
169384740dcSRalf Baechle 	LONG_L	$2, PT_R2(sp)
170384740dcSRalf Baechle #endif
171384740dcSRalf Baechle # define TRACE_IRQS_ON							\
172384740dcSRalf Baechle 	CLI;	/* make sure trace_hardirqs_on() is called in kernel level */ \
173384740dcSRalf Baechle 	jal	trace_hardirqs_on
174384740dcSRalf Baechle # define TRACE_IRQS_ON_RELOAD						\
175384740dcSRalf Baechle 	TRACE_IRQS_ON;							\
176384740dcSRalf Baechle 	TRACE_IRQS_RELOAD_REGS
177384740dcSRalf Baechle # define TRACE_IRQS_OFF							\
178384740dcSRalf Baechle 	jal	trace_hardirqs_off
179384740dcSRalf Baechle #else
180384740dcSRalf Baechle # define TRACE_IRQS_ON
181384740dcSRalf Baechle # define TRACE_IRQS_ON_RELOAD
182384740dcSRalf Baechle # define TRACE_IRQS_OFF
183384740dcSRalf Baechle #endif
184384740dcSRalf Baechle 
185384740dcSRalf Baechle #endif /* _ASM_IRQFLAGS_H */
186