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 __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
192
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
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