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