Line data Source code
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 18 : unsigned long flags;
14 :
15 : /*
16 : * "=rm" is safe here, because "pop" adjusts the stack before
17 : * it evaluates its effective address -- this is part of the
18 : * documented behavior of the "pop" instruction.
19 : */
20 18 : asm volatile("# __raw_save_flags\n\t"
21 : "pushf ; pop %0"
22 : : "=rm" (flags)
23 : : /* no input */
24 : : "memory");
25 :
26 18 : return flags;
27 : }
28 :
29 : static inline void native_restore_fl(unsigned long flags)
30 : {
31 : asm volatile("push %0 ; popf"
32 : : /* no output */
33 : :"g" (flags)
34 : :"memory", "cc");
35 : }
36 :
37 : static inline void native_irq_disable(void)
38 : {
39 : asm volatile("cli": : :"memory");
40 : }
41 :
42 : static inline void native_irq_enable(void)
43 : {
44 2 : asm volatile("sti": : :"memory");
45 2 : }
46 :
47 : static inline void native_safe_halt(void)
48 : {
49 : asm volatile("sti; hlt": : :"memory");
50 : }
51 :
52 : static inline void native_halt(void)
53 : {
54 : asm volatile("hlt": : :"memory");
55 : }
56 :
57 : #endif
58 :
59 : #ifdef CONFIG_PARAVIRT
60 : #include <asm/paravirt.h>
61 : #else
62 : #ifndef __ASSEMBLY__
63 :
64 : static inline unsigned long __raw_local_save_flags(void)
65 : {
66 72 : return native_save_fl();
67 : }
68 :
69 : static inline void raw_local_irq_restore(unsigned long flags)
70 : {
71 : native_restore_fl(flags);
72 : }
73 :
74 : static inline void raw_local_irq_disable(void)
75 : {
76 : native_irq_disable();
77 : }
78 :
79 : static inline void raw_local_irq_enable(void)
80 : {
81 4 : native_irq_enable();
82 2 : }
83 :
84 : /*
85 : * Used in the idle loop; sti takes one instruction cycle
86 : * to complete:
87 : */
88 : static inline void raw_safe_halt(void)
89 : {
90 : native_safe_halt();
91 : }
92 :
93 : /*
94 : * Used when interrupts are already enabled or to
95 : * shutdown the processor:
96 : */
97 : static inline void halt(void)
98 : {
99 : native_halt();
100 : }
101 :
102 : /*
103 : * For spinlocks, etc:
104 : */
105 : static inline unsigned long __raw_local_irq_save(void)
106 : {
107 : unsigned long flags = __raw_local_save_flags();
108 :
109 : raw_local_irq_disable();
110 :
111 : return flags;
112 : }
113 : #else
114 :
115 : #define ENABLE_INTERRUPTS(x) sti
116 : #define DISABLE_INTERRUPTS(x) cli
117 :
118 : #ifdef CONFIG_X86_64
119 : #define SWAPGS swapgs
120 : /*
121 : * Currently paravirt can't handle swapgs nicely when we
122 : * don't have a stack we can rely on (such as a user space
123 : * stack). So we either find a way around these or just fault
124 : * and emulate if a guest tries to call swapgs directly.
125 : *
126 : * Either way, this is a good way to document that we don't
127 : * have a reliable stack. x86_64 only.
128 : */
129 : #define SWAPGS_UNSAFE_STACK swapgs
130 :
131 : #define PARAVIRT_ADJUST_EXCEPTION_FRAME /* */
132 :
133 : #define INTERRUPT_RETURN iretq
134 : #define USERGS_SYSRET64 \
135 : swapgs; \
136 : sysretq;
137 : #define USERGS_SYSRET32 \
138 : swapgs; \
139 : sysretl
140 : #define ENABLE_INTERRUPTS_SYSEXIT32 \
141 : swapgs; \
142 : sti; \
143 : sysexit
144 :
145 : #else
146 : #define INTERRUPT_RETURN iret
147 : #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit
148 : #define GET_CR0_INTO_EAX movl %cr0, %eax
149 : #endif
150 :
151 :
152 : #endif /* __ASSEMBLY__ */
153 : #endif /* CONFIG_PARAVIRT */
154 :
155 : #ifndef __ASSEMBLY__
156 : #define raw_local_save_flags(flags) \
157 : do { (flags) = __raw_local_save_flags(); } while (0)
158 :
159 : #define raw_local_irq_save(flags) \
160 : do { (flags) = __raw_local_irq_save(); } while (0)
161 :
162 : static inline int raw_irqs_disabled_flags(unsigned long flags)
163 : {
164 18 : return !(flags & X86_EFLAGS_IF);
165 : }
166 :
167 : static inline int raw_irqs_disabled(void)
168 : {
169 : unsigned long flags = __raw_local_save_flags();
170 :
171 : return raw_irqs_disabled_flags(flags);
172 : }
173 :
174 : #else
175 :
176 : #ifdef CONFIG_X86_64
177 : #define ARCH_LOCKDEP_SYS_EXIT call lockdep_sys_exit_thunk
178 : #define ARCH_LOCKDEP_SYS_EXIT_IRQ \
179 : TRACE_IRQS_ON; \
180 : sti; \
181 : SAVE_REST; \
182 : LOCKDEP_SYS_EXIT; \
183 : RESTORE_REST; \
184 : cli; \
185 : TRACE_IRQS_OFF;
186 :
187 : #else
188 : #define ARCH_LOCKDEP_SYS_EXIT \
189 : pushl %eax; \
190 : pushl %ecx; \
191 : pushl %edx; \
192 : call lockdep_sys_exit; \
193 : popl %edx; \
194 : popl %ecx; \
195 : popl %eax;
196 :
197 : #define ARCH_LOCKDEP_SYS_EXIT_IRQ
198 : #endif
199 :
200 : #ifdef CONFIG_TRACE_IRQFLAGS
201 : # define TRACE_IRQS_ON call trace_hardirqs_on_thunk;
202 : # define TRACE_IRQS_OFF call trace_hardirqs_off_thunk;
203 : #else
204 : # define TRACE_IRQS_ON
205 : # define TRACE_IRQS_OFF
206 : #endif
207 : #ifdef CONFIG_DEBUG_LOCK_ALLOC
208 : # define LOCKDEP_SYS_EXIT ARCH_LOCKDEP_SYS_EXIT
209 : # define LOCKDEP_SYS_EXIT_IRQ ARCH_LOCKDEP_SYS_EXIT_IRQ
210 : # else
211 : # define LOCKDEP_SYS_EXIT
212 : # define LOCKDEP_SYS_EXIT_IRQ
213 : # endif
214 :
215 : #endif /* __ASSEMBLY__ */
216 : #endif
|