1 #ifndef _ASM_IRQ_H
2 #define _ASM_IRQ_H
3
4
5
6
7
8
9
10
11
12 #include <linux/linkage.h>
13 #include <asm/segment.h>
14
15 #define NR_IRQS 16
16
17 extern void disable_irq(unsigned int);
18 extern void enable_irq(unsigned int);
19
20 #define __STR(x) #x
21 #define STR(x) __STR(x)
22
23 #define SAVE_ALL \
24 "cld\n\t" \
25 "push %gs\n\t" \
26 "push %fs\n\t" \
27 "push %es\n\t" \
28 "push %ds\n\t" \
29 "pushl %eax\n\t" \
30 "pushl %ebp\n\t" \
31 "pushl %edi\n\t" \
32 "pushl %esi\n\t" \
33 "pushl %edx\n\t" \
34 "pushl %ecx\n\t" \
35 "pushl %ebx\n\t" \
36 "movl $" STR(KERNEL_DS) ",%edx\n\t" \
37 "mov %dx,%ds\n\t" \
38 "mov %dx,%es\n\t" \
39 "movl $" STR(USER_DS) ",%edx\n\t" \
40 "mov %dx,%fs\n\t" \
41 "movl $0,%edx\n\t" \
42 "movl %edx,%db7\n\t"
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 #define SAVE_MOST \
59 "cld\n\t" \
60 "push %es\n\t" \
61 "push %ds\n\t" \
62 "pushl %eax\n\t" \
63 "pushl %edx\n\t" \
64 "pushl %ecx\n\t" \
65 "movl $" STR(KERNEL_DS) ",%edx\n\t" \
66 "mov %dx,%ds\n\t" \
67 "mov %dx,%es\n\t"
68
69 #define RESTORE_MOST \
70 "popl %ecx\n\t" \
71 "popl %edx\n\t" \
72 "popl %eax\n\t" \
73 "pop %ds\n\t" \
74 "pop %es\n\t" \
75 "iret"
76
77
78
79
80
81
82 #define ACK_FIRST(mask) \
83 "inb $0x21,%al\n\t" \
84 "jmp 1f\n" \
85 "1:\tjmp 1f\n" \
86 "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \
87 "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
88 "outb %al,$0x21\n\t" \
89 "jmp 1f\n" \
90 "1:\tjmp 1f\n" \
91 "1:\tmovb $0x20,%al\n\t" \
92 "outb %al,$0x20\n\t"
93
94 #define ACK_SECOND(mask) \
95 "inb $0xA1,%al\n\t" \
96 "jmp 1f\n" \
97 "1:\tjmp 1f\n" \
98 "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \
99 "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
100 "outb %al,$0xA1\n\t" \
101 "jmp 1f\n" \
102 "1:\tjmp 1f\n" \
103 "1:\tmovb $0x20,%al\n\t" \
104 "outb %al,$0xA0\n\t" \
105 "jmp 1f\n" \
106 "1:\tjmp 1f\n" \
107 "1:\toutb %al,$0x20\n\t"
108
109 #define UNBLK_FIRST(mask) \
110 "inb $0x21,%al\n\t" \
111 "jmp 1f\n" \
112 "1:\tjmp 1f\n" \
113 "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \
114 "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
115 "outb %al,$0x21\n\t"
116
117 #define UNBLK_SECOND(mask) \
118 "inb $0xA1,%al\n\t" \
119 "jmp 1f\n" \
120 "1:\tjmp 1f\n" \
121 "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
122 "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
123 "outb %al,$0xA1\n\t"
124
125 #define IRQ_NAME2(nr) nr##_interrupt(void)
126 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
127 #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
128 #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
129
130 #ifdef CONFIG_SMP
131
132 #define GET_PROCESSOR_ID \
133 "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
134 "movl 32(%edx), %eax\n\t" \
135 "shrl $24,%eax\n\t" \
136 "andb $0x0F,%al\n"
137
138 #define ENTER_KERNEL \
139 "pushl %eax\n\t" \
140 "pushl %edx\n\t" \
141 "pushfl\n\t" \
142 "cli\n\t" \
143 GET_PROCESSOR_ID \
144 "1: " \
145 "lock\n\t" \
146 "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
147 "jnc 3f\n\t" \
148 "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
149 "je 4f\n\t" \
150 "2: " \
151 "incl "SYMBOL_NAME_STR(smp_spins)"\n\t" \
152 "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
153 "jnc 5f\n\t" \
154 "lock\n\t" \
155 "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
156 "jnc 5f\n\t" \
157 "movl %cr3,%edx\n\t" \
158 "movl %edx,%cr3\n" \
159 "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
160 "jc 2b\n\t" \
161 "jmp 1b\n\t" \
162 "3: " \
163 "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
164 "4: " \
165 "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
166 "popfl\n\t" \
167 "popl %edx\n\t" \
168 "popl %eax\n\t"
169
170 #define LEAVE_KERNEL \
171 "pushfl\n\t" \
172 "cli\n\t" \
173 "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
174 "jnz 1f\n\t" \
175 "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
176 "lock\n\t" \
177 "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
178 "1: " \
179 "popfl\n\t"
180
181
182
183
184
185
186
187 #define BUILD_IRQ(chip,nr,mask) \
188 asmlinkage void IRQ_NAME(nr); \
189 asmlinkage void FAST_IRQ_NAME(nr); \
190 asmlinkage void BAD_IRQ_NAME(nr); \
191 __asm__( \
192 "\n"__ALIGN_STR"\n" \
193 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
194 "pushl $-"#nr"-2\n\t" \
195 SAVE_ALL \
196 ENTER_KERNEL \
197 ACK_##chip(mask) \
198 "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
199 "sti\n\t" \
200 "movl %esp,%ebx\n\t" \
201 "pushl %ebx\n\t" \
202 "pushl $" #nr "\n\t" \
203 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
204 "addl $8,%esp\n\t" \
205 "cli\n\t" \
206 UNBLK_##chip(mask) \
207 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
208 "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
209 "jmp ret_from_sys_call\n" \
210 "\n"__ALIGN_STR"\n" \
211 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
212 SAVE_MOST \
213 ENTER_KERNEL \
214 ACK_##chip(mask) \
215 "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
216 "pushl $" #nr "\n\t" \
217 "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
218 "addl $4,%esp\n\t" \
219 "cli\n\t" \
220 UNBLK_##chip(mask) \
221 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
222 LEAVE_KERNEL \
223 RESTORE_MOST \
224 "\n"__ALIGN_STR"\n" \
225 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
226 SAVE_MOST \
227 ENTER_KERNEL \
228 ACK_##chip(mask) \
229 LEAVE_KERNEL \
230 RESTORE_MOST);
231
232
233
234
235
236
237 #define BUILD_MSGIRQ(chip,nr,mask) \
238 asmlinkage void IRQ_NAME(nr); \
239 asmlinkage void FAST_IRQ_NAME(nr); \
240 asmlinkage void BAD_IRQ_NAME(nr); \
241 __asm__( \
242 "\n"__ALIGN_STR"\n" \
243 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
244 "pushl $-"#nr"-2\n\t" \
245 SAVE_ALL \
246 ENTER_KERNEL \
247 ACK_##chip(mask) \
248 "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
249 "sti\n\t" \
250 "movl %esp,%ebx\n\t" \
251 "pushl %ebx\n\t" \
252 "pushl $" #nr "\n\t" \
253 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
254 "addl $8,%esp\n\t" \
255 "cli\n\t" \
256 UNBLK_##chip(mask) \
257 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
258 "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
259 "jmp ret_from_sys_call\n" \
260 "\n"__ALIGN_STR"\n" \
261 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
262 SAVE_MOST \
263 ACK_##chip(mask) \
264 "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" \
265 "pushl $" #nr "\n\t" \
266 "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
267 "addl $4,%esp\n\t" \
268 "cli\n\t" \
269 UNBLK_##chip(mask) \
270 RESTORE_MOST \
271 "\n"__ALIGN_STR"\n" \
272 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
273 SAVE_MOST \
274 ACK_##chip(mask) \
275 RESTORE_MOST);
276
277 #define BUILD_RESCHEDIRQ(nr) \
278 asmlinkage void IRQ_NAME(nr); \
279 __asm__( \
280 "\n"__ALIGN_STR"\n" \
281 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
282 "pushl $-"#nr"-2\n\t" \
283 SAVE_ALL \
284 ENTER_KERNEL \
285 "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
286 "sti\n\t" \
287 "movl %esp,%ebx\n\t" \
288 "pushl %ebx\n\t" \
289 "pushl $" #nr "\n\t" \
290 "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
291 "addl $8,%esp\n\t" \
292 "cli\n\t" \
293 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
294 "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
295 "jmp ret_from_sys_call\n");
296 #else
297
298 #define BUILD_IRQ(chip,nr,mask) \
299 asmlinkage void IRQ_NAME(nr); \
300 asmlinkage void FAST_IRQ_NAME(nr); \
301 asmlinkage void BAD_IRQ_NAME(nr); \
302 __asm__( \
303 "\n"__ALIGN_STR"\n" \
304 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
305 "pushl $-"#nr"-2\n\t" \
306 SAVE_ALL \
307 ACK_##chip(mask) \
308 "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
309 "sti\n\t" \
310 "movl %esp,%ebx\n\t" \
311 "pushl %ebx\n\t" \
312 "pushl $" #nr "\n\t" \
313 "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
314 "addl $8,%esp\n\t" \
315 "cli\n\t" \
316 UNBLK_##chip(mask) \
317 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
318 "jmp ret_from_sys_call\n" \
319 "\n"__ALIGN_STR"\n" \
320 SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
321 SAVE_MOST \
322 ACK_##chip(mask) \
323 "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
324 "pushl $" #nr "\n\t" \
325 "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
326 "addl $4,%esp\n\t" \
327 "cli\n\t" \
328 UNBLK_##chip(mask) \
329 "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
330 RESTORE_MOST \
331 "\n"__ALIGN_STR"\n" \
332 SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
333 SAVE_MOST \
334 ACK_##chip(mask) \
335 RESTORE_MOST);
336
337 #endif
338 #endif