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