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__ 15static 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 22static 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 29static inline void native_irq_disable(void) 30{ 31 asm volatile("cli": : :"memory"); 32} 33 34static inline void native_irq_enable(void) 35{ 36 asm volatile("sti": : :"memory"); 37} 38 39static inline void native_safe_halt(void) 40{ 41 asm volatile("sti; hlt": : :"memory"); 42} 43 44static 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 55static inline unsigned long __raw_local_save_flags(void) 56{ 57 return native_save_fl(); 58} 59 60static inline void raw_local_irq_restore(unsigned long flags) 61{ 62 native_restore_fl(flags); 63} 64 65static inline void raw_local_irq_disable(void) 66{ 67 native_irq_disable(); 68} 69 70static 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 */ 79static 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 */ 88static inline void halt(void) 89{ 90 native_halt(); 91} 92 93/* 94 * For spinlocks, etc: 95 */ 96static 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 121static inline int raw_irqs_disabled_flags(unsigned long flags) 122{ 123 return !(flags & X86_EFLAGS_IF); 124} 125 126static 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 */ 139static 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 147static 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