|
|
1.1 root 1: #ifndef _ASM_IRQ_H
2: #define _ASM_IRQ_H
3:
4: /*
5: * linux/include/asm/irq.h
6: *
7: * (C) 1992, 1993 Linus Torvalds
8: *
9: * IRQ/IPI changes taken from work by Thomas Radke <[email protected]>
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" \
1.1.1.2 ! root 41: "mov %dx,%gs\n\t" \
1.1 root 42: "movl $" STR(USER_DS) ",%edx\n\t" \
43: "mov %dx,%fs\n\t" \
44: "movl $0,%edx\n\t" \
45: "movl %edx,%db7\n\t"
46:
47: /*
48: * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
49: * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
50: * call the routines that do signal handling etc on return, and can have
51: * more relaxed register-saving etc. They are also atomic, and are thus
52: * suited for small, fast interrupts like the serial lines or the harddisk
53: * drivers, which don't actually need signal handling etc.
54: *
55: * Also note that we actually save only those registers that are used in
56: * C subroutines (%eax, %edx and %ecx), so if you do something weird,
57: * you're on your own. The only segments that are saved (not counting the
58: * automatic stack and code segment handling) are %ds and %es, and they
59: * point to kernel space. No messing around with %fs here.
60: */
61: #define SAVE_MOST \
62: "cld\n\t" \
63: "push %es\n\t" \
64: "push %ds\n\t" \
65: "pushl %eax\n\t" \
66: "pushl %edx\n\t" \
67: "pushl %ecx\n\t" \
68: "movl $" STR(KERNEL_DS) ",%edx\n\t" \
69: "mov %dx,%ds\n\t" \
70: "mov %dx,%es\n\t"
71:
72: #define RESTORE_MOST \
73: "popl %ecx\n\t" \
74: "popl %edx\n\t" \
75: "popl %eax\n\t" \
76: "pop %ds\n\t" \
77: "pop %es\n\t" \
78: "iret"
79:
80: /*
81: * The "inb" instructions are not needed, but seem to change the timings
82: * a bit - without them it seems that the harddisk driver won't work on
83: * all hardware. Arghh.
84: */
85: #define ACK_FIRST(mask,nr) \
86: "inb $0x21,%al\n\t" \
87: "jmp 1f\n" \
88: "1:\tjmp 1f\n" \
89: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \
90: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
91: "outb %al,$0x21\n\t" \
92: "jmp 1f\n" \
93: "1:\tjmp 1f\n" \
94: "1:\tmovb $0x20,%al\n\t" \
95: "outb %al,$0x20\n\t"
96:
97: #define ACK_SECOND(mask,nr) \
98: "inb $0xA1,%al\n\t" \
99: "jmp 1f\n" \
100: "1:\tjmp 1f\n" \
101: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \
102: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
103: "outb %al,$0xA1\n\t" \
104: "jmp 1f\n" \
105: "1:\tjmp 1f\n" \
106: "1:\tmovb $0x20,%al\n\t" \
107: "outb %al,$0xA0\n\t" \
108: "jmp 1f\n" \
109: "1:\tjmp 1f\n" \
110: "1:\toutb %al,$0x20\n\t"
111:
112: /* do not modify the ISR nor the cache_A1 variable */
113: #define MSGACK_SECOND(mask,nr) \
114: "inb $0xA1,%al\n\t" \
115: "jmp 1f\n" \
116: "1:\tjmp 1f\n" \
117: "1:\tmovb $0x20,%al\n\t" \
118: "outb %al,$0xA0\n\t" \
119: "jmp 1f\n" \
120: "1:\tjmp 1f\n" \
121: "1:\toutb %al,$0x20\n\t"
122:
123: #define UNBLK_FIRST(mask) \
124: "inb $0x21,%al\n\t" \
125: "jmp 1f\n" \
126: "1:\tjmp 1f\n" \
127: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \
128: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \
129: "outb %al,$0x21\n\t"
130:
131: #define UNBLK_SECOND(mask) \
132: "inb $0xA1,%al\n\t" \
133: "jmp 1f\n" \
134: "1:\tjmp 1f\n" \
135: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \
136: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \
137: "outb %al,$0xA1\n\t"
138:
139: #define IRQ_NAME2(nr) nr##_interrupt(void)
140: #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
141: #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
142: #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
143:
144: #ifdef __SMP__
145:
146: #ifndef __SMP_PROF__
147: #define SMP_PROF_INT_SPINS
148: #define SMP_PROF_IPI_CNT
149: #else
150: #define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t"
151: #define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t"
152: #endif
153:
154: #define GET_PROCESSOR_ID \
155: "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
156: "movl 32(%edx), %eax\n\t" \
157: "shrl $24,%eax\n\t" \
158: "andl $0x0F,%eax\n"
159:
160: #define ENTER_KERNEL \
161: "pushl %eax\n\t" \
162: "pushl %ebx\n\t" \
163: "pushl %ecx\n\t" \
164: "pushl %edx\n\t" \
165: "pushfl\n\t" \
166: "cli\n\t" \
167: "movl $6000, %ebx\n\t" \
168: "movl "SYMBOL_NAME_STR(smp_loops_per_tick)", %ecx\n\t" \
169: GET_PROCESSOR_ID \
170: "btsl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \
171: "1: " \
172: "lock\n\t" \
173: "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
174: "jnc 3f\n\t" \
175: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
176: "je 4f\n\t" \
177: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \
178: "jne 2f\n\t" \
179: "movb $1, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \
180: "2: " \
181: SMP_PROF_INT_SPINS \
182: "btl %eax, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
183: "jnc 5f\n\t" \
184: "lock\n\t" \
185: "btrl %eax, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
186: "jnc 5f\n\t" \
187: "movl %cr3,%edx\n\t" \
188: "movl %edx,%cr3\n" \
189: "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
190: "jnc 1b\n\t" \
191: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
192: "je 4f\n\t" \
193: "decl %ecx\n\t" \
194: "jne 2b\n\t" \
195: "decl %ebx\n\t" \
196: "jne 6f\n\t" \
197: "call "SYMBOL_NAME_STR(irq_deadlock_detected)"\n\t" \
198: "6: movl "SYMBOL_NAME_STR(smp_loops_per_tick)", %ecx\n\t" \
199: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \
200: "jne 2b\n\t" \
201: "incl "SYMBOL_NAME_STR(jiffies)"\n\t" \
202: "jmp 2b\n\t" \
203: "3: " \
204: "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
205: "4: " \
206: "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
207: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \
208: "jne 7f\n\t" \
209: "movb $0, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \
210: "7: " \
211: "popfl\n\t" \
212: "popl %edx\n\t" \
213: "popl %ecx\n\t" \
214: "popl %ebx\n\t" \
215: "popl %eax\n\t"
216:
217: #define LEAVE_KERNEL \
218: GET_PROCESSOR_ID \
219: "btrl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \
220: "pushfl\n\t" \
221: "cli\n\t" \
222: "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
223: "jnz 1f\n\t" \
224: "movb "SYMBOL_NAME_STR(saved_active_kernel_processor)",%al\n\t" \
225: "movb %al,"SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
226: "cmpb $" STR (NO_PROC_ID) ",%al\n\t" \
227: "jne 1f\n\t" \
228: "lock\n\t" \
229: "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
230: "1: " \
231: "popfl\n\t"
232:
233:
234: /*
235: * the syscall count inc is a gross hack because ret_from_syscall is used by both irq and
236: * syscall return paths (urghh).
237: */
238:
239: #define BUILD_IRQ(chip,nr,mask) \
240: asmlinkage void IRQ_NAME(nr); \
241: asmlinkage void FAST_IRQ_NAME(nr); \
242: asmlinkage void BAD_IRQ_NAME(nr); \
243: __asm__( \
244: "\n"__ALIGN_STR"\n" \
245: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
246: "pushl $-"#nr"-2\n\t" \
247: SAVE_ALL \
248: ENTER_KERNEL \
249: ACK_##chip(mask,(nr&7)) \
250: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
251: "sti\n\t" \
252: "movl %esp,%ebx\n\t" \
253: "pushl %ebx\n\t" \
254: "pushl $" #nr "\n\t" \
255: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
256: "addl $8,%esp\n\t" \
257: "cli\n\t" \
258: UNBLK_##chip(mask) \
259: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
260: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
261: "jmp ret_from_sys_call\n" \
262: "\n"__ALIGN_STR"\n" \
263: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
264: SAVE_MOST \
265: ENTER_KERNEL \
266: ACK_##chip(mask,(nr&7)) \
267: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
268: "pushl $" #nr "\n\t" \
269: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
270: "addl $4,%esp\n\t" \
271: "cli\n\t" \
272: UNBLK_##chip(mask) \
273: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
274: LEAVE_KERNEL \
275: RESTORE_MOST \
276: "\n"__ALIGN_STR"\n" \
277: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
278: SAVE_MOST \
279: ENTER_KERNEL \
280: ACK_##chip(mask,(nr&7)) \
281: LEAVE_KERNEL \
282: RESTORE_MOST);
283:
284:
285: #define BUILD_TIMER_IRQ(chip,nr,mask) \
286: asmlinkage void IRQ_NAME(nr); \
287: asmlinkage void FAST_IRQ_NAME(nr); \
288: asmlinkage void BAD_IRQ_NAME(nr); \
289: __asm__( \
290: "\n"__ALIGN_STR"\n" \
291: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
292: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
293: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
294: "pushl $-"#nr"-2\n\t" \
295: SAVE_ALL \
296: ENTER_KERNEL \
297: ACK_##chip(mask,(nr&7)) \
298: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
299: "movl %esp,%ebx\n\t" \
300: "pushl %ebx\n\t" \
301: "pushl $" #nr "\n\t" \
302: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
303: "addl $8,%esp\n\t" \
304: "cli\n\t" \
305: UNBLK_##chip(mask) \
306: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
307: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
308: "jmp ret_from_sys_call\n");
309:
310:
311: /*
312: * Message pass must be a fast IRQ..
313: */
314:
315: #define BUILD_MSGIRQ(chip,nr,mask) \
316: asmlinkage void IRQ_NAME(nr); \
317: asmlinkage void FAST_IRQ_NAME(nr); \
318: asmlinkage void BAD_IRQ_NAME(nr); \
319: __asm__( \
320: "\n"__ALIGN_STR"\n" \
321: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
322: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
323: SAVE_MOST \
324: MSGACK_##chip(mask,(nr&7)) \
325: SMP_PROF_IPI_CNT \
326: "pushl $" #nr "\n\t" \
327: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
328: "addl $4,%esp\n\t" \
329: "cli\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,(nr&7)) \
335: RESTORE_MOST);
336:
337: #define BUILD_RESCHEDIRQ(nr) \
338: asmlinkage void IRQ_NAME(nr); \
339: __asm__( \
340: "\n"__ALIGN_STR"\n" \
341: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
342: "pushl $-"#nr"-2\n\t" \
343: SAVE_ALL \
344: ENTER_KERNEL \
345: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
346: "sti\n\t" \
347: "movl %esp,%ebx\n\t" \
348: "pushl %ebx\n\t" \
349: "pushl $" #nr "\n\t" \
350: "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
351: "addl $8,%esp\n\t" \
352: "cli\n\t" \
353: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
354: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
355: "jmp ret_from_sys_call\n");
356: #else
357:
358: #define BUILD_IRQ(chip,nr,mask) \
359: asmlinkage void IRQ_NAME(nr); \
360: asmlinkage void FAST_IRQ_NAME(nr); \
361: asmlinkage void BAD_IRQ_NAME(nr); \
362: __asm__( \
363: "\n"__ALIGN_STR"\n" \
364: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
365: "pushl $-"#nr"-2\n\t" \
366: SAVE_ALL \
367: ACK_##chip(mask,(nr&7)) \
368: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
369: "sti\n\t" \
370: "movl %esp,%ebx\n\t" \
371: "pushl %ebx\n\t" \
372: "pushl $" #nr "\n\t" \
373: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
374: "addl $8,%esp\n\t" \
375: "cli\n\t" \
376: UNBLK_##chip(mask) \
377: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
378: "jmp ret_from_sys_call\n" \
379: "\n"__ALIGN_STR"\n" \
380: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
381: SAVE_MOST \
382: ACK_##chip(mask,(nr&7)) \
383: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
384: "pushl $" #nr "\n\t" \
385: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
386: "addl $4,%esp\n\t" \
387: "cli\n\t" \
388: UNBLK_##chip(mask) \
389: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
390: RESTORE_MOST \
391: "\n"__ALIGN_STR"\n" \
392: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
393: SAVE_MOST \
394: ACK_##chip(mask,(nr&7)) \
395: RESTORE_MOST);
396:
397: #define BUILD_TIMER_IRQ(chip,nr,mask) \
398: asmlinkage void IRQ_NAME(nr); \
399: asmlinkage void FAST_IRQ_NAME(nr); \
400: asmlinkage void BAD_IRQ_NAME(nr); \
401: __asm__( \
402: "\n"__ALIGN_STR"\n" \
403: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
404: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
405: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
406: "pushl $-"#nr"-2\n\t" \
407: SAVE_ALL \
408: ACK_##chip(mask,(nr&7)) \
409: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
410: "movl %esp,%ebx\n\t" \
411: "pushl %ebx\n\t" \
412: "pushl $" #nr "\n\t" \
413: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
414: "addl $8,%esp\n\t" \
415: "cli\n\t" \
416: UNBLK_##chip(mask) \
417: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
418: "jmp ret_from_sys_call\n");
419:
420: #endif
421: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.