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