| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 1 | #ifndef _X86_IRQFLAGS_H_ | 
|  | 2 | #define _X86_IRQFLAGS_H_ | 
|  | 3 |  | 
|  | 4 | #include <asm/processor-flags.h> | 
|  | 5 |  | 
|  | 6 | #ifndef __ASSEMBLY__ | 
|  | 7 | /* | 
|  | 8 | * Interrupt control: | 
|  | 9 | */ | 
|  | 10 |  | 
|  | 11 | static inline unsigned long native_save_fl(void) | 
|  | 12 | { | 
|  | 13 | unsigned long flags; | 
|  | 14 |  | 
| Joe Perches | cf7f719 | 2008-03-23 01:02:30 -0700 | [diff] [blame] | 15 | asm volatile("# __raw_save_flags\n\t" | 
|  | 16 | "pushf ; pop %0" | 
|  | 17 | : "=g" (flags) | 
|  | 18 | : /* no input */ | 
|  | 19 | : "memory"); | 
| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 20 |  | 
|  | 21 | return flags; | 
|  | 22 | } | 
|  | 23 |  | 
|  | 24 | static inline void native_restore_fl(unsigned long flags) | 
|  | 25 | { | 
| Joe Perches | cf7f719 | 2008-03-23 01:02:30 -0700 | [diff] [blame] | 26 | asm volatile("push %0 ; popf" | 
|  | 27 | : /* no output */ | 
|  | 28 | :"g" (flags) | 
|  | 29 | :"memory", "cc"); | 
| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 30 | } | 
|  | 31 |  | 
|  | 32 | static inline void native_irq_disable(void) | 
|  | 33 | { | 
|  | 34 | asm volatile("cli": : :"memory"); | 
|  | 35 | } | 
|  | 36 |  | 
|  | 37 | static inline void native_irq_enable(void) | 
|  | 38 | { | 
|  | 39 | asm volatile("sti": : :"memory"); | 
|  | 40 | } | 
|  | 41 |  | 
|  | 42 | static inline void native_safe_halt(void) | 
|  | 43 | { | 
|  | 44 | asm volatile("sti; hlt": : :"memory"); | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | static inline void native_halt(void) | 
|  | 48 | { | 
|  | 49 | asm volatile("hlt": : :"memory"); | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | #endif | 
|  | 53 |  | 
|  | 54 | #ifdef CONFIG_PARAVIRT | 
|  | 55 | #include <asm/paravirt.h> | 
| Thomas Gleixner | 96a388d | 2007-10-11 11:20:03 +0200 | [diff] [blame] | 56 | #else | 
| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 57 | #ifndef __ASSEMBLY__ | 
|  | 58 |  | 
|  | 59 | static inline unsigned long __raw_local_save_flags(void) | 
|  | 60 | { | 
|  | 61 | return native_save_fl(); | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | static inline void raw_local_irq_restore(unsigned long flags) | 
|  | 65 | { | 
|  | 66 | native_restore_fl(flags); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | static inline void raw_local_irq_disable(void) | 
|  | 70 | { | 
|  | 71 | native_irq_disable(); | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 | static inline void raw_local_irq_enable(void) | 
|  | 75 | { | 
|  | 76 | native_irq_enable(); | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | /* | 
|  | 80 | * Used in the idle loop; sti takes one instruction cycle | 
|  | 81 | * to complete: | 
|  | 82 | */ | 
|  | 83 | static inline void raw_safe_halt(void) | 
|  | 84 | { | 
|  | 85 | native_safe_halt(); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | /* | 
|  | 89 | * Used when interrupts are already enabled or to | 
|  | 90 | * shutdown the processor: | 
|  | 91 | */ | 
|  | 92 | static inline void halt(void) | 
|  | 93 | { | 
|  | 94 | native_halt(); | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | /* | 
|  | 98 | * For spinlocks, etc: | 
|  | 99 | */ | 
|  | 100 | static inline unsigned long __raw_local_irq_save(void) | 
|  | 101 | { | 
|  | 102 | unsigned long flags = __raw_local_save_flags(); | 
|  | 103 |  | 
|  | 104 | raw_local_irq_disable(); | 
|  | 105 |  | 
|  | 106 | return flags; | 
|  | 107 | } | 
|  | 108 | #else | 
|  | 109 |  | 
|  | 110 | #define ENABLE_INTERRUPTS(x)	sti | 
|  | 111 | #define DISABLE_INTERRUPTS(x)	cli | 
|  | 112 |  | 
|  | 113 | #ifdef CONFIG_X86_64 | 
|  | 114 | #define INTERRUPT_RETURN	iretq | 
|  | 115 | #define ENABLE_INTERRUPTS_SYSCALL_RET			\ | 
|  | 116 | movq	%gs:pda_oldrsp, %rsp;	\ | 
|  | 117 | swapgs;				\ | 
|  | 118 | sysretq; | 
|  | 119 | #else | 
|  | 120 | #define INTERRUPT_RETURN		iret | 
|  | 121 | #define ENABLE_INTERRUPTS_SYSCALL_RET	sti; sysexit | 
|  | 122 | #define GET_CR0_INTO_EAX		movl %cr0, %eax | 
|  | 123 | #endif | 
|  | 124 |  | 
|  | 125 |  | 
|  | 126 | #endif /* __ASSEMBLY__ */ | 
|  | 127 | #endif /* CONFIG_PARAVIRT */ | 
|  | 128 |  | 
|  | 129 | #ifndef __ASSEMBLY__ | 
| Joe Perches | cf7f719 | 2008-03-23 01:02:30 -0700 | [diff] [blame] | 130 | #define raw_local_save_flags(flags)				\ | 
|  | 131 | do { (flags) = __raw_local_save_flags(); } while (0) | 
| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 132 |  | 
| Joe Perches | cf7f719 | 2008-03-23 01:02:30 -0700 | [diff] [blame] | 133 | #define raw_local_irq_save(flags)				\ | 
|  | 134 | do { (flags) = __raw_local_irq_save(); } while (0) | 
| Glauber de Oliveira Costa | 6abcd98 | 2008-01-30 13:30:33 +0100 | [diff] [blame] | 135 |  | 
|  | 136 | static inline int raw_irqs_disabled_flags(unsigned long flags) | 
|  | 137 | { | 
|  | 138 | return !(flags & X86_EFLAGS_IF); | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | static inline int raw_irqs_disabled(void) | 
|  | 142 | { | 
|  | 143 | unsigned long flags = __raw_local_save_flags(); | 
|  | 144 |  | 
|  | 145 | return raw_irqs_disabled_flags(flags); | 
|  | 146 | } | 
|  | 147 |  | 
|  | 148 | /* | 
|  | 149 | * makes the traced hardirq state match with the machine state | 
|  | 150 | * | 
|  | 151 | * should be a rarely used function, only in places where its | 
|  | 152 | * otherwise impossible to know the irq state, like in traps. | 
|  | 153 | */ | 
|  | 154 | static inline void trace_hardirqs_fixup_flags(unsigned long flags) | 
|  | 155 | { | 
|  | 156 | if (raw_irqs_disabled_flags(flags)) | 
|  | 157 | trace_hardirqs_off(); | 
|  | 158 | else | 
|  | 159 | trace_hardirqs_on(); | 
|  | 160 | } | 
|  | 161 |  | 
|  | 162 | static inline void trace_hardirqs_fixup(void) | 
|  | 163 | { | 
|  | 164 | unsigned long flags = __raw_local_save_flags(); | 
|  | 165 |  | 
|  | 166 | trace_hardirqs_fixup_flags(flags); | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | #else | 
|  | 170 |  | 
|  | 171 | #ifdef CONFIG_X86_64 | 
|  | 172 | /* | 
|  | 173 | * Currently paravirt can't handle swapgs nicely when we | 
|  | 174 | * don't have a stack we can rely on (such as a user space | 
|  | 175 | * stack).  So we either find a way around these or just fault | 
|  | 176 | * and emulate if a guest tries to call swapgs directly. | 
|  | 177 | * | 
|  | 178 | * Either way, this is a good way to document that we don't | 
|  | 179 | * have a reliable stack. x86_64 only. | 
|  | 180 | */ | 
|  | 181 | #define SWAPGS_UNSAFE_STACK	swapgs | 
|  | 182 | #define ARCH_TRACE_IRQS_ON		call trace_hardirqs_on_thunk | 
|  | 183 | #define ARCH_TRACE_IRQS_OFF		call trace_hardirqs_off_thunk | 
|  | 184 | #define ARCH_LOCKDEP_SYS_EXIT		call lockdep_sys_exit_thunk | 
|  | 185 | #define ARCH_LOCKDEP_SYS_EXIT_IRQ	\ | 
|  | 186 | TRACE_IRQS_ON; \ | 
|  | 187 | sti; \ | 
|  | 188 | SAVE_REST; \ | 
|  | 189 | LOCKDEP_SYS_EXIT; \ | 
|  | 190 | RESTORE_REST; \ | 
|  | 191 | cli; \ | 
|  | 192 | TRACE_IRQS_OFF; | 
|  | 193 |  | 
|  | 194 | #else | 
|  | 195 | #define ARCH_TRACE_IRQS_ON			\ | 
|  | 196 | pushl %eax;				\ | 
|  | 197 | pushl %ecx;				\ | 
|  | 198 | pushl %edx;				\ | 
|  | 199 | call trace_hardirqs_on;			\ | 
|  | 200 | popl %edx;				\ | 
|  | 201 | popl %ecx;				\ | 
|  | 202 | popl %eax; | 
|  | 203 |  | 
|  | 204 | #define ARCH_TRACE_IRQS_OFF			\ | 
|  | 205 | pushl %eax;				\ | 
|  | 206 | pushl %ecx;				\ | 
|  | 207 | pushl %edx;				\ | 
|  | 208 | call trace_hardirqs_off;		\ | 
|  | 209 | popl %edx;				\ | 
|  | 210 | popl %ecx;				\ | 
|  | 211 | popl %eax; | 
|  | 212 |  | 
|  | 213 | #define ARCH_LOCKDEP_SYS_EXIT			\ | 
|  | 214 | pushl %eax;				\ | 
|  | 215 | pushl %ecx;				\ | 
|  | 216 | pushl %edx;				\ | 
|  | 217 | call lockdep_sys_exit;			\ | 
|  | 218 | popl %edx;				\ | 
|  | 219 | popl %ecx;				\ | 
|  | 220 | popl %eax; | 
|  | 221 |  | 
|  | 222 | #define ARCH_LOCKDEP_SYS_EXIT_IRQ | 
|  | 223 | #endif | 
|  | 224 |  | 
|  | 225 | #ifdef CONFIG_TRACE_IRQFLAGS | 
|  | 226 | #  define TRACE_IRQS_ON		ARCH_TRACE_IRQS_ON | 
|  | 227 | #  define TRACE_IRQS_OFF	ARCH_TRACE_IRQS_OFF | 
|  | 228 | #else | 
|  | 229 | #  define TRACE_IRQS_ON | 
|  | 230 | #  define TRACE_IRQS_OFF | 
|  | 231 | #endif | 
|  | 232 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 
|  | 233 | #  define LOCKDEP_SYS_EXIT	ARCH_LOCKDEP_SYS_EXIT | 
|  | 234 | #  define LOCKDEP_SYS_EXIT_IRQ	ARCH_LOCKDEP_SYS_EXIT_IRQ | 
|  | 235 | # else | 
|  | 236 | #  define LOCKDEP_SYS_EXIT | 
|  | 237 | #  define LOCKDEP_SYS_EXIT_IRQ | 
|  | 238 | # endif | 
|  | 239 |  | 
|  | 240 | #endif /* __ASSEMBLY__ */ | 
| Thomas Gleixner | 96a388d | 2007-10-11 11:20:03 +0200 | [diff] [blame] | 241 | #endif |