blob: 3cdd7071f35e131379e4b1d14adbb15e089d3af6 [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
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070077#define tlbmiss_save pushm r0-r3
78#define tlbmiss_restore popm r0-r3
79
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010080 .org 0x50
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070081 .global itlb_miss
82itlb_miss:
83 tlbmiss_save
84 rjmp tlb_miss_common
85
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010086 .org 0x60
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070087dtlb_miss_read:
88 tlbmiss_save
89 rjmp tlb_miss_common
90
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010091 .org 0x70
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070092dtlb_miss_write:
93 tlbmiss_save
94
95 .global tlb_miss_common
Haavard Skinnemoend704fb02008-01-14 21:42:56 +010096 .align 2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -070097tlb_miss_common:
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +010098 mfsr r0, SYSREG_TLBEAR
99 mfsr r1, SYSREG_PTBR
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700100
101 /* Is it the vmalloc space? */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100102 bld r0, 31
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700103 brcs handle_vmalloc_miss
104
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100105 /*
106 * First level lookup: The PGD contains virtual pointers to
107 * the second-level page tables, but they may be NULL if not
108 * present.
109 */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700110pgtbl_lookup:
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100111 lsr r2, r0, PGDIR_SHIFT
112 ld.w r3, r1[r2 << 2]
113 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100114 cp.w r3, 0
115 breq page_table_not_present
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700116
117 /* Second level lookup */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100118 ld.w r2, r3[r1 << 2]
119 mfsr r0, SYSREG_TLBARLO
120 bld r2, _PAGE_BIT_PRESENT
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700121 brcc page_not_present
122
123 /* Mark the page as accessed */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100124 sbr r2, _PAGE_BIT_ACCESSED
125 st.w r3[r1 << 2], r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700126
127 /* Drop software flags */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100128 andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
129 mtsr SYSREG_TLBELO, r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700130
131 /* Figure out which entry we want to replace */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100132 mfsr r1, SYSREG_MMUCR
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700133 clz r2, r0
134 brcc 1f
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100135 mov r3, -1 /* All entries have been accessed, */
136 mov r2, 0 /* so start at 0 */
137 mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700138
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +01001391: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
140 mtsr SYSREG_MMUCR, r1
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700141 tlbw
142
143 tlbmiss_restore
144 rete
145
146handle_vmalloc_miss:
147 /* Simply do the lookup in init's page table */
Haavard Skinnemoenc0c3e812007-03-14 13:59:13 +0100148 mov r1, lo(swapper_pg_dir)
149 orh r1, hi(swapper_pg_dir)
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700150 rjmp pgtbl_lookup
151
Haavard Skinnemoencfd23e92008-01-14 22:15:05 +0100152 /* The slow path of the TLB miss handler */
153 .align 2
154page_table_not_present:
155page_not_present:
156 tlbmiss_restore
157 sub sp, 4
158 stmts --sp, r0-lr
159 rcall save_full_context_ex
160 mfsr r12, SYSREG_ECR
161 mov r11, sp
162 rcall do_page_fault
163 rjmp ret_from_exception
164
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700165
166 /* --- System Call --- */
167
Haavard Skinnemoend704fb02008-01-14 21:42:56 +0100168 .org 0x100
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700169system_call:
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400170#ifdef CONFIG_PREEMPT
171 mask_interrupts
172#endif
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700173 pushm r12 /* r12_orig */
174 stmts --sp, r0-lr
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400175
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700176 mfsr r0, SYSREG_RAR_SUP
177 mfsr r1, SYSREG_RSR_SUP
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400178#ifdef CONFIG_PREEMPT
179 unmask_interrupts
180#endif
181 zero_fp
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700182 stm --sp, r0-r1
183
184 /* check for syscall tracing */
185 get_thread_info r0
186 ld.w r1, r0[TI_flags]
187 bld r1, TIF_SYSCALL_TRACE
188 brcs syscall_trace_enter
189
190syscall_trace_cont:
191 cp.w r8, NR_syscalls
192 brhs syscall_badsys
193
194 lddpc lr, syscall_table_addr
195 ld.w lr, lr[r8 << 2]
196 mov r8, r5 /* 5th argument (6th is pushed by stub) */
197 icall lr
198
199 .global syscall_return
200syscall_return:
201 get_thread_info r0
202 mask_interrupts /* make sure we don't miss an interrupt
203 setting need_resched or sigpending
204 between sampling and the rets */
205
206 /* Store the return value so that the correct value is loaded below */
207 stdsp sp[REG_R12], r12
208
209 ld.w r1, r0[TI_flags]
210 andl r1, _TIF_ALLWORK_MASK, COH
211 brne syscall_exit_work
212
213syscall_exit_cont:
214 popm r8-r9
215 mtsr SYSREG_RAR_SUP, r8
216 mtsr SYSREG_RSR_SUP, r9
217 ldmts sp++, r0-lr
218 sub sp, -4 /* r12_orig */
219 rets
220
221 .align 2
222syscall_table_addr:
223 .long sys_call_table
224
225syscall_badsys:
226 mov r12, -ENOSYS
227 rjmp syscall_return
228
229 .global ret_from_fork
230ret_from_fork:
231 rcall schedule_tail
232
233 /* check for syscall tracing */
234 get_thread_info r0
235 ld.w r1, r0[TI_flags]
236 andl r1, _TIF_ALLWORK_MASK, COH
237 brne syscall_exit_work
238 rjmp syscall_exit_cont
239
240syscall_trace_enter:
241 pushm r8-r12
242 rcall syscall_trace
243 popm r8-r12
244 rjmp syscall_trace_cont
245
246syscall_exit_work:
247 bld r1, TIF_SYSCALL_TRACE
248 brcc 1f
249 unmask_interrupts
250 rcall syscall_trace
251 mask_interrupts
252 ld.w r1, r0[TI_flags]
253
2541: bld r1, TIF_NEED_RESCHED
255 brcc 2f
256 unmask_interrupts
257 rcall schedule
258 mask_interrupts
259 ld.w r1, r0[TI_flags]
260 rjmp 1b
261
2622: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
263 tst r1, r2
264 breq 3f
265 unmask_interrupts
266 mov r12, sp
267 mov r11, r0
268 rcall do_notify_resume
269 mask_interrupts
270 ld.w r1, r0[TI_flags]
271 rjmp 1b
272
2733: bld r1, TIF_BREAKPOINT
274 brcc syscall_exit_cont
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100275 rjmp enter_monitor_mode
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700276
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700277 /* This function expects to find offending PC in SYSREG_RAR_EX */
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100278 .type save_full_context_ex, @function
279 .align 2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700280save_full_context_ex:
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100281 mfsr r11, SYSREG_RAR_EX
282 sub r9, pc, . - debug_trampoline
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700283 mfsr r8, SYSREG_RSR_EX
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100284 cp.w r9, r11
285 breq 3f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700286 mov r12, r8
287 andh r8, (MODE_MASK >> 16), COH
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700288 brne 2f
289
2901: pushm r11, r12 /* PC and SR */
291 unmask_exceptions
292 ret r12
293
2942: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
295 stdsp sp[4], r10 /* replace saved SP */
296 rjmp 1b
297
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100298 /*
299 * The debug handler set up a trampoline to make us
300 * automatically enter monitor mode upon return, but since
301 * we're saving the full context, we must assume that the
302 * exception handler might want to alter the return address
303 * and/or status register. So we need to restore the original
304 * context and enter monitor mode manually after the exception
305 * has been handled.
306 */
3073: get_thread_info r8
308 ld.w r11, r8[TI_rar_saved]
309 ld.w r12, r8[TI_rsr_saved]
310 rjmp 1b
311 .size save_full_context_ex, . - save_full_context_ex
312
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700313 /* Low-level exception handlers */
314handle_critical:
Haavard Skinnemoen5998a3c2007-12-03 18:30:15 +0100315 sub sp, 4
316 stmts --sp, r0-lr
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700317 rcall save_full_context_ex
318 mfsr r12, SYSREG_ECR
319 mov r11, sp
320 rcall do_critical_exception
321
322 /* We should never get here... */
323bad_return:
324 sub r12, pc, (. - 1f)
325 bral panic
326 .align 2
3271: .asciz "Return from critical exception!"
328
329 .align 1
330do_bus_error_write:
331 sub sp, 4
332 stmts --sp, r0-lr
333 rcall save_full_context_ex
334 mov r11, 1
335 rjmp 1f
336
337do_bus_error_read:
338 sub sp, 4
339 stmts --sp, r0-lr
340 rcall save_full_context_ex
341 mov r11, 0
3421: mfsr r12, SYSREG_BEAR
343 mov r10, sp
344 rcall do_bus_error
345 rjmp ret_from_exception
346
347 .align 1
348do_nmi_ll:
349 sub sp, 4
350 stmts --sp, r0-lr
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100351 mfsr r9, SYSREG_RSR_NMI
352 mfsr r8, SYSREG_RAR_NMI
353 bfextu r0, r9, MODE_SHIFT, 3
354 brne 2f
355
3561: pushm r8, r9 /* PC and SR */
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700357 mfsr r12, SYSREG_ECR
358 mov r11, sp
359 rcall do_nmi
Haavard Skinnemoen92b728c2007-03-13 10:06:37 +0100360 popm r8-r9
361 mtsr SYSREG_RAR_NMI, r8
362 tst r0, r0
363 mtsr SYSREG_RSR_NMI, r9
364 brne 3f
365
366 ldmts sp++, r0-lr
367 sub sp, -4 /* skip r12_orig */
368 rete
369
3702: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
371 stdsp sp[4], r10 /* replace saved SP */
372 rjmp 1b
373
3743: popm lr
375 sub sp, -4 /* skip sp */
376 popm r0-r12
377 sub sp, -4 /* skip r12_orig */
378 rete
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700379
380handle_address_fault:
381 sub sp, 4
382 stmts --sp, r0-lr
383 rcall save_full_context_ex
384 mfsr r12, SYSREG_ECR
385 mov r11, sp
386 rcall do_address_exception
387 rjmp ret_from_exception
388
389handle_protection_fault:
390 sub sp, 4
391 stmts --sp, r0-lr
392 rcall save_full_context_ex
393 mfsr r12, SYSREG_ECR
394 mov r11, sp
395 rcall do_page_fault
396 rjmp ret_from_exception
397
398 .align 1
399do_illegal_opcode_ll:
400 sub sp, 4
401 stmts --sp, r0-lr
402 rcall save_full_context_ex
403 mfsr r12, SYSREG_ECR
404 mov r11, sp
405 rcall do_illegal_opcode
406 rjmp ret_from_exception
407
408do_dtlb_modified:
409 pushm r0-r3
410 mfsr r1, SYSREG_TLBEAR
411 mfsr r0, SYSREG_PTBR
412 lsr r2, r1, PGDIR_SHIFT
413 ld.w r0, r0[r2 << 2]
414 lsl r1, (32 - PGDIR_SHIFT)
415 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
416
417 /* Translate to virtual address in P1 */
418 andl r0, 0xf000
419 sbr r0, 31
420 add r2, r0, r1 << 2
421 ld.w r3, r2[0]
422 sbr r3, _PAGE_BIT_DIRTY
423 mov r0, r3
424 st.w r2[0], r3
425
426 /* The page table is up-to-date. Update the TLB entry as well */
427 andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
428 mtsr SYSREG_TLBELO, r0
429
430 /* MMUCR[DRP] is updated automatically, so let's go... */
431 tlbw
432
433 popm r0-r3
434 rete
435
436do_fpe_ll:
437 sub sp, 4
438 stmts --sp, r0-lr
439 rcall save_full_context_ex
440 unmask_interrupts
441 mov r12, 26
442 mov r11, sp
443 rcall do_fpe
444 rjmp ret_from_exception
445
446ret_from_exception:
447 mask_interrupts
448 lddsp r4, sp[REG_SR]
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100449
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700450 andh r4, (MODE_MASK >> 16), COH
451 brne fault_resume_kernel
452
453 get_thread_info r0
454 ld.w r1, r0[TI_flags]
455 andl r1, _TIF_WORK_MASK, COH
456 brne fault_exit_work
457
458fault_resume_user:
459 popm r8-r9
460 mask_exceptions
461 mtsr SYSREG_RAR_EX, r8
462 mtsr SYSREG_RSR_EX, r9
463 ldmts sp++, r0-lr
464 sub sp, -4
465 rete
466
467fault_resume_kernel:
468#ifdef CONFIG_PREEMPT
469 get_thread_info r0
470 ld.w r2, r0[TI_preempt_count]
471 cp.w r2, 0
472 brne 1f
473 ld.w r1, r0[TI_flags]
474 bld r1, TIF_NEED_RESCHED
475 brcc 1f
476 lddsp r4, sp[REG_SR]
477 bld r4, SYSREG_GM_OFFSET
478 brcs 1f
479 rcall preempt_schedule_irq
4801:
481#endif
482
483 popm r8-r9
484 mask_exceptions
485 mfsr r1, SYSREG_SR
486 mtsr SYSREG_RAR_EX, r8
487 mtsr SYSREG_RSR_EX, r9
488 popm lr
489 sub sp, -4 /* ignore SP */
490 popm r0-r12
491 sub sp, -4 /* ignore r12_orig */
492 rete
493
494irq_exit_work:
495 /* Switch to exception mode so that we can share the same code. */
496 mfsr r8, SYSREG_SR
497 cbr r8, SYSREG_M0_OFFSET
498 orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
499 mtsr SYSREG_SR, r8
500 sub pc, -2
501 get_thread_info r0
502 ld.w r1, r0[TI_flags]
503
504fault_exit_work:
505 bld r1, TIF_NEED_RESCHED
506 brcc 1f
507 unmask_interrupts
508 rcall schedule
509 mask_interrupts
510 ld.w r1, r0[TI_flags]
511 rjmp fault_exit_work
512
5131: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
514 tst r1, r2
515 breq 2f
516 unmask_interrupts
517 mov r12, sp
518 mov r11, r0
519 rcall do_notify_resume
520 mask_interrupts
521 ld.w r1, r0[TI_flags]
522 rjmp fault_exit_work
523
5242: bld r1, TIF_BREAKPOINT
525 brcc fault_resume_user
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100526 rjmp enter_monitor_mode
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700527
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100528 .section .kprobes.text, "ax", @progbits
529 .type handle_debug, @function
530handle_debug:
531 sub sp, 4 /* r12_orig */
532 stmts --sp, r0-lr
533 mfsr r8, SYSREG_RAR_DBG
534 mfsr r9, SYSREG_RSR_DBG
535 unmask_exceptions
536 pushm r8-r9
537 bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
538 brne debug_fixup_regs
539
540.Ldebug_fixup_cont:
541#ifdef CONFIG_TRACE_IRQFLAGS
542 rcall trace_hardirqs_off
543#endif
544 mov r12, sp
545 rcall do_debug
546 mov sp, r12
547
548 lddsp r2, sp[REG_SR]
549 bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
550 brne debug_resume_kernel
551
552 get_thread_info r0
553 ld.w r1, r0[TI_flags]
554 mov r2, _TIF_DBGWORK_MASK
555 tst r1, r2
556 brne debug_exit_work
557
558 bld r1, TIF_SINGLE_STEP
559 brcc 1f
560 mfdr r4, OCD_DC
561 sbr r4, OCD_DC_SS_BIT
562 mtdr OCD_DC, r4
563
5641: popm r10,r11
565 mask_exceptions
566 mtsr SYSREG_RSR_DBG, r11
567 mtsr SYSREG_RAR_DBG, r10
568#ifdef CONFIG_TRACE_IRQFLAGS
569 rcall trace_hardirqs_on
5701:
571#endif
572 ldmts sp++, r0-lr
573 sub sp, -4
574 retd
575 .size handle_debug, . - handle_debug
576
577 /* Mode of the trapped context is in r9 */
578 .type debug_fixup_regs, @function
579debug_fixup_regs:
580 mfsr r8, SYSREG_SR
581 mov r10, r8
582 bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
583 mtsr SYSREG_SR, r8
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700584 sub pc, -2
585 stdsp sp[REG_LR], lr
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100586 mtsr SYSREG_SR, r10
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700587 sub pc, -2
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100588 sub r8, sp, -FRAME_SIZE_FULL
589 stdsp sp[REG_SP], r8
590 rjmp .Ldebug_fixup_cont
591 .size debug_fixup_regs, . - debug_fixup_regs
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700592
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100593 .type debug_resume_kernel, @function
594debug_resume_kernel:
595 mask_exceptions
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700596 popm r10, r11
597 mtsr SYSREG_RAR_DBG, r10
598 mtsr SYSREG_RSR_DBG, r11
Haavard Skinnemoen320516b2007-11-26 14:34:57 +0100599#ifdef CONFIG_TRACE_IRQFLAGS
600 bld r11, SYSREG_GM_OFFSET
601 brcc 1f
602 rcall trace_hardirqs_on
6031:
604#endif
605 mfsr r2, SYSREG_SR
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100606 mov r1, r2
607 bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
Haavard Skinnemoen320516b2007-11-26 14:34:57 +0100608 mtsr SYSREG_SR, r2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700609 sub pc, -2
610 popm lr
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100611 mtsr SYSREG_SR, r1
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700612 sub pc, -2
613 sub sp, -4 /* skip SP */
614 popm r0-r12
615 sub sp, -4
616 retd
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100617 .size debug_resume_kernel, . - debug_resume_kernel
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700618
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100619 .type debug_exit_work, @function
620debug_exit_work:
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700621 /*
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100622 * We must return from Monitor Mode using a retd, and we must
623 * not schedule since that involves the D bit in SR getting
624 * cleared by something other than the debug hardware. This
625 * may cause undefined behaviour according to the Architecture
626 * manual.
627 *
628 * So we fix up the return address and status and return to a
629 * stub below in Exception mode. From there, we can follow the
630 * normal exception return path.
631 *
632 * The real return address and status registers are stored on
633 * the stack in the way the exception return path understands,
634 * so no need to fix anything up there.
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700635 */
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100636 sub r8, pc, . - fault_exit_work
637 mtsr SYSREG_RAR_DBG, r8
638 mov r9, 0
639 orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION)
640 mtsr SYSREG_RSR_DBG, r9
641 sub pc, -2
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700642 retd
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100643 .size debug_exit_work, . - debug_exit_work
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700644
645 .set rsr_int0, SYSREG_RSR_INT0
646 .set rsr_int1, SYSREG_RSR_INT1
647 .set rsr_int2, SYSREG_RSR_INT2
648 .set rsr_int3, SYSREG_RSR_INT3
649 .set rar_int0, SYSREG_RAR_INT0
650 .set rar_int1, SYSREG_RAR_INT1
651 .set rar_int2, SYSREG_RAR_INT2
652 .set rar_int3, SYSREG_RAR_INT3
653
654 .macro IRQ_LEVEL level
655 .type irq_level\level, @function
656irq_level\level:
657 sub sp, 4 /* r12_orig */
658 stmts --sp,r0-lr
659 mfsr r8, rar_int\level
660 mfsr r9, rsr_int\level
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400661
662#ifdef CONFIG_PREEMPT
663 sub r11, pc, (. - system_call)
664 cp.w r11, r8
665 breq 4f
666#endif
667
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700668 pushm r8-r9
669
670 mov r11, sp
671 mov r12, \level
672
673 rcall do_IRQ
674
675 lddsp r4, sp[REG_SR]
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100676 bfextu r4, r4, SYSREG_M0_OFFSET, 3
677 cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
678 breq 2f
679 cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700680#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100681 brne 3f
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700682#else
683 brne 1f
684#endif
685
686 get_thread_info r0
687 ld.w r1, r0[TI_flags]
688 andl r1, _TIF_WORK_MASK, COH
689 brne irq_exit_work
690
Haavard Skinnemoen320516b2007-11-26 14:34:57 +01006911:
692#ifdef CONFIG_TRACE_IRQFLAGS
693 rcall trace_hardirqs_on
694#endif
695 popm r8-r9
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700696 mtsr rar_int\level, r8
697 mtsr rsr_int\level, r9
698 ldmts sp++,r0-lr
699 sub sp, -4 /* ignore r12_orig */
700 rete
701
Philippe Rétornaza7e30b82007-10-10 18:52:24 -0400702#ifdef CONFIG_PREEMPT
7034: mask_interrupts
704 mfsr r8, rsr_int\level
705 sbr r8, 16
706 mtsr rsr_int\level, r8
707 ldmts sp++, r0-lr
708 sub sp, -4 /* ignore r12_orig */
709 rete
710#endif
711
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +01007122: get_thread_info r0
713 ld.w r1, r0[TI_flags]
714 bld r1, TIF_CPU_GOING_TO_SLEEP
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700715#ifdef CONFIG_PREEMPT
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100716 brcc 3f
717#else
718 brcc 1b
719#endif
720 sub r1, pc, . - cpu_idle_skip_sleep
721 stdsp sp[REG_PC], r1
722#ifdef CONFIG_PREEMPT
7233: get_thread_info r0
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700724 ld.w r2, r0[TI_preempt_count]
725 cp.w r2, 0
726 brne 1b
727 ld.w r1, r0[TI_flags]
728 bld r1, TIF_NEED_RESCHED
729 brcc 1b
730 lddsp r4, sp[REG_SR]
731 bld r4, SYSREG_GM_OFFSET
732 brcs 1b
733 rcall preempt_schedule_irq
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700734#endif
Hans-Christian Egtvedt19b7ce82007-02-26 13:50:43 +0100735 rjmp 1b
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700736 .endm
737
738 .section .irq.text,"ax",@progbits
739
Haavard Skinnemoen5f97f7f2006-09-25 23:32:13 -0700740 .global irq_level0
741 .global irq_level1
742 .global irq_level2
743 .global irq_level3
744 IRQ_LEVEL 0
745 IRQ_LEVEL 1
746 IRQ_LEVEL 2
747 IRQ_LEVEL 3
Haavard Skinnemoen2507bc12007-11-28 15:04:01 +0100748
749 .section .kprobes.text, "ax", @progbits
750 .type enter_monitor_mode, @function
751enter_monitor_mode:
752 /*
753 * We need to enter monitor mode to do a single step. The
754 * monitor code will alter the return address so that we
755 * return directly to the user instead of returning here.
756 */
757 breakpoint
758 rjmp breakpoint_failed
759
760 .size enter_monitor_mode, . - enter_monitor_mode
761
762 .type debug_trampoline, @function
763 .global debug_trampoline
764debug_trampoline:
765 /*
766 * Save the registers on the stack so that the monitor code
767 * can find them easily.
768 */
769 sub sp, 4 /* r12_orig */
770 stmts --sp, r0-lr
771 get_thread_info r0
772 ld.w r8, r0[TI_rar_saved]
773 ld.w r9, r0[TI_rsr_saved]
774 pushm r8-r9
775
776 /*
777 * The monitor code will alter the return address so we don't
778 * return here.
779 */
780 breakpoint
781 rjmp breakpoint_failed
782 .size debug_trampoline, . - debug_trampoline
783
784 .type breakpoint_failed, @function
785breakpoint_failed:
786 /*
787 * Something went wrong. Perhaps the debug hardware isn't
788 * enabled?
789 */
790 lda.w r12, msg_breakpoint_failed
791 mov r11, sp
792 mov r10, 9 /* SIGKILL */
793 call die
7941: rjmp 1b
795
796msg_breakpoint_failed:
797 .asciz "Failed to enter Debug Mode"