irqflags.h 5.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
 * Copyright (C) 1996 by Paul M. Antoine
 * Copyright (C) 1999 Silicon Graphics
 * Copyright (C) 2000 MIPS Technologies, Inc.
 */
11 12 13 14
#ifndef _ASM_IRQFLAGS_H
#define _ASM_IRQFLAGS_H

#ifndef __ASSEMBLY__
L
Linus Torvalds 已提交
15

16
#include <linux/compiler.h>
L
Linus Torvalds 已提交
17 18
#include <asm/hazards.h>

19
#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
L
Linus Torvalds 已提交
20

21
__asm__(
D
David Howells 已提交
22
	"	.macro	arch_local_irq_disable\n"
23 24 25 26 27 28
	"	.set	push						\n"
	"	.set	noat						\n"
	"	di							\n"
	"	irq_disable_hazard					\n"
	"	.set	pop						\n"
	"	.endm							\n");
L
Linus Torvalds 已提交
29

D
David Howells 已提交
30
static inline void arch_local_irq_disable(void)
L
Linus Torvalds 已提交
31 32
{
	__asm__ __volatile__(
D
David Howells 已提交
33
		"arch_local_irq_disable"
L
Linus Torvalds 已提交
34 35 36 37 38 39
		: /* no outputs */
		: /* no inputs */
		: "memory");
}


40
__asm__(
D
David Howells 已提交
41
	"	.macro	arch_local_irq_save result			\n"
42 43 44 45
	"	.set	push						\n"
	"	.set	reorder						\n"
	"	.set	noat						\n"
	"	di	\\result					\n"
M
Maxime Bizon 已提交
46
	"	andi	\\result, 1					\n"
47 48 49
	"	irq_disable_hazard					\n"
	"	.set	pop						\n"
	"	.endm							\n");
L
Linus Torvalds 已提交
50

D
David Howells 已提交
51 52 53 54 55 56 57 58 59
static inline unsigned long arch_local_irq_save(void)
{
	unsigned long flags;
	asm volatile("arch_local_irq_save\t%0"
		     : "=r" (flags)
		     : /* no inputs */
		     : "memory");
	return flags;
}
L
Linus Torvalds 已提交
60

61

62
__asm__(
D
David Howells 已提交
63
	"	.macro	arch_local_irq_restore flags			\n"
64
	"	.set	push						\n"
65 66
	"	.set	noreorder					\n"
	"	.set	noat						\n"
67
#if defined(CONFIG_IRQ_CPU)
68
	/*
L
Lucas De Marchi 已提交
69
	 * Slow, but doesn't suffer from a relatively unlikely race
70 71 72
	 * condition we're having since days 1.
	 */
	"	beqz	\\flags, 1f					\n"
73
	"	di							\n"
74 75
	"	ei							\n"
	"1:								\n"
76
#else
77 78 79 80 81 82 83 84
	/*
	 * Fast, dangerous.  Life is fun, life is good.
	 */
	"	mfc0	$1, $12						\n"
	"	ins	$1, \\flags, 0, 1				\n"
	"	mtc0	$1, $12						\n"
#endif
	"	irq_disable_hazard					\n"
85
	"	.set	pop						\n"
86
	"	.endm							\n");
L
Linus Torvalds 已提交
87

D
David Howells 已提交
88
static inline void arch_local_irq_restore(unsigned long flags)
89 90 91 92
{
	unsigned long __tmp1;

	__asm__ __volatile__(
D
David Howells 已提交
93
		"arch_local_irq_restore\t%0"
94 95 96 97
		: "=r" (__tmp1)
		: "0" (flags)
		: "memory");
}
L
Linus Torvalds 已提交
98

D
David Howells 已提交
99
static inline void __arch_local_irq_restore(unsigned long flags)
100 101 102 103
{
	unsigned long __tmp1;

	__asm__ __volatile__(
D
David Howells 已提交
104
		"arch_local_irq_restore\t%0"
105 106 107 108
		: "=r" (__tmp1)
		: "0" (flags)
		: "memory");
}
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
#else
/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
void arch_local_irq_disable(void);
unsigned long arch_local_irq_save(void);
void arch_local_irq_restore(unsigned long flags);
void __arch_local_irq_restore(unsigned long flags);
#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */


__asm__(
	"	.macro	arch_local_irq_enable				\n"
	"	.set	push						\n"
	"	.set	reorder						\n"
	"	.set	noat						\n"
#ifdef CONFIG_MIPS_MT_SMTC
	"	mfc0	$1, $2, 1	# SMTC - clear TCStatus.IXMT	\n"
	"	ori	$1, 0x400					\n"
	"	xori	$1, 0x400					\n"
	"	mtc0	$1, $2, 1					\n"
#elif defined(CONFIG_CPU_MIPSR2)
	"	ei							\n"
#else
	"	mfc0	$1,$12						\n"
	"	ori	$1,0x1f						\n"
	"	xori	$1,0x1e						\n"
	"	mtc0	$1,$12						\n"
#endif
	"	irq_enable_hazard					\n"
	"	.set	pop						\n"
	"	.endm");

extern void smtc_ipi_replay(void);

static inline void arch_local_irq_enable(void)
{
#ifdef CONFIG_MIPS_MT_SMTC
	/*
	 * SMTC kernel needs to do a software replay of queued
	 * IPIs, at the cost of call overhead on each local_irq_enable()
	 */
	smtc_ipi_replay();
#endif
	__asm__ __volatile__(
		"arch_local_irq_enable"
		: /* no outputs */
		: /* no inputs */
		: "memory");
}


__asm__(
	"	.macro	arch_local_save_flags flags			\n"
	"	.set	push						\n"
	"	.set	reorder						\n"
#ifdef CONFIG_MIPS_MT_SMTC
	"	mfc0	\\flags, $2, 1					\n"
#else
	"	mfc0	\\flags, $12					\n"
#endif
	"	.set	pop						\n"
	"	.endm							\n");

static inline unsigned long arch_local_save_flags(void)
{
	unsigned long flags;
	asm volatile("arch_local_save_flags %0" : "=r" (flags));
	return flags;
}

178

D
David Howells 已提交
179
static inline int arch_irqs_disabled_flags(unsigned long flags)
180 181 182 183 184
{
#ifdef CONFIG_MIPS_MT_SMTC
	/*
	 * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
	 */
185
	return flags & 0x400;
186 187 188 189
#else
	return !(flags & 1);
#endif
}
L
Linus Torvalds 已提交
190

191
#endif /* #ifndef __ASSEMBLY__ */
192 193 194 195 196

/*
 * Do the CPU's IRQ-state tracing from assembly code.
 */
#ifdef CONFIG_TRACE_IRQFLAGS
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
/* Reload some registers clobbered by trace_hardirqs_on */
#ifdef CONFIG_64BIT
# define TRACE_IRQS_RELOAD_REGS						\
	LONG_L	$11, PT_R11(sp);					\
	LONG_L	$10, PT_R10(sp);					\
	LONG_L	$9, PT_R9(sp);						\
	LONG_L	$8, PT_R8(sp);						\
	LONG_L	$7, PT_R7(sp);						\
	LONG_L	$6, PT_R6(sp);						\
	LONG_L	$5, PT_R5(sp);						\
	LONG_L	$4, PT_R4(sp);						\
	LONG_L	$2, PT_R2(sp)
#else
# define TRACE_IRQS_RELOAD_REGS						\
	LONG_L	$7, PT_R7(sp);						\
	LONG_L	$6, PT_R6(sp);						\
	LONG_L	$5, PT_R5(sp);						\
	LONG_L	$4, PT_R4(sp);						\
	LONG_L	$2, PT_R2(sp)
#endif
217
# define TRACE_IRQS_ON							\
218
	CLI;	/* make sure trace_hardirqs_on() is called in kernel level */ \
219
	jal	trace_hardirqs_on
220 221 222
# define TRACE_IRQS_ON_RELOAD						\
	TRACE_IRQS_ON;							\
	TRACE_IRQS_RELOAD_REGS
223 224 225 226
# define TRACE_IRQS_OFF							\
	jal	trace_hardirqs_off
#else
# define TRACE_IRQS_ON
227
# define TRACE_IRQS_ON_RELOAD
228 229 230 231
# define TRACE_IRQS_OFF
#endif

#endif /* _ASM_IRQFLAGS_H */