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