blob: 484e08310f1512651af5fffb5d932ed9296ab30f [file] [log] [blame]
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -07001/*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/*
10 * This file contains the low-level entry-points into the kernel, that is,
11 * exception handlers, debug trap handlers, interrupt handlers and the
12 * system call handler.
13 */
14#include <linux/errno.h>
15
16#include <asm/asm.h>
17#include <asm/hardirq.h>
18#include <asm/irq.h>
19#include <asm/ocd.h>
20#include <asm/page.h>
21#include <asm/pgtable.h>
22#include <asm/ptrace.h>
23#include <asm/sysreg.h>
24#include <asm/thread_info.h>
25#include <asm/unistd.h>
26
27#ifdef CONFIG_PREEMPT
28# define preempt_stop mask_interrupts
29#else
30# define preempt_stop
31# define fault_resume_kernel fault_restore_all
32#endif
33
34#define __MASK(x) ((1 << (x)) - 1)
35#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
36 (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
37
38 .section .ex.text,"ax",@progbits
39 .align 2
40exception_vectors:
41 bral handle_critical
42 .align 2
43 bral handle_critical
44 .align 2
45 bral do_bus_error_write
46 .align 2
47 bral do_bus_error_read
48 .align 2
49 bral do_nmi_ll
50 .align 2
51 bral handle_address_fault
52 .align 2
53 bral handle_protection_fault
54 .align 2
55 bral handle_debug
56 .align 2
57 bral do_illegal_opcode_ll
58 .align 2
59 bral do_illegal_opcode_ll
60 .align 2
61 bral do_illegal_opcode_ll
62 .align 2
63 bral do_fpe_ll
64 .align 2
65 bral do_illegal_opcode_ll
66 .align 2
67 bral handle_address_fault
68 .align 2
69 bral handle_address_fault
70 .align 2
71 bral handle_protection_fault
72 .align 2
73 bral handle_protection_fault
74 .align 2
75 bral do_dtlb_modified
76
77 /*
78 * r0 : PGD/PT/PTE
79 * r1 : Offending address
80 * r2 : Scratch register
81 * r3 : Cause (5, 12 or 13)
82 */
83#define tlbmiss_save pushm r0-r3
84#define tlbmiss_restore popm r0-r3
85
86 .section .tlbx.ex.text,"ax",@progbits
87 .global itlb_miss
88itlb_miss:
89 tlbmiss_save
90 rjmp tlb_miss_common
91
92 .section .tlbr.ex.text,"ax",@progbits
93dtlb_miss_read:
94 tlbmiss_save
95 rjmp tlb_miss_common
96
97 .section .tlbw.ex.text,"ax",@progbits
98dtlb_miss_write:
99 tlbmiss_save
100
101 .global tlb_miss_common
102tlb_miss_common:
103 mfsr r0, SYSREG_PTBR
104 mfsr r1, SYSREG_TLBEAR
105
106 /* Is it the vmalloc space? */
107 bld r1, 31
108 brcs handle_vmalloc_miss
109
110 /* First level lookup */
111pgtbl_lookup:
112 lsr r2, r1, PGDIR_SHIFT
113 ld.w r0, r0[r2 << 2]
114 bld r0, _PAGE_BIT_PRESENT
115 brcc page_table_not_present
116
117 /* TODO: Check access rights on page table if necessary */
118
119 /* Translate to virtual address in P1. */
120 andl r0, 0xf000
121 sbr r0, 31
122
123 /* Second level lookup */
124 lsl r1, (32 - PGDIR_SHIFT)
125 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
126 add r2, r0, r1 << 2
127 ld.w r1, r2[0]
128 bld r1, _PAGE_BIT_PRESENT
129 brcc page_not_present
130
131 /* Mark the page as accessed */
132 sbr r1, _PAGE_BIT_ACCESSED
133 st.w r2[0], r1
134
135 /* Drop software flags */
136 andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
137 mtsr SYSREG_TLBELO, r1
138
139 /* Figure out which entry we want to replace */
140 mfsr r0, SYSREG_TLBARLO
141 clz r2, r0
142 brcc 1f
143 mov r1, -1 /* All entries have been accessed, */
144 mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
145 mov r2, 0 /* and start at 0 */
1461: mfsr r1, SYSREG_MMUCR
147 lsl r2, 14
148 andl r1, 0x3fff, COH
149 or r1, r2
150 mtsr SYSREG_MMUCR, r1
151
152 tlbw
153
154 tlbmiss_restore
155 rete
156
157handle_vmalloc_miss:
158 /* Simply do the lookup in init's page table */
159 mov r0, lo(swapper_pg_dir)
160 orh r0, hi(swapper_pg_dir)
161 rjmp pgtbl_lookup
162
163
164 /* --- System Call --- */
165
166 .section .scall.text,"ax",@progbits
167system_call:
168 pushm r12 /* r12_orig */
169 stmts --sp, r0-lr
170 zero_fp
171 mfsr r0, SYSREG_RAR_SUP
172 mfsr r1, SYSREG_RSR_SUP
173 stm --sp, r0-r1
174
175 /* check for syscall tracing */
176 get_thread_info r0
177 ld.w r1, r0[TI_flags]
178 bld r1, TIF_SYSCALL_TRACE
179 brcs syscall_trace_enter
180
181syscall_trace_cont:
182 cp.w r8, NR_syscalls
183 brhs syscall_badsys
184
185 lddpc lr, syscall_table_addr
186 ld.w lr, lr[r8 << 2]
187 mov r8, r5 /* 5th argument (6th is pushed by stub) */
188 icall lr
189
190 .global syscall_return
191syscall_return:
192 get_thread_info r0
193 mask_interrupts /* make sure we don't miss an interrupt
194 setting need_resched or sigpending
195 between sampling and the rets */
196
197 /* Store the return value so that the correct value is loaded below */
198 stdsp sp[REG_R12], r12
199
200 ld.w r1, r0[TI_flags]
201 andl r1, _TIF_ALLWORK_MASK, COH
202 brne syscall_exit_work
203
204syscall_exit_cont:
205 popm r8-r9
206 mtsr SYSREG_RAR_SUP, r8
207 mtsr SYSREG_RSR_SUP, r9
208 ldmts sp++, r0-lr
209 sub sp, -4 /* r12_orig */
210 rets
211
212 .align 2
213syscall_table_addr:
214 .long sys_call_table
215
216syscall_badsys:
217 mov r12, -ENOSYS
218 rjmp syscall_return
219
220 .global ret_from_fork
221ret_from_fork:
222 rcall schedule_tail
223
224 /* check for syscall tracing */
225 get_thread_info r0
226 ld.w r1, r0[TI_flags]
227 andl r1, _TIF_ALLWORK_MASK, COH
228 brne syscall_exit_work
229 rjmp syscall_exit_cont
230
231syscall_trace_enter:
232 pushm r8-r12
233 rcall syscall_trace
234 popm r8-r12
235 rjmp syscall_trace_cont
236
237syscall_exit_work:
238 bld r1, TIF_SYSCALL_TRACE
239 brcc 1f
240 unmask_interrupts
241 rcall syscall_trace
242 mask_interrupts
243 ld.w r1, r0[TI_flags]
244
2451: bld r1, TIF_NEED_RESCHED
246 brcc 2f
247 unmask_interrupts
248 rcall schedule
249 mask_interrupts
250 ld.w r1, r0[TI_flags]
251 rjmp 1b
252
2532: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
254 tst r1, r2
255 breq 3f
256 unmask_interrupts
257 mov r12, sp
258 mov r11, r0
259 rcall do_notify_resume
260 mask_interrupts
261 ld.w r1, r0[TI_flags]
262 rjmp 1b
263
2643: bld r1, TIF_BREAKPOINT
265 brcc syscall_exit_cont
266 mfsr r3, SYSREG_TLBEHI
267 lddsp r2, sp[REG_PC]
268 andl r3, 0xff, COH
269 lsl r3, 1
270 sbr r3, 30
271 sbr r3, 0
272 mtdr DBGREG_BWA2A, r2
273 mtdr DBGREG_BWC2A, r3
274 rjmp syscall_exit_cont
275
276
277 /* The slow path of the TLB miss handler */
278page_table_not_present:
279page_not_present:
280 tlbmiss_restore
281 sub sp, 4
282 stmts --sp, r0-lr
283 rcall save_full_context_ex
284 mfsr r12, SYSREG_ECR
285 mov r11, sp
286 rcall do_page_fault
287 rjmp ret_from_exception
288
289 /* This function expects to find offending PC in SYSREG_RAR_EX */
290save_full_context_ex:
291 mfsr r8, SYSREG_RSR_EX
292 mov r12, r8
293 andh r8, (MODE_MASK >> 16), COH
294 mfsr r11, SYSREG_RAR_EX
295 brne 2f
296
2971: pushm r11, r12 /* PC and SR */
298 unmask_exceptions
299 ret r12
300
3012: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
302 stdsp sp[4], r10 /* replace saved SP */
303 rjmp 1b
304
305 /* Low-level exception handlers */
306handle_critical:
307 pushm r12
308 pushm r0-r12
309 rcall save_full_context_ex
310 mfsr r12, SYSREG_ECR
311 mov r11, sp
312 rcall do_critical_exception
313
314 /* We should never get here... */
315bad_return:
316 sub r12, pc, (. - 1f)
317 bral panic
318 .align 2
3191: .asciz "Return from critical exception!"
320
321 .align 1
322do_bus_error_write:
323 sub sp, 4
324 stmts --sp, r0-lr
325 rcall save_full_context_ex
326 mov r11, 1
327 rjmp 1f
328
329do_bus_error_read:
330 sub sp, 4
331 stmts --sp, r0-lr
332 rcall save_full_context_ex
333 mov r11, 0
3341: mfsr r12, SYSREG_BEAR
335 mov r10, sp
336 rcall do_bus_error
337 rjmp ret_from_exception
338
339 .align 1
340do_nmi_ll:
341 sub sp, 4
342 stmts --sp, r0-lr
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100343 mfsr r9, SYSREG_RSR_NMI
344 mfsr r8, SYSREG_RAR_NMI
345 bfextu r0, r9, MODE_SHIFT, 3
346 brne 2f
347
3481: pushm r8, r9 /* PC and SR */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700349 mfsr r12, SYSREG_ECR
350 mov r11, sp
351 rcall do_nmi
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100352 popm r8-r9
353 mtsr SYSREG_RAR_NMI, r8
354 tst r0, r0
355 mtsr SYSREG_RSR_NMI, r9
356 brne 3f
357
358 ldmts sp++, r0-lr
359 sub sp, -4 /* skip r12_orig */
360 rete
361
3622: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
363 stdsp sp[4], r10 /* replace saved SP */
364 rjmp 1b
365
3663: popm lr
367 sub sp, -4 /* skip sp */
368 popm r0-r12
369 sub sp, -4 /* skip r12_orig */
370 rete
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700371
372handle_address_fault:
373 sub sp, 4
374 stmts --sp, r0-lr
375 rcall save_full_context_ex
376 mfsr r12, SYSREG_ECR
377 mov r11, sp
378 rcall do_address_exception
379 rjmp ret_from_exception
380
381handle_protection_fault:
382 sub sp, 4
383 stmts --sp, r0-lr
384 rcall save_full_context_ex
385 mfsr r12, SYSREG_ECR
386 mov r11, sp
387 rcall do_page_fault
388 rjmp ret_from_exception
389
390 .align 1
391do_illegal_opcode_ll:
392 sub sp, 4
393 stmts --sp, r0-lr
394 rcall save_full_context_ex
395 mfsr r12, SYSREG_ECR
396 mov r11, sp
397 rcall do_illegal_opcode
398 rjmp ret_from_exception
399
400do_dtlb_modified:
401 pushm r0-r3
402 mfsr r1, SYSREG_TLBEAR
403 mfsr r0, SYSREG_PTBR
404 lsr r2, r1, PGDIR_SHIFT
405 ld.w r0, r0[r2 << 2]
406 lsl r1, (32 - PGDIR_SHIFT)
407 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
408
409 /* Translate to virtual address in P1 */
410 andl r0, 0xf000
411 sbr r0, 31
412 add r2, r0, r1 << 2
413 ld.w r3, r2[0]
414 sbr r3, _PAGE_BIT_DIRTY
415 mov r0, r3
416 st.w r2[0], r3
417
418 /* The page table is up-to-date. Update the TLB entry as well */
419 andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
420 mtsr SYSREG_TLBELO, r0
421
422 /* MMUCR[DRP] is updated automatically, so let's go... */
423 tlbw
424
425 popm r0-r3
426 rete
427
428do_fpe_ll:
429 sub sp, 4
430 stmts --sp, r0-lr
431 rcall save_full_context_ex
432 unmask_interrupts
433 mov r12, 26
434 mov r11, sp
435 rcall do_fpe
436 rjmp ret_from_exception
437
438ret_from_exception:
439 mask_interrupts
440 lddsp r4, sp[REG_SR]
441 andh r4, (MODE_MASK >> 16), COH
442 brne fault_resume_kernel
443
444 get_thread_info r0
445 ld.w r1, r0[TI_flags]
446 andl r1, _TIF_WORK_MASK, COH
447 brne fault_exit_work
448
449fault_resume_user:
450 popm r8-r9
451 mask_exceptions
452 mtsr SYSREG_RAR_EX, r8
453 mtsr SYSREG_RSR_EX, r9
454 ldmts sp++, r0-lr
455 sub sp, -4
456 rete
457
458fault_resume_kernel:
459#ifdef CONFIG_PREEMPT
460 get_thread_info r0
461 ld.w r2, r0[TI_preempt_count]
462 cp.w r2, 0
463 brne 1f
464 ld.w r1, r0[TI_flags]
465 bld r1, TIF_NEED_RESCHED
466 brcc 1f
467 lddsp r4, sp[REG_SR]
468 bld r4, SYSREG_GM_OFFSET
469 brcs 1f
470 rcall preempt_schedule_irq
4711:
472#endif
473
474 popm r8-r9
475 mask_exceptions
476 mfsr r1, SYSREG_SR
477 mtsr SYSREG_RAR_EX, r8
478 mtsr SYSREG_RSR_EX, r9
479 popm lr
480 sub sp, -4 /* ignore SP */
481 popm r0-r12
482 sub sp, -4 /* ignore r12_orig */
483 rete
484
485irq_exit_work:
486 /* Switch to exception mode so that we can share the same code. */
487 mfsr r8, SYSREG_SR
488 cbr r8, SYSREG_M0_OFFSET
489 orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
490 mtsr SYSREG_SR, r8
491 sub pc, -2
492 get_thread_info r0
493 ld.w r1, r0[TI_flags]
494
495fault_exit_work:
496 bld r1, TIF_NEED_RESCHED
497 brcc 1f
498 unmask_interrupts
499 rcall schedule
500 mask_interrupts
501 ld.w r1, r0[TI_flags]
502 rjmp fault_exit_work
503
5041: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
505 tst r1, r2
506 breq 2f
507 unmask_interrupts
508 mov r12, sp
509 mov r11, r0
510 rcall do_notify_resume
511 mask_interrupts
512 ld.w r1, r0[TI_flags]
513 rjmp fault_exit_work
514
5152: bld r1, TIF_BREAKPOINT
516 brcc fault_resume_user
517 mfsr r3, SYSREG_TLBEHI
518 lddsp r2, sp[REG_PC]
519 andl r3, 0xff, COH
520 lsl r3, 1
521 sbr r3, 30
522 sbr r3, 0
523 mtdr DBGREG_BWA2A, r2
524 mtdr DBGREG_BWC2A, r3
525 rjmp fault_resume_user
526
527 /* If we get a debug trap from privileged context we end up here */
528handle_debug_priv:
529 /* Fix up LR and SP in regs. r11 contains the mode we came from */
530 mfsr r8, SYSREG_SR
531 mov r9, r8
532 andh r8, hi(~MODE_MASK)
533 or r8, r11
534 mtsr SYSREG_SR, r8
535 sub pc, -2
536 stdsp sp[REG_LR], lr
537 mtsr SYSREG_SR, r9
538 sub pc, -2
539 sub r10, sp, -FRAME_SIZE_FULL
540 stdsp sp[REG_SP], r10
541 mov r12, sp
542 rcall do_debug_priv
543
544 /* Now, put everything back */
545 ssrf SR_EM_BIT
546 popm r10, r11
547 mtsr SYSREG_RAR_DBG, r10
548 mtsr SYSREG_RSR_DBG, r11
549 mfsr r8, SYSREG_SR
550 mov r9, r8
551 andh r8, hi(~MODE_MASK)
552 andh r11, hi(MODE_MASK)
553 or r8, r11
554 mtsr SYSREG_SR, r8
555 sub pc, -2
556 popm lr
557 mtsr SYSREG_SR, r9
558 sub pc, -2
559 sub sp, -4 /* skip SP */
560 popm r0-r12
561 sub sp, -4
562 retd
563
564 /*
565 * At this point, everything is masked, that is, interrupts,
566 * exceptions and debugging traps. We might get called from
567 * interrupt or exception context in some rare cases, but this
568 * will be taken care of by do_debug(), so we're not going to
569 * do a 100% correct context save here.
570 */
571handle_debug:
572 sub sp, 4 /* r12_orig */
573 stmts --sp, r0-lr
574 mfsr r10, SYSREG_RAR_DBG
575 mfsr r11, SYSREG_RSR_DBG
576 unmask_exceptions
577 pushm r10,r11
578 andh r11, (MODE_MASK >> 16), COH
579 brne handle_debug_priv
580
581 mov r12, sp
582 rcall do_debug
583
584 lddsp r10, sp[REG_SR]
585 andh r10, (MODE_MASK >> 16), COH
586 breq debug_resume_user
587
588debug_restore_all:
589 popm r10,r11
590 mask_exceptions
591 mtsr SYSREG_RSR_DBG, r11
592 mtsr SYSREG_RAR_DBG, r10
593 ldmts sp++, r0-lr
594 sub sp, -4
595 retd
596
597debug_resume_user:
598 get_thread_info r0
599 mask_interrupts
600
601 ld.w r1, r0[TI_flags]
602 andl r1, _TIF_DBGWORK_MASK, COH
603 breq debug_restore_all
604
6051: bld r1, TIF_NEED_RESCHED
606 brcc 2f
607 unmask_interrupts
608 rcall schedule
609 mask_interrupts
610 ld.w r1, r0[TI_flags]
611 rjmp 1b
612
6132: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
614 tst r1, r2
615 breq 3f
616 unmask_interrupts
617 mov r12, sp
618 mov r11, r0
619 rcall do_notify_resume
620 mask_interrupts
621 ld.w r1, r0[TI_flags]
622 rjmp 1b
623
6243: bld r1, TIF_SINGLE_STEP
625 brcc debug_restore_all
626 mfdr r2, DBGREG_DC
627 sbr r2, DC_SS_BIT
628 mtdr DBGREG_DC, r2
629 rjmp debug_restore_all
630
631 .set rsr_int0, SYSREG_RSR_INT0
632 .set rsr_int1, SYSREG_RSR_INT1
633 .set rsr_int2, SYSREG_RSR_INT2
634 .set rsr_int3, SYSREG_RSR_INT3
635 .set rar_int0, SYSREG_RAR_INT0
636 .set rar_int1, SYSREG_RAR_INT1
637 .set rar_int2, SYSREG_RAR_INT2
638 .set rar_int3, SYSREG_RAR_INT3
639
640 .macro IRQ_LEVEL level
641 .type irq_level\level, @function
642irq_level\level:
643 sub sp, 4 /* r12_orig */
644 stmts --sp,r0-lr
645 mfsr r8, rar_int\level
646 mfsr r9, rsr_int\level
647 pushm r8-r9
648
649 mov r11, sp
650 mov r12, \level
651
652 rcall do_IRQ
653
654 lddsp r4, sp[REG_SR]
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100655 bfextu r4, r4, SYSREG_M0_OFFSET, 3
656 cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
657 breq 2f
658 cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700659#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100660 brne 3f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700661#else
662 brne 1f
663#endif
664
665 get_thread_info r0
666 ld.w r1, r0[TI_flags]
667 andl r1, _TIF_WORK_MASK, COH
668 brne irq_exit_work
669
6701: popm r8-r9
671 mtsr rar_int\level, r8
672 mtsr rsr_int\level, r9
673 ldmts sp++,r0-lr
674 sub sp, -4 /* ignore r12_orig */
675 rete
676
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +01006772: get_thread_info r0
678 ld.w r1, r0[TI_flags]
679 bld r1, TIF_CPU_GOING_TO_SLEEP
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700680#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100681 brcc 3f
682#else
683 brcc 1b
684#endif
685 sub r1, pc, . - cpu_idle_skip_sleep
686 stdsp sp[REG_PC], r1
687#ifdef CONFIG_PREEMPT
6883: get_thread_info r0
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700689 ld.w r2, r0[TI_preempt_count]
690 cp.w r2, 0
691 brne 1b
692 ld.w r1, r0[TI_flags]
693 bld r1, TIF_NEED_RESCHED
694 brcc 1b
695 lddsp r4, sp[REG_SR]
696 bld r4, SYSREG_GM_OFFSET
697 brcs 1b
698 rcall preempt_schedule_irq
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700699#endif
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100700 rjmp 1b
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700701 .endm
702
703 .section .irq.text,"ax",@progbits
704
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100705.global cpu_idle_sleep
706cpu_idle_sleep:
707 mask_interrupts
708 get_thread_info r8
709 ld.w r9, r8[TI_flags]
710 bld r9, TIF_NEED_RESCHED
711 brcs cpu_idle_enable_int_and_exit
712 sbr r9, TIF_CPU_GOING_TO_SLEEP
713 st.w r8[TI_flags], r9
714 unmask_interrupts
715 sleep 0
716cpu_idle_skip_sleep:
717 mask_interrupts
718 ld.w r9, r8[TI_flags]
719 cbr r9, TIF_CPU_GOING_TO_SLEEP
720 st.w r8[TI_flags], r9
721cpu_idle_enable_int_and_exit:
722 unmask_interrupts
723 retal r12
724
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700725 .global irq_level0
726 .global irq_level1
727 .global irq_level2
728 .global irq_level3
729 IRQ_LEVEL 0
730 IRQ_LEVEL 1
731 IRQ_LEVEL 2
732 IRQ_LEVEL 3