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_MIPSR2) || defined (CONFIG_CPU_MIPSR6) 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_LOONGSON3) 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_MIPSR2 || CONFIG_CPU_MIPSR6 */ 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_MIPSR2) || defined(CONFIG_CPU_MIPSR6) 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 #endif /* #ifndef __ASSEMBLY__ */ 141 142 /* 143 * Do the CPU's IRQ-state tracing from assembly code. 144 */ 145 #ifdef CONFIG_TRACE_IRQFLAGS 146 /* Reload some registers clobbered by trace_hardirqs_on */ 147 #ifdef CONFIG_64BIT 148 # define TRACE_IRQS_RELOAD_REGS \ 149 LONG_L $11, PT_R11(sp); \ 150 LONG_L $10, PT_R10(sp); \ 151 LONG_L $9, PT_R9(sp); \ 152 LONG_L $8, PT_R8(sp); \ 153 LONG_L $7, PT_R7(sp); \ 154 LONG_L $6, PT_R6(sp); \ 155 LONG_L $5, PT_R5(sp); \ 156 LONG_L $4, PT_R4(sp); \ 157 LONG_L $2, PT_R2(sp) 158 #else 159 # define TRACE_IRQS_RELOAD_REGS \ 160 LONG_L $7, PT_R7(sp); \ 161 LONG_L $6, PT_R6(sp); \ 162 LONG_L $5, PT_R5(sp); \ 163 LONG_L $4, PT_R4(sp); \ 164 LONG_L $2, PT_R2(sp) 165 #endif 166 # define TRACE_IRQS_ON \ 167 CLI; /* make sure trace_hardirqs_on() is called in kernel level */ \ 168 jal trace_hardirqs_on 169 # define TRACE_IRQS_ON_RELOAD \ 170 TRACE_IRQS_ON; \ 171 TRACE_IRQS_RELOAD_REGS 172 # define TRACE_IRQS_OFF \ 173 jal trace_hardirqs_off 174 #else 175 # define TRACE_IRQS_ON 176 # define TRACE_IRQS_ON_RELOAD 177 # define TRACE_IRQS_OFF 178 #endif 179 180 #endif /* _ASM_IRQFLAGS_H */ 181