Merge git://git.infradead.org/battery-2.6
[pandora-kernel.git] / 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_TLBEAR
104         mfsr    r1, SYSREG_PTBR
105
106         /* Is it the vmalloc space? */
107         bld     r0, 31
108         brcs    handle_vmalloc_miss
109
110         /* First level lookup */
111 pgtbl_lookup:
112         lsr     r2, r0, PGDIR_SHIFT
113         ld.w    r3, r1[r2 << 2]
114         bfextu  r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
115         bld     r3, _PAGE_BIT_PRESENT
116         brcc    page_table_not_present
117
118         /* Translate to virtual address in P1. */
119         andl    r3, 0xf000
120         sbr     r3, 31
121
122         /* Second level lookup */
123         ld.w    r2, r3[r1 << 2]
124         mfsr    r0, SYSREG_TLBARLO
125         bld     r2, _PAGE_BIT_PRESENT
126         brcc    page_not_present
127
128         /* Mark the page as accessed */
129         sbr     r2, _PAGE_BIT_ACCESSED
130         st.w    r3[r1 << 2], r2
131
132         /* Drop software flags */
133         andl    r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
134         mtsr    SYSREG_TLBELO, r2
135
136         /* Figure out which entry we want to replace */
137         mfsr    r1, SYSREG_MMUCR
138         clz     r2, r0
139         brcc    1f
140         mov     r3, -1                  /* All entries have been accessed, */
141         mov     r2, 0                   /* so start at 0 */
142         mtsr    SYSREG_TLBARLO, r3      /* and reset TLBAR */
143
144 1:      bfins   r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
145         mtsr    SYSREG_MMUCR, r1
146         tlbw
147
148         tlbmiss_restore
149         rete
150
151 handle_vmalloc_miss:
152         /* Simply do the lookup in init's page table */
153         mov     r1, lo(swapper_pg_dir)
154         orh     r1, hi(swapper_pg_dir)
155         rjmp    pgtbl_lookup
156
157
158         /* ---                    System Call                    --- */
159
160         .section .scall.text,"ax",@progbits
161 system_call:
162 #ifdef CONFIG_PREEMPT
163         mask_interrupts
164 #endif
165         pushm   r12             /* r12_orig */
166         stmts   --sp, r0-lr
167
168         mfsr    r0, SYSREG_RAR_SUP
169         mfsr    r1, SYSREG_RSR_SUP
170 #ifdef CONFIG_PREEMPT
171         unmask_interrupts
172 #endif
173         zero_fp
174         stm     --sp, r0-r1
175
176         /* check for syscall tracing */
177         get_thread_info r0
178         ld.w    r1, r0[TI_flags]
179         bld     r1, TIF_SYSCALL_TRACE
180         brcs    syscall_trace_enter
181
182 syscall_trace_cont:
183         cp.w    r8, NR_syscalls
184         brhs    syscall_badsys
185
186         lddpc   lr, syscall_table_addr
187         ld.w    lr, lr[r8 << 2]
188         mov     r8, r5          /* 5th argument (6th is pushed by stub) */
189         icall   lr
190
191         .global syscall_return
192 syscall_return:
193         get_thread_info r0
194         mask_interrupts         /* make sure we don't miss an interrupt
195                                    setting need_resched or sigpending
196                                    between sampling and the rets */
197
198         /* Store the return value so that the correct value is loaded below */
199         stdsp   sp[REG_R12], r12
200
201         ld.w    r1, r0[TI_flags]
202         andl    r1, _TIF_ALLWORK_MASK, COH
203         brne    syscall_exit_work
204
205 syscall_exit_cont:
206         popm    r8-r9
207         mtsr    SYSREG_RAR_SUP, r8
208         mtsr    SYSREG_RSR_SUP, r9
209         ldmts   sp++, r0-lr
210         sub     sp, -4          /* r12_orig */
211         rets
212
213         .align  2
214 syscall_table_addr:
215         .long   sys_call_table
216
217 syscall_badsys:
218         mov     r12, -ENOSYS
219         rjmp    syscall_return
220
221         .global ret_from_fork
222 ret_from_fork:
223         rcall   schedule_tail
224
225         /* check for syscall tracing */
226         get_thread_info r0
227         ld.w    r1, r0[TI_flags]
228         andl    r1, _TIF_ALLWORK_MASK, COH
229         brne    syscall_exit_work
230         rjmp    syscall_exit_cont
231
232 syscall_trace_enter:
233         pushm   r8-r12
234         rcall   syscall_trace
235         popm    r8-r12
236         rjmp    syscall_trace_cont
237
238 syscall_exit_work:
239         bld     r1, TIF_SYSCALL_TRACE
240         brcc    1f
241         unmask_interrupts
242         rcall   syscall_trace
243         mask_interrupts
244         ld.w    r1, r0[TI_flags]
245
246 1:      bld     r1, TIF_NEED_RESCHED
247         brcc    2f
248         unmask_interrupts
249         rcall   schedule
250         mask_interrupts
251         ld.w    r1, r0[TI_flags]
252         rjmp    1b
253
254 2:      mov     r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
255         tst     r1, r2
256         breq    3f
257         unmask_interrupts
258         mov     r12, sp
259         mov     r11, r0
260         rcall   do_notify_resume
261         mask_interrupts
262         ld.w    r1, r0[TI_flags]
263         rjmp    1b
264
265 3:      bld     r1, TIF_BREAKPOINT
266         brcc    syscall_exit_cont
267         mfsr    r3, SYSREG_TLBEHI
268         lddsp   r2, sp[REG_PC]
269         andl    r3, 0xff, COH
270         lsl     r3, 1
271         sbr     r3, 30
272         sbr     r3, 0
273         mtdr    DBGREG_BWA2A, r2
274         mtdr    DBGREG_BWC2A, r3
275         rjmp    syscall_exit_cont
276
277
278         /* The slow path of the TLB miss handler */
279 page_table_not_present:
280 page_not_present:
281         tlbmiss_restore
282         sub     sp, 4
283         stmts   --sp, r0-lr
284         rcall   save_full_context_ex
285         mfsr    r12, SYSREG_ECR
286         mov     r11, sp
287         rcall   do_page_fault
288         rjmp    ret_from_exception
289
290         /* This function expects to find offending PC in SYSREG_RAR_EX */
291 save_full_context_ex:
292         mfsr    r8, SYSREG_RSR_EX
293         mov     r12, r8
294         andh    r8, (MODE_MASK >> 16), COH
295         mfsr    r11, SYSREG_RAR_EX
296         brne    2f
297
298 1:      pushm   r11, r12        /* PC and SR */
299         unmask_exceptions
300         ret     r12
301
302 2:      sub     r10, sp, -(FRAME_SIZE_FULL - REG_LR)
303         stdsp   sp[4], r10      /* replace saved SP */
304         rjmp    1b
305
306         /* Low-level exception handlers */
307 handle_critical:
308         pushm   r12
309         pushm   r0-r12
310         rcall   save_full_context_ex
311         mfsr    r12, SYSREG_ECR
312         mov     r11, sp
313         rcall   do_critical_exception
314
315         /* We should never get here... */
316 bad_return:
317         sub     r12, pc, (. - 1f)
318         bral    panic
319         .align  2
320 1:      .asciz  "Return from critical exception!"
321
322         .align  1
323 do_bus_error_write:
324         sub     sp, 4
325         stmts   --sp, r0-lr
326         rcall   save_full_context_ex
327         mov     r11, 1
328         rjmp    1f
329
330 do_bus_error_read:
331         sub     sp, 4
332         stmts   --sp, r0-lr
333         rcall   save_full_context_ex
334         mov     r11, 0
335 1:      mfsr    r12, SYSREG_BEAR
336         mov     r10, sp
337         rcall   do_bus_error
338         rjmp    ret_from_exception
339
340         .align  1
341 do_nmi_ll:
342         sub     sp, 4
343         stmts   --sp, r0-lr
344         mfsr    r9, SYSREG_RSR_NMI
345         mfsr    r8, SYSREG_RAR_NMI
346         bfextu  r0, r9, MODE_SHIFT, 3
347         brne    2f
348
349 1:      pushm   r8, r9  /* PC and SR */
350         mfsr    r12, SYSREG_ECR
351         mov     r11, sp
352         rcall   do_nmi
353         popm    r8-r9
354         mtsr    SYSREG_RAR_NMI, r8
355         tst     r0, r0
356         mtsr    SYSREG_RSR_NMI, r9
357         brne    3f
358
359         ldmts   sp++, r0-lr
360         sub     sp, -4          /* skip r12_orig */
361         rete
362
363 2:      sub     r10, sp, -(FRAME_SIZE_FULL - REG_LR)
364         stdsp   sp[4], r10      /* replace saved SP */
365         rjmp    1b
366
367 3:      popm    lr
368         sub     sp, -4          /* skip sp */
369         popm    r0-r12
370         sub     sp, -4          /* skip r12_orig */
371         rete
372
373 handle_address_fault:
374         sub     sp, 4
375         stmts   --sp, r0-lr
376         rcall   save_full_context_ex
377         mfsr    r12, SYSREG_ECR
378         mov     r11, sp
379         rcall   do_address_exception
380         rjmp    ret_from_exception
381
382 handle_protection_fault:
383         sub     sp, 4
384         stmts   --sp, r0-lr
385         rcall   save_full_context_ex
386         mfsr    r12, SYSREG_ECR
387         mov     r11, sp
388         rcall   do_page_fault
389         rjmp    ret_from_exception
390
391         .align  1
392 do_illegal_opcode_ll:
393         sub     sp, 4
394         stmts   --sp, r0-lr
395         rcall   save_full_context_ex
396         mfsr    r12, SYSREG_ECR
397         mov     r11, sp
398         rcall   do_illegal_opcode
399         rjmp    ret_from_exception
400
401 do_dtlb_modified:
402         pushm   r0-r3
403         mfsr    r1, SYSREG_TLBEAR
404         mfsr    r0, SYSREG_PTBR
405         lsr     r2, r1, PGDIR_SHIFT
406         ld.w    r0, r0[r2 << 2]
407         lsl     r1, (32 - PGDIR_SHIFT)
408         lsr     r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
409
410         /* Translate to virtual address in P1 */
411         andl    r0, 0xf000
412         sbr     r0, 31
413         add     r2, r0, r1 << 2
414         ld.w    r3, r2[0]
415         sbr     r3, _PAGE_BIT_DIRTY
416         mov     r0, r3
417         st.w    r2[0], r3
418
419         /* The page table is up-to-date. Update the TLB entry as well */
420         andl    r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
421         mtsr    SYSREG_TLBELO, r0
422
423         /* MMUCR[DRP] is updated automatically, so let's go... */
424         tlbw
425
426         popm    r0-r3
427         rete
428
429 do_fpe_ll:
430         sub     sp, 4
431         stmts   --sp, r0-lr
432         rcall   save_full_context_ex
433         unmask_interrupts
434         mov     r12, 26
435         mov     r11, sp
436         rcall   do_fpe
437         rjmp    ret_from_exception
438
439 ret_from_exception:
440         mask_interrupts
441         lddsp   r4, sp[REG_SR]
442         andh    r4, (MODE_MASK >> 16), COH
443         brne    fault_resume_kernel
444
445         get_thread_info r0
446         ld.w    r1, r0[TI_flags]
447         andl    r1, _TIF_WORK_MASK, COH
448         brne    fault_exit_work
449
450 fault_resume_user:
451         popm    r8-r9
452         mask_exceptions
453         mtsr    SYSREG_RAR_EX, r8
454         mtsr    SYSREG_RSR_EX, r9
455         ldmts   sp++, r0-lr
456         sub     sp, -4
457         rete
458
459 fault_resume_kernel:
460 #ifdef CONFIG_PREEMPT
461         get_thread_info r0
462         ld.w    r2, r0[TI_preempt_count]
463         cp.w    r2, 0
464         brne    1f
465         ld.w    r1, r0[TI_flags]
466         bld     r1, TIF_NEED_RESCHED
467         brcc    1f
468         lddsp   r4, sp[REG_SR]
469         bld     r4, SYSREG_GM_OFFSET
470         brcs    1f
471         rcall   preempt_schedule_irq
472 1:
473 #endif
474
475         popm    r8-r9
476         mask_exceptions
477         mfsr    r1, SYSREG_SR
478         mtsr    SYSREG_RAR_EX, r8
479         mtsr    SYSREG_RSR_EX, r9
480         popm    lr
481         sub     sp, -4          /* ignore SP */
482         popm    r0-r12
483         sub     sp, -4          /* ignore r12_orig */
484         rete
485
486 irq_exit_work:
487         /* Switch to exception mode so that we can share the same code. */
488         mfsr    r8, SYSREG_SR
489         cbr     r8, SYSREG_M0_OFFSET
490         orh     r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
491         mtsr    SYSREG_SR, r8
492         sub     pc, -2
493         get_thread_info r0
494         ld.w    r1, r0[TI_flags]
495
496 fault_exit_work:
497         bld     r1, TIF_NEED_RESCHED
498         brcc    1f
499         unmask_interrupts
500         rcall   schedule
501         mask_interrupts
502         ld.w    r1, r0[TI_flags]
503         rjmp    fault_exit_work
504
505 1:      mov     r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
506         tst     r1, r2
507         breq    2f
508         unmask_interrupts
509         mov     r12, sp
510         mov     r11, r0
511         rcall   do_notify_resume
512         mask_interrupts
513         ld.w    r1, r0[TI_flags]
514         rjmp    fault_exit_work
515
516 2:      bld     r1, TIF_BREAKPOINT
517         brcc    fault_resume_user
518         mfsr    r3, SYSREG_TLBEHI
519         lddsp   r2, sp[REG_PC]
520         andl    r3, 0xff, COH
521         lsl     r3, 1
522         sbr     r3, 30
523         sbr     r3, 0
524         mtdr    DBGREG_BWA2A, r2
525         mtdr    DBGREG_BWC2A, r3
526         rjmp    fault_resume_user
527
528         /* If we get a debug trap from privileged context we end up here */
529 handle_debug_priv:
530         /* Fix up LR and SP in regs. r11 contains the mode we came from */
531         mfsr    r8, SYSREG_SR
532         mov     r9, r8
533         andh    r8, hi(~MODE_MASK)
534         or      r8, r11
535         mtsr    SYSREG_SR, r8
536         sub     pc, -2
537         stdsp   sp[REG_LR], lr
538         mtsr    SYSREG_SR, r9
539         sub     pc, -2
540         sub     r10, sp, -FRAME_SIZE_FULL
541         stdsp   sp[REG_SP], r10
542         mov     r12, sp
543         rcall   do_debug_priv
544
545         /* Now, put everything back */
546         ssrf    SR_EM_BIT
547         popm    r10, r11
548         mtsr    SYSREG_RAR_DBG, r10
549         mtsr    SYSREG_RSR_DBG, r11
550         mfsr    r8, SYSREG_SR
551         mov     r9, r8
552         andh    r8, hi(~MODE_MASK)
553         andh    r11, hi(MODE_MASK)
554         or      r8, r11
555         mtsr    SYSREG_SR, r8
556         sub     pc, -2
557         popm    lr
558         mtsr    SYSREG_SR, r9
559         sub     pc, -2
560         sub     sp, -4          /* skip SP */
561         popm    r0-r12
562         sub     sp, -4
563         retd
564
565         /*
566          * At this point, everything is masked, that is, interrupts,
567          * exceptions and debugging traps. We might get called from
568          * interrupt or exception context in some rare cases, but this
569          * will be taken care of by do_debug(), so we're not going to
570          * do a 100% correct context save here.
571          */
572 handle_debug:
573         sub     sp, 4           /* r12_orig */
574         stmts   --sp, r0-lr
575         mfsr    r10, SYSREG_RAR_DBG
576         mfsr    r11, SYSREG_RSR_DBG
577         unmask_exceptions
578         pushm   r10,r11
579         andh    r11, (MODE_MASK >> 16), COH
580         brne    handle_debug_priv
581
582         mov     r12, sp
583         rcall   do_debug
584
585         lddsp   r10, sp[REG_SR]
586         andh    r10, (MODE_MASK >> 16), COH
587         breq    debug_resume_user
588
589 debug_restore_all:
590         popm    r10,r11
591         mask_exceptions
592         mtsr    SYSREG_RSR_DBG, r11
593         mtsr    SYSREG_RAR_DBG, r10
594         ldmts   sp++, r0-lr
595         sub     sp, -4
596         retd
597
598 debug_resume_user:
599         get_thread_info r0
600         mask_interrupts
601
602         ld.w    r1, r0[TI_flags]
603         andl    r1, _TIF_DBGWORK_MASK, COH
604         breq    debug_restore_all
605
606 1:      bld     r1, TIF_NEED_RESCHED
607         brcc    2f
608         unmask_interrupts
609         rcall   schedule
610         mask_interrupts
611         ld.w    r1, r0[TI_flags]
612         rjmp    1b
613
614 2:      mov     r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
615         tst     r1, r2
616         breq    3f
617         unmask_interrupts
618         mov     r12, sp
619         mov     r11, r0
620         rcall   do_notify_resume
621         mask_interrupts
622         ld.w    r1, r0[TI_flags]
623         rjmp    1b
624
625 3:      bld     r1, TIF_SINGLE_STEP
626         brcc    debug_restore_all
627         mfdr    r2, DBGREG_DC
628         sbr     r2, DC_SS_BIT
629         mtdr    DBGREG_DC, r2
630         rjmp    debug_restore_all
631
632         .set    rsr_int0,       SYSREG_RSR_INT0
633         .set    rsr_int1,       SYSREG_RSR_INT1
634         .set    rsr_int2,       SYSREG_RSR_INT2
635         .set    rsr_int3,       SYSREG_RSR_INT3
636         .set    rar_int0,       SYSREG_RAR_INT0
637         .set    rar_int1,       SYSREG_RAR_INT1
638         .set    rar_int2,       SYSREG_RAR_INT2
639         .set    rar_int3,       SYSREG_RAR_INT3
640
641         .macro  IRQ_LEVEL level
642         .type   irq_level\level, @function
643 irq_level\level:
644         sub     sp, 4           /* r12_orig */
645         stmts   --sp,r0-lr
646         mfsr    r8, rar_int\level
647         mfsr    r9, rsr_int\level
648
649 #ifdef CONFIG_PREEMPT
650         sub     r11, pc, (. - system_call)
651         cp.w    r11, r8
652         breq    4f
653 #endif
654
655         pushm   r8-r9
656
657         mov     r11, sp
658         mov     r12, \level
659
660         rcall   do_IRQ
661
662         lddsp   r4, sp[REG_SR]
663         bfextu  r4, r4, SYSREG_M0_OFFSET, 3
664         cp.w    r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
665         breq    2f
666         cp.w    r4, MODE_USER >> SYSREG_M0_OFFSET
667 #ifdef CONFIG_PREEMPT
668         brne    3f
669 #else
670         brne    1f
671 #endif
672
673         get_thread_info r0
674         ld.w    r1, r0[TI_flags]
675         andl    r1, _TIF_WORK_MASK, COH
676         brne    irq_exit_work
677
678 1:      popm    r8-r9
679         mtsr    rar_int\level, r8
680         mtsr    rsr_int\level, r9
681         ldmts   sp++,r0-lr
682         sub     sp, -4          /* ignore r12_orig */
683         rete
684
685 #ifdef CONFIG_PREEMPT
686 4:      mask_interrupts
687         mfsr    r8, rsr_int\level
688         sbr     r8, 16
689         mtsr    rsr_int\level, r8
690         ldmts   sp++, r0-lr
691         sub     sp, -4          /* ignore r12_orig */
692         rete
693 #endif
694
695 2:      get_thread_info r0
696         ld.w    r1, r0[TI_flags]
697         bld     r1, TIF_CPU_GOING_TO_SLEEP
698 #ifdef CONFIG_PREEMPT
699         brcc    3f
700 #else
701         brcc    1b
702 #endif
703         sub     r1, pc, . - cpu_idle_skip_sleep
704         stdsp   sp[REG_PC], r1
705 #ifdef CONFIG_PREEMPT
706 3:      get_thread_info r0
707         ld.w    r2, r0[TI_preempt_count]
708         cp.w    r2, 0
709         brne    1b
710         ld.w    r1, r0[TI_flags]
711         bld     r1, TIF_NEED_RESCHED
712         brcc    1b
713         lddsp   r4, sp[REG_SR]
714         bld     r4, SYSREG_GM_OFFSET
715         brcs    1b
716         rcall   preempt_schedule_irq
717 #endif
718         rjmp    1b
719         .endm
720
721         .section .irq.text,"ax",@progbits
722
723 .global cpu_idle_sleep
724 cpu_idle_sleep:
725         mask_interrupts
726         get_thread_info r8
727         ld.w    r9, r8[TI_flags]
728         bld     r9, TIF_NEED_RESCHED
729         brcs    cpu_idle_enable_int_and_exit
730         sbr     r9, TIF_CPU_GOING_TO_SLEEP
731         st.w    r8[TI_flags], r9
732         unmask_interrupts
733         sleep 0
734 cpu_idle_skip_sleep:
735         mask_interrupts
736         ld.w    r9, r8[TI_flags]
737         cbr     r9, TIF_CPU_GOING_TO_SLEEP
738         st.w    r8[TI_flags], r9
739 cpu_idle_enable_int_and_exit:
740         unmask_interrupts
741         retal   r12
742
743         .global irq_level0
744         .global irq_level1
745         .global irq_level2
746         .global irq_level3
747         IRQ_LEVEL 0
748         IRQ_LEVEL 1
749         IRQ_LEVEL 2
750         IRQ_LEVEL 3