|
|
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: 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: * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
46: * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't
47: * call the routines that do signal handling etc on return, and can have
48: * more relaxed register-saving etc. They are also atomic, and are thus
49: * suited for small, fast interrupts like the serial lines or the harddisk
50: * drivers, which don't actually need signal handling etc.
51: *
52: * Also note that we actually save only those registers that are used in
53: * C subroutines (%eax, %edx and %ecx), so if you do something weird,
54: * you're on your own. The only segments that are saved (not counting the
55: * automatic stack and code segment handling) are %ds and %es, and they
56: * point to kernel space. No messing around with %fs here.
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: * The "inb" instructions are not needed, but seem to change the timings
79: * a bit - without them it seems that the harddisk driver won't work on
80: * all hardware. Arghh.
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 __SMP__
131:
132: #ifndef __SMP_PROF__
133: #define SMP_PROF_INT_SPINS
134: #define SMP_PROF_IPI_CNT
135: #else
136: #define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t"
137: #define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t"
138: #endif
139:
140: #define GET_PROCESSOR_ID \
141: "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
142: "movl 32(%edx), %eax\n\t" \
143: "shrl $24,%eax\n\t" \
144: "andb $0x0F,%al\n"
145:
146: #define ENTER_KERNEL \
147: "pushl %eax\n\t" \
148: "pushl %edx\n\t" \
149: "pushfl\n\t" \
150: "cli\n\t" \
151: GET_PROCESSOR_ID \
152: "1: " \
153: "lock\n\t" \
154: "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
155: "jnc 3f\n\t" \
156: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \
157: "je 4f\n\t" \
158: "2: " \
159: SMP_PROF_INT_SPINS \
160: "btl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
161: "jnc 5f\n\t" \
162: "lock\n\t" \
163: "btrl %al, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \
164: "jnc 5f\n\t" \
165: "movl %cr3,%edx\n\t" \
166: "movl %edx,%cr3\n" \
167: "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
168: "jc 2b\n\t" \
169: "jmp 1b\n\t" \
170: "3: " \
171: "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
172: "4: " \
173: "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
174: "popfl\n\t" \
175: "popl %edx\n\t" \
176: "popl %eax\n\t"
177:
178: #define LEAVE_KERNEL \
179: "pushfl\n\t" \
180: "cli\n\t" \
181: "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
182: "jnz 1f\n\t" \
183: "movb $" STR (NO_PROC_ID) ", "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \
184: "lock\n\t" \
185: "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
186: "1: " \
187: "popfl\n\t"
188:
189:
190: /*
191: * the syscall count inc is a gross hack because ret_from_syscall is used by both irq and
192: * syscall return paths (urghh).
193: */
194:
195: #define BUILD_IRQ(chip,nr,mask) \
196: asmlinkage void IRQ_NAME(nr); \
197: asmlinkage void FAST_IRQ_NAME(nr); \
198: asmlinkage void BAD_IRQ_NAME(nr); \
199: __asm__( \
200: "\n"__ALIGN_STR"\n" \
201: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
202: "pushl $-"#nr"-2\n\t" \
203: SAVE_ALL \
204: ENTER_KERNEL \
205: ACK_##chip(mask) \
206: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
207: "sti\n\t" \
208: "movl %esp,%ebx\n\t" \
209: "pushl %ebx\n\t" \
210: "pushl $" #nr "\n\t" \
211: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
212: "addl $8,%esp\n\t" \
213: "cli\n\t" \
214: UNBLK_##chip(mask) \
215: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
216: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
217: "jmp ret_from_sys_call\n" \
218: "\n"__ALIGN_STR"\n" \
219: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
220: SAVE_MOST \
221: ENTER_KERNEL \
222: ACK_##chip(mask) \
223: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
224: "pushl $" #nr "\n\t" \
225: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
226: "addl $4,%esp\n\t" \
227: "cli\n\t" \
228: UNBLK_##chip(mask) \
229: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
230: LEAVE_KERNEL \
231: RESTORE_MOST \
232: "\n"__ALIGN_STR"\n" \
233: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
234: SAVE_MOST \
235: ENTER_KERNEL \
236: ACK_##chip(mask) \
237: LEAVE_KERNEL \
238: RESTORE_MOST);
239:
240:
241: /*
242: * Message pass must be a fast IRQ..
243: */
244:
245: #define BUILD_MSGIRQ(chip,nr,mask) \
246: asmlinkage void IRQ_NAME(nr); \
247: asmlinkage void FAST_IRQ_NAME(nr); \
248: asmlinkage void BAD_IRQ_NAME(nr); \
249: __asm__( \
250: "\n"__ALIGN_STR"\n" \
251: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
252: "pushl $-"#nr"-2\n\t" \
253: SAVE_ALL \
254: ENTER_KERNEL \
255: ACK_##chip(mask) \
256: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
257: "sti\n\t" \
258: "movl %esp,%ebx\n\t" \
259: "pushl %ebx\n\t" \
260: "pushl $" #nr "\n\t" \
261: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
262: "addl $8,%esp\n\t" \
263: "cli\n\t" \
264: UNBLK_##chip(mask) \
265: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
266: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
267: "jmp ret_from_sys_call\n" \
268: "\n"__ALIGN_STR"\n" \
269: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
270: SAVE_MOST \
271: ACK_##chip(mask) \
272: SMP_PROF_IPI_CNT \
273: "pushl $" #nr "\n\t" \
274: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
275: "addl $4,%esp\n\t" \
276: "cli\n\t" \
277: UNBLK_##chip(mask) \
278: RESTORE_MOST \
279: "\n"__ALIGN_STR"\n" \
280: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
281: SAVE_MOST \
282: ACK_##chip(mask) \
283: RESTORE_MOST);
284:
285: #define BUILD_RESCHEDIRQ(nr) \
286: asmlinkage void IRQ_NAME(nr); \
287: __asm__( \
288: "\n"__ALIGN_STR"\n" \
289: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
290: "pushl $-"#nr"-2\n\t" \
291: SAVE_ALL \
292: ENTER_KERNEL \
293: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
294: "sti\n\t" \
295: "movl %esp,%ebx\n\t" \
296: "pushl %ebx\n\t" \
297: "pushl $" #nr "\n\t" \
298: "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \
299: "addl $8,%esp\n\t" \
300: "cli\n\t" \
301: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
302: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
303: "jmp ret_from_sys_call\n");
304: #else
305:
306: #define BUILD_IRQ(chip,nr,mask) \
307: asmlinkage void IRQ_NAME(nr); \
308: asmlinkage void FAST_IRQ_NAME(nr); \
309: asmlinkage void BAD_IRQ_NAME(nr); \
310: __asm__( \
311: "\n"__ALIGN_STR"\n" \
312: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
313: "pushl $-"#nr"-2\n\t" \
314: SAVE_ALL \
315: ACK_##chip(mask) \
316: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\
317: "sti\n\t" \
318: "movl %esp,%ebx\n\t" \
319: "pushl %ebx\n\t" \
320: "pushl $" #nr "\n\t" \
321: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
322: "addl $8,%esp\n\t" \
323: "cli\n\t" \
324: UNBLK_##chip(mask) \
325: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
326: "jmp ret_from_sys_call\n" \
327: "\n"__ALIGN_STR"\n" \
328: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \
329: SAVE_MOST \
330: ACK_##chip(mask) \
331: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \
332: "pushl $" #nr "\n\t" \
333: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \
334: "addl $4,%esp\n\t" \
335: "cli\n\t" \
336: UNBLK_##chip(mask) \
337: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
338: RESTORE_MOST \
339: "\n"__ALIGN_STR"\n" \
340: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \
341: SAVE_MOST \
342: ACK_##chip(mask) \
343: RESTORE_MOST);
344:
345: #endif
346: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.