aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/kernel/entry-avr32b.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/avr32/kernel/entry-avr32b.S')
-rw-r--r--arch/avr32/kernel/entry-avr32b.S285
1 files changed, 178 insertions, 107 deletions
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index ccadfd9b438..8cf16d7a704 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -264,16 +264,7 @@ syscall_exit_work:
264 264
2653: bld r1, TIF_BREAKPOINT 2653: bld r1, TIF_BREAKPOINT
266 brcc syscall_exit_cont 266 brcc syscall_exit_cont
267 mfsr r3, SYSREG_TLBEHI 267 rjmp enter_monitor_mode
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 268
278 /* The slow path of the TLB miss handler */ 269 /* The slow path of the TLB miss handler */
279page_table_not_present: 270page_table_not_present:
@@ -288,11 +279,16 @@ page_not_present:
288 rjmp ret_from_exception 279 rjmp ret_from_exception
289 280
290 /* This function expects to find offending PC in SYSREG_RAR_EX */ 281 /* This function expects to find offending PC in SYSREG_RAR_EX */
282 .type save_full_context_ex, @function
283 .align 2
291save_full_context_ex: 284save_full_context_ex:
285 mfsr r11, SYSREG_RAR_EX
286 sub r9, pc, . - debug_trampoline
292 mfsr r8, SYSREG_RSR_EX 287 mfsr r8, SYSREG_RSR_EX
288 cp.w r9, r11
289 breq 3f
293 mov r12, r8 290 mov r12, r8
294 andh r8, (MODE_MASK >> 16), COH 291 andh r8, (MODE_MASK >> 16), COH
295 mfsr r11, SYSREG_RAR_EX
296 brne 2f 292 brne 2f
297 293
2981: pushm r11, r12 /* PC and SR */ 2941: pushm r11, r12 /* PC and SR */
@@ -303,10 +299,25 @@ save_full_context_ex:
303 stdsp sp[4], r10 /* replace saved SP */ 299 stdsp sp[4], r10 /* replace saved SP */
304 rjmp 1b 300 rjmp 1b
305 301
302 /*
303 * The debug handler set up a trampoline to make us
304 * automatically enter monitor mode upon return, but since
305 * we're saving the full context, we must assume that the
306 * exception handler might want to alter the return address
307 * and/or status register. So we need to restore the original
308 * context and enter monitor mode manually after the exception
309 * has been handled.
310 */
3113: get_thread_info r8
312 ld.w r11, r8[TI_rar_saved]
313 ld.w r12, r8[TI_rsr_saved]
314 rjmp 1b
315 .size save_full_context_ex, . - save_full_context_ex
316
306 /* Low-level exception handlers */ 317 /* Low-level exception handlers */
307handle_critical: 318handle_critical:
308 pushm r12 319 sub sp, 4
309 pushm r0-r12 320 stmts --sp, r0-lr
310 rcall save_full_context_ex 321 rcall save_full_context_ex
311 mfsr r12, SYSREG_ECR 322 mfsr r12, SYSREG_ECR
312 mov r11, sp 323 mov r11, sp
@@ -439,6 +450,7 @@ do_fpe_ll:
439ret_from_exception: 450ret_from_exception:
440 mask_interrupts 451 mask_interrupts
441 lddsp r4, sp[REG_SR] 452 lddsp r4, sp[REG_SR]
453
442 andh r4, (MODE_MASK >> 16), COH 454 andh r4, (MODE_MASK >> 16), COH
443 brne fault_resume_kernel 455 brne fault_resume_kernel
444 456
@@ -515,119 +527,124 @@ fault_exit_work:
515 527
5162: bld r1, TIF_BREAKPOINT 5282: bld r1, TIF_BREAKPOINT
517 brcc fault_resume_user 529 brcc fault_resume_user
518 mfsr r3, SYSREG_TLBEHI 530 rjmp enter_monitor_mode
519 lddsp r2, sp[REG_PC] 531
520 andl r3, 0xff, COH 532 .section .kprobes.text, "ax", @progbits
521 lsl r3, 1 533 .type handle_debug, @function
522 sbr r3, 30 534handle_debug:
523 sbr r3, 0 535 sub sp, 4 /* r12_orig */
524 mtdr DBGREG_BWA2A, r2 536 stmts --sp, r0-lr
525 mtdr DBGREG_BWC2A, r3 537 mfsr r8, SYSREG_RAR_DBG
526 rjmp fault_resume_user 538 mfsr r9, SYSREG_RSR_DBG
527 539 unmask_exceptions
528 /* If we get a debug trap from privileged context we end up here */ 540 pushm r8-r9
529handle_debug_priv: 541 bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
530 /* Fix up LR and SP in regs. r11 contains the mode we came from */ 542 brne debug_fixup_regs
543
544.Ldebug_fixup_cont:
545#ifdef CONFIG_TRACE_IRQFLAGS
546 rcall trace_hardirqs_off
547#endif
548 mov r12, sp
549 rcall do_debug
550 mov sp, r12
551
552 lddsp r2, sp[REG_SR]
553 bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
554 brne debug_resume_kernel
555
556 get_thread_info r0
557 ld.w r1, r0[TI_flags]
558 mov r2, _TIF_DBGWORK_MASK
559 tst r1, r2
560 brne debug_exit_work
561
562 bld r1, TIF_SINGLE_STEP
563 brcc 1f
564 mfdr r4, OCD_DC
565 sbr r4, OCD_DC_SS_BIT
566 mtdr OCD_DC, r4
567
5681: popm r10,r11
569 mask_exceptions
570 mtsr SYSREG_RSR_DBG, r11
571 mtsr SYSREG_RAR_DBG, r10
572#ifdef CONFIG_TRACE_IRQFLAGS
573 rcall trace_hardirqs_on
5741:
575#endif
576 ldmts sp++, r0-lr
577 sub sp, -4
578 retd
579 .size handle_debug, . - handle_debug
580
581 /* Mode of the trapped context is in r9 */
582 .type debug_fixup_regs, @function
583debug_fixup_regs:
531 mfsr r8, SYSREG_SR 584 mfsr r8, SYSREG_SR
532 mov r9, r8 585 mov r10, r8
533 andh r8, hi(~MODE_MASK) 586 bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
534 or r8, r11
535 mtsr SYSREG_SR, r8 587 mtsr SYSREG_SR, r8
536 sub pc, -2 588 sub pc, -2
537 stdsp sp[REG_LR], lr 589 stdsp sp[REG_LR], lr
538 mtsr SYSREG_SR, r9 590 mtsr SYSREG_SR, r10
539 sub pc, -2 591 sub pc, -2
540 sub r10, sp, -FRAME_SIZE_FULL 592 sub r8, sp, -FRAME_SIZE_FULL
541 stdsp sp[REG_SP], r10 593 stdsp sp[REG_SP], r8
542 mov r12, sp 594 rjmp .Ldebug_fixup_cont
543 rcall do_debug_priv 595 .size debug_fixup_regs, . - debug_fixup_regs
544 596
545 /* Now, put everything back */ 597 .type debug_resume_kernel, @function
546 ssrf SR_EM_BIT 598debug_resume_kernel:
599 mask_exceptions
547 popm r10, r11 600 popm r10, r11
548 mtsr SYSREG_RAR_DBG, r10 601 mtsr SYSREG_RAR_DBG, r10
549 mtsr SYSREG_RSR_DBG, r11 602 mtsr SYSREG_RSR_DBG, r11
550 mfsr r8, SYSREG_SR 603#ifdef CONFIG_TRACE_IRQFLAGS
551 mov r9, r8 604 bld r11, SYSREG_GM_OFFSET
552 andh r8, hi(~MODE_MASK) 605 brcc 1f
553 andh r11, hi(MODE_MASK) 606 rcall trace_hardirqs_on
554 or r8, r11 6071:
555 mtsr SYSREG_SR, r8 608#endif
609 mfsr r2, SYSREG_SR
610 mov r1, r2
611 bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
612 mtsr SYSREG_SR, r2
556 sub pc, -2 613 sub pc, -2
557 popm lr 614 popm lr
558 mtsr SYSREG_SR, r9 615 mtsr SYSREG_SR, r1
559 sub pc, -2 616 sub pc, -2
560 sub sp, -4 /* skip SP */ 617 sub sp, -4 /* skip SP */
561 popm r0-r12 618 popm r0-r12
562 sub sp, -4 619 sub sp, -4
563 retd 620 retd
621 .size debug_resume_kernel, . - debug_resume_kernel
564 622
623 .type debug_exit_work, @function
624debug_exit_work:
565 /* 625 /*
566 * At this point, everything is masked, that is, interrupts, 626 * We must return from Monitor Mode using a retd, and we must
567 * exceptions and debugging traps. We might get called from 627 * not schedule since that involves the D bit in SR getting
568 * interrupt or exception context in some rare cases, but this 628 * cleared by something other than the debug hardware. This
569 * will be taken care of by do_debug(), so we're not going to 629 * may cause undefined behaviour according to the Architecture
570 * do a 100% correct context save here. 630 * manual.
631 *
632 * So we fix up the return address and status and return to a
633 * stub below in Exception mode. From there, we can follow the
634 * normal exception return path.
635 *
636 * The real return address and status registers are stored on
637 * the stack in the way the exception return path understands,
638 * so no need to fix anything up there.
571 */ 639 */
572handle_debug: 640 sub r8, pc, . - fault_exit_work
573 sub sp, 4 /* r12_orig */ 641 mtsr SYSREG_RAR_DBG, r8
574 stmts --sp, r0-lr 642 mov r9, 0
575 mfsr r10, SYSREG_RAR_DBG 643 orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION)
576 mfsr r11, SYSREG_RSR_DBG 644 mtsr SYSREG_RSR_DBG, r9
577 unmask_exceptions 645 sub pc, -2
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
589debug_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 646 retd
597 647 .size debug_exit_work, . - debug_exit_work
598debug_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
6061: 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
6142: 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
6253: 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 648
632 .set rsr_int0, SYSREG_RSR_INT0 649 .set rsr_int0, SYSREG_RSR_INT0
633 .set rsr_int1, SYSREG_RSR_INT1 650 .set rsr_int1, SYSREG_RSR_INT1
@@ -675,7 +692,11 @@ irq_level\level:
675 andl r1, _TIF_WORK_MASK, COH 692 andl r1, _TIF_WORK_MASK, COH
676 brne irq_exit_work 693 brne irq_exit_work
677 694
6781: popm r8-r9 6951:
696#ifdef CONFIG_TRACE_IRQFLAGS
697 rcall trace_hardirqs_on
698#endif
699 popm r8-r9
679 mtsr rar_int\level, r8 700 mtsr rar_int\level, r8
680 mtsr rsr_int\level, r9 701 mtsr rsr_int\level, r9
681 ldmts sp++,r0-lr 702 ldmts sp++,r0-lr
@@ -748,3 +769,53 @@ cpu_idle_enable_int_and_exit:
748 IRQ_LEVEL 1 769 IRQ_LEVEL 1
749 IRQ_LEVEL 2 770 IRQ_LEVEL 2
750 IRQ_LEVEL 3 771 IRQ_LEVEL 3
772
773 .section .kprobes.text, "ax", @progbits
774 .type enter_monitor_mode, @function
775enter_monitor_mode:
776 /*
777 * We need to enter monitor mode to do a single step. The
778 * monitor code will alter the return address so that we
779 * return directly to the user instead of returning here.
780 */
781 breakpoint
782 rjmp breakpoint_failed
783
784 .size enter_monitor_mode, . - enter_monitor_mode
785
786 .type debug_trampoline, @function
787 .global debug_trampoline
788debug_trampoline:
789 /*
790 * Save the registers on the stack so that the monitor code
791 * can find them easily.
792 */
793 sub sp, 4 /* r12_orig */
794 stmts --sp, r0-lr
795 get_thread_info r0
796 ld.w r8, r0[TI_rar_saved]
797 ld.w r9, r0[TI_rsr_saved]
798 pushm r8-r9
799
800 /*
801 * The monitor code will alter the return address so we don't
802 * return here.
803 */
804 breakpoint
805 rjmp breakpoint_failed
806 .size debug_trampoline, . - debug_trampoline
807
808 .type breakpoint_failed, @function
809breakpoint_failed:
810 /*
811 * Something went wrong. Perhaps the debug hardware isn't
812 * enabled?
813 */
814 lda.w r12, msg_breakpoint_failed
815 mov r11, sp
816 mov r10, 9 /* SIGKILL */
817 call die
8181: rjmp 1b
819
820msg_breakpoint_failed:
821 .asciz "Failed to enter Debug Mode"