1 /* 2 * include/asm-i386/irqflags.h 3 * 4 * IRQ flags handling 5 * 6 * This file gets included from lowlevel asm headers too, to provide 7 * wrapped versions of the local_irq_*() APIs, based on the 8 * raw_local_irq_*() functions from the lowlevel headers. 9 */ 10 #ifndef _ASM_IRQFLAGS_H 11 #define _ASM_IRQFLAGS_H 12 #include <asm/processor-flags.h> 13 14 #ifndef __ASSEMBLY__ 15 static inline unsigned long native_save_fl(void) 16 { 17 unsigned long f; 18 asm volatile("pushfl ; popl %0":"=g" (f): /* no input */); 19 return f; 20 } 21 22 static inline void native_restore_fl(unsigned long f) 23 { 24 asm volatile("pushl %0 ; popfl": /* no output */ 25 :"g" (f) 26 :"memory", "cc"); 27 } 28 29 static inline void native_irq_disable(void) 30 { 31 asm volatile("cli": : :"memory"); 32 } 33 34 static inline void native_irq_enable(void) 35 { 36 asm volatile("sti": : :"memory"); 37 } 38 39 static inline void native_safe_halt(void) 40 { 41 asm volatile("sti; hlt": : :"memory"); 42 } 43 44 static inline void native_halt(void) 45 { 46 asm volatile("hlt": : :"memory"); 47 } 48 #endif /* __ASSEMBLY__ */ 49 50 #ifdef CONFIG_PARAVIRT 51 #include <asm/paravirt.h> 52 #else 53 #ifndef __ASSEMBLY__ 54 55 static inline unsigned long __raw_local_save_flags(void) 56 { 57 return native_save_fl(); 58 } 59 60 static inline void raw_local_irq_restore(unsigned long flags) 61 { 62 native_restore_fl(flags); 63 } 64 65 static inline void raw_local_irq_disable(void) 66 { 67 native_irq_disable(); 68 } 69 70 static inline void raw_local_irq_enable(void) 71 { 72 native_irq_enable(); 73 } 74 75 /* 76 * Used in the idle loop; sti takes one instruction cycle 77 * to complete: 78 */ 79 static inline void raw_safe_halt(void) 80 { 81 native_safe_halt(); 82 } 83 84 /* 85 * Used when interrupts are already enabled or to 86 * shutdown the processor: 87 */ 88 static inline void halt(void) 89 { 90 native_halt(); 91 } 92 93 /* 94 * For spinlocks, etc: 95 */ 96 static inline unsigned long __raw_local_irq_save(void) 97 { 98 unsigned long flags = __raw_local_save_flags(); 99 100 raw_local_irq_disable(); 101 102 return flags; 103 } 104 105 #else 106 #define DISABLE_INTERRUPTS(clobbers) cli 107 #define ENABLE_INTERRUPTS(clobbers) sti 108 #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit 109 #define INTERRUPT_RETURN iret 110 #define GET_CR0_INTO_EAX movl %cr0, %eax 111 #endif /* __ASSEMBLY__ */ 112 #endif /* CONFIG_PARAVIRT */ 113 114 #ifndef __ASSEMBLY__ 115 #define raw_local_save_flags(flags) \ 116 do { (flags) = __raw_local_save_flags(); } while (0) 117 118 #define raw_local_irq_save(flags) \ 119 do { (flags) = __raw_local_irq_save(); } while (0) 120 121 static inline int raw_irqs_disabled_flags(unsigned long flags) 122 { 123 return !(flags & X86_EFLAGS_IF); 124 } 125 126 static inline int raw_irqs_disabled(void) 127 { 128 unsigned long flags = __raw_local_save_flags(); 129 130 return raw_irqs_disabled_flags(flags); 131 } 132 133 /* 134 * makes the traced hardirq state match with the machine state 135 * 136 * should be a rarely used function, only in places where its 137 * otherwise impossible to know the irq state, like in traps. 138 */ 139 static inline void trace_hardirqs_fixup_flags(unsigned long flags) 140 { 141 if (raw_irqs_disabled_flags(flags)) 142 trace_hardirqs_off(); 143 else 144 trace_hardirqs_on(); 145 } 146 147 static inline void trace_hardirqs_fixup(void) 148 { 149 unsigned long flags = __raw_local_save_flags(); 150 151 trace_hardirqs_fixup_flags(flags); 152 } 153 #endif /* __ASSEMBLY__ */ 154 155 /* 156 * Do the CPU's IRQ-state tracing from assembly code. We call a 157 * C function, so save all the C-clobbered registers: 158 */ 159 #ifdef CONFIG_TRACE_IRQFLAGS 160 161 # define TRACE_IRQS_ON \ 162 pushl %eax; \ 163 pushl %ecx; \ 164 pushl %edx; \ 165 call trace_hardirqs_on; \ 166 popl %edx; \ 167 popl %ecx; \ 168 popl %eax; 169 170 # define TRACE_IRQS_OFF \ 171 pushl %eax; \ 172 pushl %ecx; \ 173 pushl %edx; \ 174 call trace_hardirqs_off; \ 175 popl %edx; \ 176 popl %ecx; \ 177 popl %eax; 178 179 #else 180 # define TRACE_IRQS_ON 181 # define TRACE_IRQS_OFF 182 #endif 183 184 #ifdef CONFIG_DEBUG_LOCK_ALLOC 185 # define LOCKDEP_SYS_EXIT \ 186 pushl %eax; \ 187 pushl %ecx; \ 188 pushl %edx; \ 189 call lockdep_sys_exit; \ 190 popl %edx; \ 191 popl %ecx; \ 192 popl %eax; 193 #else 194 # define LOCKDEP_SYS_EXIT 195 #endif 196 197 #endif 198