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