| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | */ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 11 | #ifndef _ASM_IRQFLAGS_H | 
|  | 12 | #define _ASM_IRQFLAGS_H | 
|  | 13 |  | 
|  | 14 | #ifndef __ASSEMBLY__ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 |  | 
|  | 16 | #include <asm/hazards.h> | 
|  | 17 |  | 
| Ralf Baechle | ac8be95 | 2007-01-20 00:18:01 +0000 | [diff] [blame] | 18 | /* | 
|  | 19 | * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs, | 
|  | 20 | * at the cost of branch and call overhead on each local_irq_restore() | 
|  | 21 | */ | 
|  | 22 |  | 
|  | 23 | #ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY | 
|  | 24 |  | 
|  | 25 | extern void smtc_ipi_replay(void); | 
|  | 26 |  | 
|  | 27 | #define irq_restore_epilog(flags)				\ | 
|  | 28 | do {								\ | 
|  | 29 | if (!(flags & 0x0400))					\ | 
|  | 30 | smtc_ipi_replay();				\ | 
|  | 31 | } while (0) | 
|  | 32 |  | 
|  | 33 | #else | 
|  | 34 |  | 
|  | 35 | #define irq_restore_epilog(ignore) do { } while (0) | 
|  | 36 |  | 
|  | 37 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ | 
|  | 38 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 39 | __asm__ ( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 40 | "	.macro	raw_local_irq_enable				\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 41 | "	.set	push						\n" | 
|  | 42 | "	.set	reorder						\n" | 
|  | 43 | "	.set	noat						\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 44 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 45 | "	mfc0	$1, $2, 1	# SMTC - clear TCStatus.IXMT	\n" | 
|  | 46 | "	ori	$1, 0x400					\n" | 
|  | 47 | "	xori	$1, 0x400					\n" | 
|  | 48 | "	mtc0	$1, $2, 1					\n" | 
|  | 49 | #elif defined(CONFIG_CPU_MIPSR2) | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 50 | "	ei							\n" | 
|  | 51 | #else | 
|  | 52 | "	mfc0	$1,$12						\n" | 
|  | 53 | "	ori	$1,0x1f						\n" | 
|  | 54 | "	xori	$1,0x1e						\n" | 
|  | 55 | "	mtc0	$1,$12						\n" | 
|  | 56 | #endif | 
|  | 57 | "	irq_enable_hazard					\n" | 
|  | 58 | "	.set	pop						\n" | 
|  | 59 | "	.endm"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 60 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 61 | static inline void raw_local_irq_enable(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 62 | { | 
|  | 63 | __asm__ __volatile__( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 64 | "raw_local_irq_enable" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 65 | : /* no outputs */ | 
|  | 66 | : /* no inputs */ | 
|  | 67 | : "memory"); | 
|  | 68 | } | 
|  | 69 |  | 
|  | 70 | /* | 
|  | 71 | * For cli() we have to insert nops to make sure that the new value | 
|  | 72 | * has actually arrived in the status register before the end of this | 
|  | 73 | * macro. | 
|  | 74 | * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs | 
|  | 75 | * no nops at all. | 
|  | 76 | */ | 
| Atsushi Nemoto | c226f26 | 2006-02-03 01:34:01 +0900 | [diff] [blame] | 77 | /* | 
|  | 78 | * For TX49, operating only IE bit is not enough. | 
|  | 79 | * | 
|  | 80 | * If mfc0 $12 follows store and the mfc0 is last instruction of a | 
|  | 81 | * page and fetching the next instruction causes TLB miss, the result | 
|  | 82 | * of the mfc0 might wrongly contain EXL bit. | 
|  | 83 | * | 
|  | 84 | * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 | 
|  | 85 | * | 
|  | 86 | * Workaround: mask EXL bit of the result or place a nop before mfc0. | 
|  | 87 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 | __asm__ ( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 89 | "	.macro	raw_local_irq_disable\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 90 | "	.set	push						\n" | 
|  | 91 | "	.set	noat						\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 92 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 93 | "	mfc0	$1, $2, 1					\n" | 
|  | 94 | "	ori	$1, 0x400					\n" | 
|  | 95 | "	.set	noreorder					\n" | 
|  | 96 | "	mtc0	$1, $2, 1					\n" | 
|  | 97 | #elif defined(CONFIG_CPU_MIPSR2) | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 98 | "	di							\n" | 
|  | 99 | #else | 
|  | 100 | "	mfc0	$1,$12						\n" | 
| Atsushi Nemoto | c226f26 | 2006-02-03 01:34:01 +0900 | [diff] [blame] | 101 | "	ori	$1,0x1f						\n" | 
|  | 102 | "	xori	$1,0x1f						\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 103 | "	.set	noreorder					\n" | 
|  | 104 | "	mtc0	$1,$12						\n" | 
|  | 105 | #endif | 
|  | 106 | "	irq_disable_hazard					\n" | 
|  | 107 | "	.set	pop						\n" | 
|  | 108 | "	.endm							\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 110 | static inline void raw_local_irq_disable(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 111 | { | 
|  | 112 | __asm__ __volatile__( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 113 | "raw_local_irq_disable" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 114 | : /* no outputs */ | 
|  | 115 | : /* no inputs */ | 
|  | 116 | : "memory"); | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | __asm__ ( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 120 | "	.macro	raw_local_save_flags flags			\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 121 | "	.set	push						\n" | 
|  | 122 | "	.set	reorder						\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 123 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 124 | "	mfc0	\\flags, $2, 1					\n" | 
|  | 125 | #else | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 126 | "	mfc0	\\flags, $12					\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 127 | #endif | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 128 | "	.set	pop						\n" | 
|  | 129 | "	.endm							\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 130 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 131 | #define raw_local_save_flags(x)						\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 132 | __asm__ __volatile__(							\ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 133 | "raw_local_save_flags %0"					\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 134 | : "=r" (x)) | 
|  | 135 |  | 
|  | 136 | __asm__ ( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 137 | "	.macro	raw_local_irq_save result			\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 138 | "	.set	push						\n" | 
|  | 139 | "	.set	reorder						\n" | 
|  | 140 | "	.set	noat						\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 141 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 142 | "	mfc0	\\result, $2, 1					\n" | 
|  | 143 | "	ori	$1, \\result, 0x400				\n" | 
|  | 144 | "	.set	noreorder					\n" | 
|  | 145 | "	mtc0	$1, $2, 1					\n" | 
|  | 146 | "	andi	\\result, \\result, 0x400			\n" | 
|  | 147 | #elif defined(CONFIG_CPU_MIPSR2) | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 148 | "	di	\\result					\n" | 
| Maxime Bizon | 1526525 | 2005-12-20 06:32:19 +0100 | [diff] [blame] | 149 | "	andi	\\result, 1					\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 150 | #else | 
|  | 151 | "	mfc0	\\result, $12					\n" | 
| Atsushi Nemoto | c226f26 | 2006-02-03 01:34:01 +0900 | [diff] [blame] | 152 | "	ori	$1, \\result, 0x1f				\n" | 
|  | 153 | "	xori	$1, 0x1f					\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 154 | "	.set	noreorder					\n" | 
|  | 155 | "	mtc0	$1, $12						\n" | 
|  | 156 | #endif | 
|  | 157 | "	irq_disable_hazard					\n" | 
|  | 158 | "	.set	pop						\n" | 
|  | 159 | "	.endm							\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 161 | #define raw_local_irq_save(x)						\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 162 | __asm__ __volatile__(							\ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 163 | "raw_local_irq_save\t%0"					\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 164 | : "=r" (x)							\ | 
|  | 165 | : /* no inputs */						\ | 
|  | 166 | : "memory") | 
|  | 167 |  | 
|  | 168 | __asm__ ( | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 169 | "	.macro	raw_local_irq_restore flags			\n" | 
| Ralf Baechle | 2e66fe2 | 2006-01-30 16:48:26 +0000 | [diff] [blame] | 170 | "	.set	push						\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 171 | "	.set	noreorder					\n" | 
|  | 172 | "	.set	noat						\n" | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 173 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 174 | "mfc0	$1, $2, 1						\n" | 
|  | 175 | "andi	\\flags, 0x400						\n" | 
|  | 176 | "ori	$1, 0x400						\n" | 
|  | 177 | "xori	$1, 0x400						\n" | 
|  | 178 | "or	\\flags, $1						\n" | 
|  | 179 | "mtc0	\\flags, $2, 1						\n" | 
|  | 180 | #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 181 | /* | 
|  | 182 | * Slow, but doesn't suffer from a relativly unlikely race | 
|  | 183 | * condition we're having since days 1. | 
|  | 184 | */ | 
|  | 185 | "	beqz	\\flags, 1f					\n" | 
|  | 186 | "	 di							\n" | 
|  | 187 | "	ei							\n" | 
|  | 188 | "1:								\n" | 
| Ralf Baechle | ec917c2c | 2005-10-07 16:58:15 +0100 | [diff] [blame] | 189 | #elif defined(CONFIG_CPU_MIPSR2) | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 190 | /* | 
|  | 191 | * Fast, dangerous.  Life is fun, life is good. | 
|  | 192 | */ | 
|  | 193 | "	mfc0	$1, $12						\n" | 
|  | 194 | "	ins	$1, \\flags, 0, 1				\n" | 
|  | 195 | "	mtc0	$1, $12						\n" | 
|  | 196 | #else | 
|  | 197 | "	mfc0	$1, $12						\n" | 
|  | 198 | "	andi	\\flags, 1					\n" | 
| Atsushi Nemoto | c226f26 | 2006-02-03 01:34:01 +0900 | [diff] [blame] | 199 | "	ori	$1, 0x1f					\n" | 
|  | 200 | "	xori	$1, 0x1f					\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 201 | "	or	\\flags, $1					\n" | 
|  | 202 | "	mtc0	\\flags, $12					\n" | 
|  | 203 | #endif | 
|  | 204 | "	irq_disable_hazard					\n" | 
| Ralf Baechle | 2e66fe2 | 2006-01-30 16:48:26 +0000 | [diff] [blame] | 205 | "	.set	pop						\n" | 
| Ralf Baechle | ff88f8a | 2005-07-12 14:54:31 +0000 | [diff] [blame] | 206 | "	.endm							\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 207 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 208 | #define raw_local_irq_restore(flags)					\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 209 | do {									\ | 
|  | 210 | unsigned long __tmp1;						\ | 
|  | 211 | \ | 
|  | 212 | __asm__ __volatile__(						\ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 213 | "raw_local_irq_restore\t%0"				\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 214 | : "=r" (__tmp1)						\ | 
|  | 215 | : "0" (flags)						\ | 
|  | 216 | : "memory");						\ | 
| Ralf Baechle | ac8be95 | 2007-01-20 00:18:01 +0000 | [diff] [blame] | 217 | irq_restore_epilog(flags);					\ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 218 | } while(0) | 
|  | 219 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 220 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 221 | { | 
|  | 222 | #ifdef CONFIG_MIPS_MT_SMTC | 
|  | 223 | /* | 
|  | 224 | * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU | 
|  | 225 | */ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 226 | return flags & 0x400; | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 227 | #else | 
| Ralf Baechle | 41c594a | 2006-04-05 09:45:45 +0100 | [diff] [blame] | 228 | return !(flags & 1); | 
|  | 229 | #endif | 
|  | 230 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 231 |  | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 232 | #endif | 
|  | 233 |  | 
|  | 234 | /* | 
|  | 235 | * Do the CPU's IRQ-state tracing from assembly code. | 
|  | 236 | */ | 
|  | 237 | #ifdef CONFIG_TRACE_IRQFLAGS | 
| Atsushi Nemoto | eae6c0d | 2006-09-26 23:43:40 +0900 | [diff] [blame] | 238 | /* Reload some registers clobbered by trace_hardirqs_on */ | 
|  | 239 | #ifdef CONFIG_64BIT | 
|  | 240 | # define TRACE_IRQS_RELOAD_REGS						\ | 
|  | 241 | LONG_L	$11, PT_R11(sp);					\ | 
|  | 242 | LONG_L	$10, PT_R10(sp);					\ | 
|  | 243 | LONG_L	$9, PT_R9(sp);						\ | 
|  | 244 | LONG_L	$8, PT_R8(sp);						\ | 
|  | 245 | LONG_L	$7, PT_R7(sp);						\ | 
|  | 246 | LONG_L	$6, PT_R6(sp);						\ | 
|  | 247 | LONG_L	$5, PT_R5(sp);						\ | 
|  | 248 | LONG_L	$4, PT_R4(sp);						\ | 
|  | 249 | LONG_L	$2, PT_R2(sp) | 
|  | 250 | #else | 
|  | 251 | # define TRACE_IRQS_RELOAD_REGS						\ | 
|  | 252 | LONG_L	$7, PT_R7(sp);						\ | 
|  | 253 | LONG_L	$6, PT_R6(sp);						\ | 
|  | 254 | LONG_L	$5, PT_R5(sp);						\ | 
|  | 255 | LONG_L	$4, PT_R4(sp);						\ | 
|  | 256 | LONG_L	$2, PT_R2(sp) | 
|  | 257 | #endif | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 258 | # define TRACE_IRQS_ON							\ | 
| Atsushi Nemoto | eae6c0d | 2006-09-26 23:43:40 +0900 | [diff] [blame] | 259 | CLI;	/* make sure trace_hardirqs_on() is called in kernel level */ \ | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 260 | jal	trace_hardirqs_on | 
| Atsushi Nemoto | eae6c0d | 2006-09-26 23:43:40 +0900 | [diff] [blame] | 261 | # define TRACE_IRQS_ON_RELOAD						\ | 
|  | 262 | TRACE_IRQS_ON;							\ | 
|  | 263 | TRACE_IRQS_RELOAD_REGS | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 264 | # define TRACE_IRQS_OFF							\ | 
|  | 265 | jal	trace_hardirqs_off | 
|  | 266 | #else | 
|  | 267 | # define TRACE_IRQS_ON | 
| Atsushi Nemoto | eae6c0d | 2006-09-26 23:43:40 +0900 | [diff] [blame] | 268 | # define TRACE_IRQS_ON_RELOAD | 
| Ralf Baechle | 192ef36 | 2006-07-07 14:07:18 +0100 | [diff] [blame] | 269 | # define TRACE_IRQS_OFF | 
|  | 270 | #endif | 
|  | 271 |  | 
|  | 272 | #endif /* _ASM_IRQFLAGS_H */ |