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 <asm/hazards.h> 18 19 #if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) 20 21 __asm__( 22 " .macro arch_local_irq_disable\n" 23 " .set push \n" 24 " .set noat \n" 25 " di \n" 26 " irq_disable_hazard \n" 27 " .set pop \n" 28 " .endm \n"); 29 30 static inline void arch_local_irq_disable(void) 31 { 32 __asm__ __volatile__( 33 "arch_local_irq_disable" 34 : /* no outputs */ 35 : /* no inputs */ 36 : "memory"); 37 } 38 39 40 __asm__( 41 " .macro arch_local_irq_save result \n" 42 " .set push \n" 43 " .set reorder \n" 44 " .set noat \n" 45 " di \\result \n" 46 " andi \\result, 1 \n" 47 " irq_disable_hazard \n" 48 " .set pop \n" 49 " .endm \n"); 50 51 static inline unsigned long arch_local_irq_save(void) 52 { 53 unsigned long flags; 54 asm volatile("arch_local_irq_save\t%0" 55 : "=r" (flags) 56 : /* no inputs */ 57 : "memory"); 58 return flags; 59 } 60 61 62 __asm__( 63 " .macro arch_local_irq_restore flags \n" 64 " .set push \n" 65 " .set noreorder \n" 66 " .set noat \n" 67 #if defined(CONFIG_IRQ_CPU) 68 /* 69 * Slow, but doesn't suffer from a relatively unlikely race 70 * condition we're having since days 1. 71 */ 72 " beqz \\flags, 1f \n" 73 " di \n" 74 " ei \n" 75 "1: \n" 76 #else 77 /* 78 * Fast, dangerous. Life is fun, life is good. 79 */ 80 " mfc0 $1, $12 \n" 81 " ins $1, \\flags, 0, 1 \n" 82 " mtc0 $1, $12 \n" 83 #endif 84 " irq_disable_hazard \n" 85 " .set pop \n" 86 " .endm \n"); 87 88 static inline void arch_local_irq_restore(unsigned long flags) 89 { 90 unsigned long __tmp1; 91 92 __asm__ __volatile__( 93 "arch_local_irq_restore\t%0" 94 : "=r" (__tmp1) 95 : "0" (flags) 96 : "memory"); 97 } 98 99 static inline void __arch_local_irq_restore(unsigned long flags) 100 { 101 unsigned long __tmp1; 102 103 __asm__ __volatile__( 104 "arch_local_irq_restore\t%0" 105 : "=r" (__tmp1) 106 : "0" (flags) 107 : "memory"); 108 } 109 #else 110 /* Functions that require preempt_{dis,en}able() are in mips-atomic.c */ 111 void arch_local_irq_disable(void); 112 unsigned long arch_local_irq_save(void); 113 void arch_local_irq_restore(unsigned long flags); 114 void __arch_local_irq_restore(unsigned long flags); 115 #endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */ 116 117 118 __asm__( 119 " .macro arch_local_irq_enable \n" 120 " .set push \n" 121 " .set reorder \n" 122 " .set noat \n" 123 #ifdef CONFIG_MIPS_MT_SMTC 124 " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" 125 " ori $1, 0x400 \n" 126 " xori $1, 0x400 \n" 127 " mtc0 $1, $2, 1 \n" 128 #elif defined(CONFIG_CPU_MIPSR2) 129 " ei \n" 130 #else 131 " mfc0 $1,$12 \n" 132 " ori $1,0x1f \n" 133 " xori $1,0x1e \n" 134 " mtc0 $1,$12 \n" 135 #endif 136 " irq_enable_hazard \n" 137 " .set pop \n" 138 " .endm"); 139 140 extern void smtc_ipi_replay(void); 141 142 static inline void arch_local_irq_enable(void) 143 { 144 #ifdef CONFIG_MIPS_MT_SMTC 145 /* 146 * SMTC kernel needs to do a software replay of queued 147 * IPIs, at the cost of call overhead on each local_irq_enable() 148 */ 149 smtc_ipi_replay(); 150 #endif 151 __asm__ __volatile__( 152 "arch_local_irq_enable" 153 : /* no outputs */ 154 : /* no inputs */ 155 : "memory"); 156 } 157 158 159 __asm__( 160 " .macro arch_local_save_flags flags \n" 161 " .set push \n" 162 " .set reorder \n" 163 #ifdef CONFIG_MIPS_MT_SMTC 164 " mfc0 \\flags, $2, 1 \n" 165 #else 166 " mfc0 \\flags, $12 \n" 167 #endif 168 " .set pop \n" 169 " .endm \n"); 170 171 static inline unsigned long arch_local_save_flags(void) 172 { 173 unsigned long flags; 174 asm volatile("arch_local_save_flags %0" : "=r" (flags)); 175 return flags; 176 } 177 178 179 static inline int arch_irqs_disabled_flags(unsigned long flags) 180 { 181 #ifdef CONFIG_MIPS_MT_SMTC 182 /* 183 * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU 184 */ 185 return flags & 0x400; 186 #else 187 return !(flags & 1); 188 #endif 189 } 190 191 #endif /* #ifndef __ASSEMBLY__ */ 192 193 /* 194 * Do the CPU's IRQ-state tracing from assembly code. 195 */ 196 #ifdef CONFIG_TRACE_IRQFLAGS 197 /* Reload some registers clobbered by trace_hardirqs_on */ 198 #ifdef CONFIG_64BIT 199 # define TRACE_IRQS_RELOAD_REGS \ 200 LONG_L $11, PT_R11(sp); \ 201 LONG_L $10, PT_R10(sp); \ 202 LONG_L $9, PT_R9(sp); \ 203 LONG_L $8, PT_R8(sp); \ 204 LONG_L $7, PT_R7(sp); \ 205 LONG_L $6, PT_R6(sp); \ 206 LONG_L $5, PT_R5(sp); \ 207 LONG_L $4, PT_R4(sp); \ 208 LONG_L $2, PT_R2(sp) 209 #else 210 # define TRACE_IRQS_RELOAD_REGS \ 211 LONG_L $7, PT_R7(sp); \ 212 LONG_L $6, PT_R6(sp); \ 213 LONG_L $5, PT_R5(sp); \ 214 LONG_L $4, PT_R4(sp); \ 215 LONG_L $2, PT_R2(sp) 216 #endif 217 # define TRACE_IRQS_ON \ 218 CLI; /* make sure trace_hardirqs_on() is called in kernel level */ \ 219 jal trace_hardirqs_on 220 # define TRACE_IRQS_ON_RELOAD \ 221 TRACE_IRQS_ON; \ 222 TRACE_IRQS_RELOAD_REGS 223 # define TRACE_IRQS_OFF \ 224 jal trace_hardirqs_off 225 #else 226 # define TRACE_IRQS_ON 227 # define TRACE_IRQS_ON_RELOAD 228 # define TRACE_IRQS_OFF 229 #endif 230 231 #endif /* _ASM_IRQFLAGS_H */ 232