]> err.no Git - linux-2.6/blob - arch/avr32/kernel/entry-avr32b.S
[AVR32] Fix NMI handler
[linux-2.6] / arch / avr32 / kernel / entry-avr32b.S
1 /*
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
40 exception_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
88 itlb_miss:
89         tlbmiss_save
90         rjmp    tlb_miss_common
91
92         .section .tlbr.ex.text,"ax",@progbits
93 dtlb_miss_read:
94         tlbmiss_save
95         rjmp    tlb_miss_common
96
97         .section .tlbw.ex.text,"ax",@progbits
98 dtlb_miss_write:
99         tlbmiss_save
100
101         .global tlb_miss_common
102 tlb_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 */
111 pgtbl_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 */
146 1:      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
157 handle_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
167 system_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
181 syscall_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
191 syscall_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
204 syscall_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
213 syscall_table_addr:
214         .long   sys_call_table
215
216 syscall_badsys:
217         mov     r12, -ENOSYS
218         rjmp    syscall_return
219
220         .global ret_from_fork
221 ret_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
231 syscall_trace_enter:
232         pushm   r8-r12
233         rcall   syscall_trace
234         popm    r8-r12
235         rjmp    syscall_trace_cont
236
237 syscall_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
245 1:      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
253 2:      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
264 3:      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 */
278 page_table_not_present:
279 page_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 */
290 save_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
297 1:      pushm   r11, r12        /* PC and SR */
298         unmask_exceptions
299         ret     r12
300
301 2:      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 */
306 handle_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... */
315 bad_return:
316         sub     r12, pc, (. - 1f)
317         bral    panic
318         .align  2
319 1:      .asciz  "Return from critical exception!"
320
321         .align  1
322 do_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
329 do_bus_error_read:
330         sub     sp, 4
331         stmts   --sp, r0-lr
332         rcall   save_full_context_ex
333         mov     r11, 0
334 1:      mfsr    r12, SYSREG_BEAR
335         mov     r10, sp
336         rcall   do_bus_error
337         rjmp    ret_from_exception
338
339         .align  1
340 do_nmi_ll:
341         sub     sp, 4
342         stmts   --sp, r0-lr
343         mfsr    r9, SYSREG_RSR_NMI
344         mfsr    r8, SYSREG_RAR_NMI
345         bfextu  r0, r9, MODE_SHIFT, 3
346         brne    2f
347
348 1:      pushm   r8, r9  /* PC and SR */
349         mfsr    r12, SYSREG_ECR
350         mov     r11, sp
351         rcall   do_nmi
352         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
362 2:      sub     r10, sp, -(FRAME_SIZE_FULL - REG_LR)
363         stdsp   sp[4], r10      /* replace saved SP */
364         rjmp    1b
365
366 3:      popm    lr
367         sub     sp, -4          /* skip sp */
368         popm    r0-r12
369         sub     sp, -4          /* skip r12_orig */
370         rete
371
372 handle_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
381 handle_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
391 do_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
400 do_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
428 do_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
438 ret_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
449 fault_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
458 fault_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
471 1:
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
485 irq_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
495 fault_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
504 1:      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
515 2:      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 */
528 handle_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          */
571 handle_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
588 debug_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
597 debug_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
605 1:      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
613 2:      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
624 3:      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
642 irq_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]
655         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
659 #ifdef CONFIG_PREEMPT
660         brne    3f
661 #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
670 1:      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
677 2:      get_thread_info r0
678         ld.w    r1, r0[TI_flags]
679         bld     r1, TIF_CPU_GOING_TO_SLEEP
680 #ifdef CONFIG_PREEMPT
681         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
688 3:      get_thread_info r0
689         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
699 #endif
700         rjmp    1b
701         .endm
702
703         .section .irq.text,"ax",@progbits
704
705 .global cpu_idle_sleep
706 cpu_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
716 cpu_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
721 cpu_idle_enable_int_and_exit:
722         unmask_interrupts
723         retal   r12
724
725         .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