📄 entry-avr32b.s
字号:
/* * Copyright (C) 2004-2006 Atmel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. *//* * This file contains the low-level entry-points into the kernel, that is, * exception handlers, debug trap handlers, interrupt handlers and the * system call handler. */#include <linux/errno.h>#include <asm/asm.h>#include <asm/hardirq.h>#include <asm/irq.h>#include <asm/ocd.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/ptrace.h>#include <asm/sysreg.h>#include <asm/thread_info.h>#include <asm/unistd.h>#ifdef CONFIG_PREEMPT# define preempt_stop mask_interrupts#else# define preempt_stop# define fault_resume_kernel fault_restore_all#endif#define __MASK(x) ((1 << (x)) - 1)#define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \ (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)) .section .ex.text,"ax",@progbits .align 2exception_vectors: bral handle_critical .align 2 bral handle_critical .align 2 bral do_bus_error_write .align 2 bral do_bus_error_read .align 2 bral do_nmi_ll .align 2 bral handle_address_fault .align 2 bral handle_protection_fault .align 2 bral handle_debug .align 2 bral do_illegal_opcode_ll .align 2 bral do_illegal_opcode_ll .align 2 bral do_illegal_opcode_ll .align 2 bral do_fpe_ll .align 2 bral do_illegal_opcode_ll .align 2 bral handle_address_fault .align 2 bral handle_address_fault .align 2 bral handle_protection_fault .align 2 bral handle_protection_fault .align 2 bral do_dtlb_modified /* * r0 : PGD/PT/PTE * r1 : Offending address * r2 : Scratch register * r3 : Cause (5, 12 or 13) */#define tlbmiss_save pushm r0-r3#define tlbmiss_restore popm r0-r3 .section .tlbx.ex.text,"ax",@progbits .global itlb_missitlb_miss: tlbmiss_save rjmp tlb_miss_common .section .tlbr.ex.text,"ax",@progbitsdtlb_miss_read: tlbmiss_save rjmp tlb_miss_common .section .tlbw.ex.text,"ax",@progbitsdtlb_miss_write: tlbmiss_save .global tlb_miss_commontlb_miss_common: mfsr r0, SYSREG_TLBEAR mfsr r1, SYSREG_PTBR /* Is it the vmalloc space? */ bld r0, 31 brcs handle_vmalloc_miss /* First level lookup */pgtbl_lookup: lsr r2, r0, PGDIR_SHIFT ld.w r3, r1[r2 << 2] bfextu r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT bld r3, _PAGE_BIT_PRESENT brcc page_table_not_present /* Translate to virtual address in P1. */ andl r3, 0xf000 sbr r3, 31 /* Second level lookup */ ld.w r2, r3[r1 << 2] mfsr r0, SYSREG_TLBARLO bld r2, _PAGE_BIT_PRESENT brcc page_not_present /* Mark the page as accessed */ sbr r2, _PAGE_BIT_ACCESSED st.w r3[r1 << 2], r2 /* Drop software flags */ andl r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff mtsr SYSREG_TLBELO, r2 /* Figure out which entry we want to replace */ mfsr r1, SYSREG_MMUCR clz r2, r0 brcc 1f mov r3, -1 /* All entries have been accessed, */ mov r2, 0 /* so start at 0 */ mtsr SYSREG_TLBARLO, r3 /* and reset TLBAR */1: bfins r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE mtsr SYSREG_MMUCR, r1 tlbw tlbmiss_restore retehandle_vmalloc_miss: /* Simply do the lookup in init's page table */ mov r1, lo(swapper_pg_dir) orh r1, hi(swapper_pg_dir) rjmp pgtbl_lookup /* --- System Call --- */ .section .scall.text,"ax",@progbitssystem_call:#ifdef CONFIG_PREEMPT mask_interrupts#endif pushm r12 /* r12_orig */ stmts --sp, r0-lr mfsr r0, SYSREG_RAR_SUP mfsr r1, SYSREG_RSR_SUP#ifdef CONFIG_PREEMPT unmask_interrupts#endif zero_fp stm --sp, r0-r1 /* check for syscall tracing */ get_thread_info r0 ld.w r1, r0[TI_flags] bld r1, TIF_SYSCALL_TRACE brcs syscall_trace_entersyscall_trace_cont: cp.w r8, NR_syscalls brhs syscall_badsys lddpc lr, syscall_table_addr ld.w lr, lr[r8 << 2] mov r8, r5 /* 5th argument (6th is pushed by stub) */ icall lr .global syscall_returnsyscall_return: get_thread_info r0 mask_interrupts /* make sure we don't miss an interrupt setting need_resched or sigpending between sampling and the rets */ /* Store the return value so that the correct value is loaded below */ stdsp sp[REG_R12], r12 ld.w r1, r0[TI_flags] andl r1, _TIF_ALLWORK_MASK, COH brne syscall_exit_worksyscall_exit_cont: popm r8-r9 mtsr SYSREG_RAR_SUP, r8 mtsr SYSREG_RSR_SUP, r9 ldmts sp++, r0-lr sub sp, -4 /* r12_orig */ rets .align 2syscall_table_addr: .long sys_call_tablesyscall_badsys: mov r12, -ENOSYS rjmp syscall_return .global ret_from_forkret_from_fork: rcall schedule_tail /* check for syscall tracing */ get_thread_info r0 ld.w r1, r0[TI_flags] andl r1, _TIF_ALLWORK_MASK, COH brne syscall_exit_work rjmp syscall_exit_contsyscall_trace_enter: pushm r8-r12 rcall syscall_trace popm r8-r12 rjmp syscall_trace_contsyscall_exit_work: bld r1, TIF_SYSCALL_TRACE brcc 1f unmask_interrupts rcall syscall_trace mask_interrupts ld.w r1, r0[TI_flags]1: bld r1, TIF_NEED_RESCHED brcc 2f unmask_interrupts rcall schedule mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK tst r1, r2 breq 3f unmask_interrupts mov r12, sp mov r11, r0 rcall do_notify_resume mask_interrupts ld.w r1, r0[TI_flags] rjmp 1b3: bld r1, TIF_BREAKPOINT brcc syscall_exit_cont rjmp enter_monitor_mode /* The slow path of the TLB miss handler */page_table_not_present:page_not_present: tlbmiss_restore sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp rcall do_page_fault rjmp ret_from_exception /* This function expects to find offending PC in SYSREG_RAR_EX */ .type save_full_context_ex, @function .align 2save_full_context_ex: mfsr r11, SYSREG_RAR_EX sub r9, pc, . - debug_trampoline mfsr r8, SYSREG_RSR_EX cp.w r9, r11 breq 3f mov r12, r8 andh r8, (MODE_MASK >> 16), COH brne 2f1: pushm r11, r12 /* PC and SR */ unmask_exceptions ret r122: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR) stdsp sp[4], r10 /* replace saved SP */ rjmp 1b /* * The debug handler set up a trampoline to make us * automatically enter monitor mode upon return, but since * we're saving the full context, we must assume that the * exception handler might want to alter the return address * and/or status register. So we need to restore the original * context and enter monitor mode manually after the exception * has been handled. */3: get_thread_info r8 ld.w r11, r8[TI_rar_saved] ld.w r12, r8[TI_rsr_saved] rjmp 1b .size save_full_context_ex, . - save_full_context_ex /* Low-level exception handlers */handle_critical: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp rcall do_critical_exception /* We should never get here... */bad_return: sub r12, pc, (. - 1f) bral panic .align 21: .asciz "Return from critical exception!" .align 1do_bus_error_write: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mov r11, 1 rjmp 1fdo_bus_error_read: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mov r11, 01: mfsr r12, SYSREG_BEAR mov r10, sp rcall do_bus_error rjmp ret_from_exception .align 1do_nmi_ll: sub sp, 4 stmts --sp, r0-lr mfsr r9, SYSREG_RSR_NMI mfsr r8, SYSREG_RAR_NMI bfextu r0, r9, MODE_SHIFT, 3 brne 2f1: pushm r8, r9 /* PC and SR */ mfsr r12, SYSREG_ECR mov r11, sp rcall do_nmi popm r8-r9 mtsr SYSREG_RAR_NMI, r8 tst r0, r0 mtsr SYSREG_RSR_NMI, r9 brne 3f ldmts sp++, r0-lr sub sp, -4 /* skip r12_orig */ rete2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR) stdsp sp[4], r10 /* replace saved SP */ rjmp 1b3: popm lr sub sp, -4 /* skip sp */ popm r0-r12 sub sp, -4 /* skip r12_orig */ retehandle_address_fault: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp rcall do_address_exception rjmp ret_from_exceptionhandle_protection_fault: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp rcall do_page_fault rjmp ret_from_exception .align 1do_illegal_opcode_ll: sub sp, 4 stmts --sp, r0-lr rcall save_full_context_ex mfsr r12, SYSREG_ECR mov r11, sp rcall do_illegal_opcode rjmp ret_from_exception
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -