2 * Copyright (C) 2004-2006 Atmel Corporation
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.
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.
14 #include <linux/errno.h>
17 #include <asm/hardirq.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>
28 # define preempt_stop mask_interrupts
31 # define fault_resume_kernel fault_restore_all
34 #define __MASK(x) ((1 << (x)) - 1)
35 #define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
36 (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
38 .section .ex.text,"ax",@progbits
45 bral do_bus_error_write
47 bral do_bus_error_read
51 bral handle_address_fault
53 bral handle_protection_fault
57 bral do_illegal_opcode_ll
59 bral do_illegal_opcode_ll
61 bral do_illegal_opcode_ll
65 bral do_illegal_opcode_ll
67 bral handle_address_fault
69 bral handle_address_fault
71 bral handle_protection_fault
73 bral handle_protection_fault
77 #define tlbmiss_save pushm r0-r3
78 #define tlbmiss_restore popm r0-r3
95 .global tlb_miss_common
98 mfsr r0, SYSREG_TLBEAR
102 * First level lookup: The PGD contains virtual pointers to
103 * the second-level page tables, but they may be NULL if not
107 lsr r2, r0, PGDIR_SHIFT
109 bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
111 breq page_table_not_present
113 /* Second level lookup */
115 mfsr r0, SYSREG_TLBARLO
116 bld r2, _PAGE_BIT_PRESENT
117 brcc page_not_present
119 /* Mark the page as accessed */
120 sbr r2, _PAGE_BIT_ACCESSED
123 /* Drop software flags */
124 andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
125 mtsr SYSREG_TLBELO, r2
127 /* Figure out which entry we want to replace */
128 mfsr r1, SYSREG_MMUCR
131 mov r3, -1 /* All entries have been accessed, */
132 mov r2, 0 /* so start at 0 */
133 mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */
135 1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE
136 mtsr SYSREG_MMUCR, r1
142 /* The slow path of the TLB miss handler */
144 page_table_not_present:
145 /* Do we need to synchronize with swapper_pg_dir? */
147 brcs sync_with_swapper_pg_dir
153 call save_full_context_ex
157 rjmp ret_from_exception
160 sync_with_swapper_pg_dir:
162 * If swapper_pg_dir contains a non-NULL second-level page
163 * table pointer, copy it into the current PGD. If not, we
164 * must handle it as a full-blown page fault.
166 * Jumping back to pgtbl_lookup causes an unnecessary lookup,
167 * but it is guaranteed to be a cache hit, it won't happen
168 * very often, and we absolutely do not want to sacrifice any
169 * performance in the fast path in order to improve this.
171 mov r1, lo(swapper_pg_dir)
172 orh r1, hi(swapper_pg_dir)
175 breq page_not_present
181 * We currently have two bytes left at this point until we
182 * crash into the system call handler...
184 * Don't worry, the assembler will let us know.
188 /* --- System Call --- */
192 #ifdef CONFIG_PREEMPT
195 pushm r12 /* r12_orig */
198 mfsr r0, SYSREG_RAR_SUP
199 mfsr r1, SYSREG_RSR_SUP
200 #ifdef CONFIG_PREEMPT
206 /* check for syscall tracing */
208 ld.w r1, r0[TI_flags]
209 bld r1, TIF_SYSCALL_TRACE
210 brcs syscall_trace_enter
216 lddpc lr, syscall_table_addr
218 mov r8, r5 /* 5th argument (6th is pushed by stub) */
221 .global syscall_return
224 mask_interrupts /* make sure we don't miss an interrupt
225 setting need_resched or sigpending
226 between sampling and the rets */
228 /* Store the return value so that the correct value is loaded below */
229 stdsp sp[REG_R12], r12
231 ld.w r1, r0[TI_flags]
232 andl r1, _TIF_ALLWORK_MASK, COH
233 brne syscall_exit_work
237 mtsr SYSREG_RAR_SUP, r8
238 mtsr SYSREG_RSR_SUP, r9
240 sub sp, -4 /* r12_orig */
251 .global ret_from_fork
257 .global ret_from_kernel_thread
258 ret_from_kernel_thread:
261 mov lr, r2 /* syscall_return */
268 rjmp syscall_trace_cont
271 bld r1, TIF_SYSCALL_TRACE
276 ld.w r1, r0[TI_flags]
278 1: bld r1, TIF_NEED_RESCHED
283 ld.w r1, r0[TI_flags]
286 2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
292 call do_notify_resume
294 ld.w r1, r0[TI_flags]
297 3: bld r1, TIF_BREAKPOINT
298 brcc syscall_exit_cont
299 rjmp enter_monitor_mode
301 /* This function expects to find offending PC in SYSREG_RAR_EX */
302 .type save_full_context_ex, @function
304 save_full_context_ex:
305 mfsr r11, SYSREG_RAR_EX
306 sub r9, pc, . - debug_trampoline
307 mfsr r8, SYSREG_RSR_EX
311 andh r8, (MODE_MASK >> 16), COH
314 1: pushm r11, r12 /* PC and SR */
318 2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
319 stdsp sp[4], r10 /* replace saved SP */
323 * The debug handler set up a trampoline to make us
324 * automatically enter monitor mode upon return, but since
325 * we're saving the full context, we must assume that the
326 * exception handler might want to alter the return address
327 * and/or status register. So we need to restore the original
328 * context and enter monitor mode manually after the exception
331 3: get_thread_info r8
332 ld.w r11, r8[TI_rar_saved]
333 ld.w r12, r8[TI_rsr_saved]
335 .size save_full_context_ex, . - save_full_context_ex
337 /* Low-level exception handlers */
342 * After a Java stack overflow or underflow trap, any CPU
343 * memory access may cause erratic behavior. This will happen
344 * when the four least significant bits of the JOSP system
345 * register contains any value between 9 and 15 (inclusive).
347 * Possible workarounds:
348 * - Don't use the Java Extension Module
349 * - Ensure that the stack overflow and underflow trap
350 * handlers do not do any memory access or trigger any
351 * exceptions before the overflow/underflow condition is
352 * cleared (by incrementing or decrementing the JOSP)
353 * - Make sure that JOSP does not contain any problematic
354 * value before doing any exception or interrupt
356 * - Set up a critical exception handler which writes a
357 * known-to-be-safe value, e.g. 4, to JOSP before doing
358 * any further processing.
360 * We'll use the last workaround for now since we cannot
361 * guarantee that user space processes don't use Java mode.
362 * Non-well-behaving userland will be terminated with extreme
365 #ifdef CONFIG_CPU_AT32AP700X
367 * There's a chance we can't touch memory, so temporarily
368 * borrow PTBR to save the stack pointer while we fix things
377 /* Push most of pt_regs on stack. We'll do the rest later */
381 /* PTBR mirrors current_thread_info()->task->active_mm->pgd */
384 ld.w r2, r1[TSK_active_mm]
391 sub r0, sp, -(14 * 4)
393 mfsr r2, SYSREG_RAR_EX
394 mfsr r3, SYSREG_RSR_EX
399 call do_critical_exception
401 /* We should never get here... */
403 sub r12, pc, (. - 1f)
406 1: .asciz "Return from critical exception!"
412 call save_full_context_ex
419 call save_full_context_ex
421 1: mfsr r12, SYSREG_BEAR
424 rjmp ret_from_exception
430 mfsr r9, SYSREG_RSR_NMI
431 mfsr r8, SYSREG_RAR_NMI
432 bfextu r0, r9, MODE_SHIFT, 3
435 1: pushm r8, r9 /* PC and SR */
440 mtsr SYSREG_RAR_NMI, r8
442 mtsr SYSREG_RSR_NMI, r9
446 sub sp, -4 /* skip r12_orig */
449 2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
450 stdsp sp[4], r10 /* replace saved SP */
454 sub sp, -4 /* skip sp */
456 sub sp, -4 /* skip r12_orig */
459 handle_address_fault:
462 call save_full_context_ex
465 call do_address_exception
466 rjmp ret_from_exception
468 handle_protection_fault:
471 call save_full_context_ex
475 rjmp ret_from_exception
478 do_illegal_opcode_ll:
481 call save_full_context_ex
484 call do_illegal_opcode
485 rjmp ret_from_exception
489 mfsr r1, SYSREG_TLBEAR
491 lsr r2, r1, PGDIR_SHIFT
493 lsl r1, (32 - PGDIR_SHIFT)
494 lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
496 /* Translate to virtual address in P1 */
501 sbr r3, _PAGE_BIT_DIRTY
505 /* The page table is up-to-date. Update the TLB entry as well */
506 andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
507 mtsr SYSREG_TLBELO, r0
509 /* MMUCR[DRP] is updated automatically, so let's go... */
518 call save_full_context_ex
523 rjmp ret_from_exception
529 andh r4, (MODE_MASK >> 16), COH
530 brne fault_resume_kernel
533 ld.w r1, r0[TI_flags]
534 andl r1, _TIF_WORK_MASK, COH
540 mtsr SYSREG_RAR_EX, r8
541 mtsr SYSREG_RSR_EX, r9
547 #ifdef CONFIG_PREEMPT
549 ld.w r2, r0[TI_preempt_count]
552 ld.w r1, r0[TI_flags]
553 bld r1, TIF_NEED_RESCHED
556 bld r4, SYSREG_GM_OFFSET
558 call preempt_schedule_irq
565 mtsr SYSREG_RAR_EX, r8
566 mtsr SYSREG_RSR_EX, r9
568 sub sp, -4 /* ignore SP */
570 sub sp, -4 /* ignore r12_orig */
574 /* Switch to exception mode so that we can share the same code. */
576 cbr r8, SYSREG_M0_OFFSET
577 orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
581 ld.w r1, r0[TI_flags]
584 bld r1, TIF_NEED_RESCHED
589 ld.w r1, r0[TI_flags]
592 1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
598 call do_notify_resume
600 ld.w r1, r0[TI_flags]
603 2: bld r1, TIF_BREAKPOINT
604 brcc fault_resume_user
605 rjmp enter_monitor_mode
607 .section .kprobes.text, "ax", @progbits
608 .type handle_debug, @function
610 sub sp, 4 /* r12_orig */
612 mfsr r8, SYSREG_RAR_DBG
613 mfsr r9, SYSREG_RSR_DBG
616 bfextu r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
617 brne debug_fixup_regs
620 #ifdef CONFIG_TRACE_IRQFLAGS
621 call trace_hardirqs_off
628 bfextu r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
629 brne debug_resume_kernel
632 ld.w r1, r0[TI_flags]
633 mov r2, _TIF_DBGWORK_MASK
637 bld r1, TIF_SINGLE_STEP
640 sbr r4, OCD_DC_SS_BIT
645 mtsr SYSREG_RSR_DBG, r11
646 mtsr SYSREG_RAR_DBG, r10
647 #ifdef CONFIG_TRACE_IRQFLAGS
648 call trace_hardirqs_on
654 .size handle_debug, . - handle_debug
656 /* Mode of the trapped context is in r9 */
657 .type debug_fixup_regs, @function
661 bfins r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
667 sub r8, sp, -FRAME_SIZE_FULL
669 rjmp .Ldebug_fixup_cont
670 .size debug_fixup_regs, . - debug_fixup_regs
672 .type debug_resume_kernel, @function
676 mtsr SYSREG_RAR_DBG, r10
677 mtsr SYSREG_RSR_DBG, r11
678 #ifdef CONFIG_TRACE_IRQFLAGS
679 bld r11, SYSREG_GM_OFFSET
681 call trace_hardirqs_on
686 bfins r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE
692 sub sp, -4 /* skip SP */
696 .size debug_resume_kernel, . - debug_resume_kernel
698 .type debug_exit_work, @function
701 * We must return from Monitor Mode using a retd, and we must
702 * not schedule since that involves the D bit in SR getting
703 * cleared by something other than the debug hardware. This
704 * may cause undefined behaviour according to the Architecture
707 * So we fix up the return address and status and return to a
708 * stub below in Exception mode. From there, we can follow the
709 * normal exception return path.
711 * The real return address and status registers are stored on
712 * the stack in the way the exception return path understands,
713 * so no need to fix anything up there.
715 sub r8, pc, . - fault_exit_work
716 mtsr SYSREG_RAR_DBG, r8
718 orh r9, hi(SR_EM | SR_GM | MODE_EXCEPTION)
719 mtsr SYSREG_RSR_DBG, r9
722 .size debug_exit_work, . - debug_exit_work
724 .set rsr_int0, SYSREG_RSR_INT0
725 .set rsr_int1, SYSREG_RSR_INT1
726 .set rsr_int2, SYSREG_RSR_INT2
727 .set rsr_int3, SYSREG_RSR_INT3
728 .set rar_int0, SYSREG_RAR_INT0
729 .set rar_int1, SYSREG_RAR_INT1
730 .set rar_int2, SYSREG_RAR_INT2
731 .set rar_int3, SYSREG_RAR_INT3
733 .macro IRQ_LEVEL level
734 .type irq_level\level, @function
736 sub sp, 4 /* r12_orig */
738 mfsr r8, rar_int\level
739 mfsr r9, rsr_int\level
741 #ifdef CONFIG_PREEMPT
742 sub r11, pc, (. - system_call)
755 bfextu r4, r4, SYSREG_M0_OFFSET, 3
756 cp.w r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET
758 cp.w r4, MODE_USER >> SYSREG_M0_OFFSET
759 #ifdef CONFIG_PREEMPT
766 ld.w r1, r0[TI_flags]
767 andl r1, _TIF_WORK_MASK, COH
771 #ifdef CONFIG_TRACE_IRQFLAGS
772 call trace_hardirqs_on
775 mtsr rar_int\level, r8
776 mtsr rsr_int\level, r9
778 sub sp, -4 /* ignore r12_orig */
781 #ifdef CONFIG_PREEMPT
783 mfsr r8, rsr_int\level
785 mtsr rsr_int\level, r8
787 sub sp, -4 /* ignore r12_orig */
791 2: get_thread_info r0
792 ld.w r1, r0[TI_flags]
793 bld r1, TIF_CPU_GOING_TO_SLEEP
794 #ifdef CONFIG_PREEMPT
799 sub r1, pc, . - cpu_idle_skip_sleep
801 #ifdef CONFIG_PREEMPT
802 3: get_thread_info r0
803 ld.w r2, r0[TI_preempt_count]
806 ld.w r1, r0[TI_flags]
807 bld r1, TIF_NEED_RESCHED
810 bld r4, SYSREG_GM_OFFSET
812 call preempt_schedule_irq
817 .section .irq.text,"ax",@progbits
828 .section .kprobes.text, "ax", @progbits
829 .type enter_monitor_mode, @function
832 * We need to enter monitor mode to do a single step. The
833 * monitor code will alter the return address so that we
834 * return directly to the user instead of returning here.
837 rjmp breakpoint_failed
839 .size enter_monitor_mode, . - enter_monitor_mode
841 .type debug_trampoline, @function
842 .global debug_trampoline
845 * Save the registers on the stack so that the monitor code
846 * can find them easily.
848 sub sp, 4 /* r12_orig */
851 ld.w r8, r0[TI_rar_saved]
852 ld.w r9, r0[TI_rsr_saved]
856 * The monitor code will alter the return address so we don't
860 rjmp breakpoint_failed
861 .size debug_trampoline, . - debug_trampoline
863 .type breakpoint_failed, @function
866 * Something went wrong. Perhaps the debug hardware isn't
869 lda.w r12, msg_breakpoint_failed
871 mov r10, 9 /* SIGKILL */
875 msg_breakpoint_failed:
876 .asciz "Failed to enter Debug Mode"