diff options
author | Greentime Hu <greentime@andestech.com> | 2017-10-24 14:42:02 +0800 |
---|---|---|
committer | Greentime Hu <greentime@andestech.com> | 2018-02-22 10:44:31 +0800 |
commit | 2923f5ea7738cb9f5372bb9d7ac9886cf4193003 (patch) | |
tree | ee1811a5903a7cc76253c6fdb0161e150cfe80c9 /arch/nds32/kernel/ex-entry.S | |
parent | 001d953ede35dfb135e636af4b41d5dd20a09471 (diff) |
nds32: Exception handling
This patch includes the exception/interrupt entries, pt_reg structure and
related accessors.
/* Unaligned accessing handling*/
Andes processors cannot load/store information which is not naturally
aligned on the bus, i.e., loading a 4 byte data whose start address must
be divisible by 4. If unaligned data accessing is happened, data
unaligned exception will be triggered and user will get SIGSEGV or
kernel oops according to the unaligned address. In order to make user be
able to load/store data from an unaligned address, software load/store
emulation is implemented in arch/nds32/mm/alignment.c to address data
unaligned exception.
Unaligned accessing handling is disabled by default because it is not a
normal case. User can enable this feature by following steps.
A. Compile time:
1. Enable kernel config CONFIG_ALIGNMENT_TRAP
B. Run time:
1. Enter /proc/sys/nds32/unaligned_acess folder
2. Write 1 to file enable_mode to enable unaligned accessing
handling. User can disable it by writing 0 to this file.
3. Write 1 to file debug to show which unaligned address is under
processing. User can disable it by writing 0 to this file.
However, unaligned accessing handler cannot work if this unaligned
address is not accessible such as protection violation. On this
condition, the default behaviors for addressing data unaligned exception
still happen
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/nds32/kernel/ex-entry.S')
-rw-r--r-- | arch/nds32/kernel/ex-entry.S | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/arch/nds32/kernel/ex-entry.S b/arch/nds32/kernel/ex-entry.S new file mode 100644 index 000000000000..a72e83d804f5 --- /dev/null +++ b/arch/nds32/kernel/ex-entry.S @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include <linux/linkage.h> +#include <asm/memory.h> +#include <asm/nds32.h> +#include <asm/errno.h> +#include <asm/asm-offsets.h> +#include <asm/page.h> + +#ifdef CONFIG_HWZOL + .macro push_zol + mfusr $r14, $LB + mfusr $r15, $LE + mfusr $r16, $LC + .endm +#endif + + .macro save_user_regs + + smw.adm $sp, [$sp], $sp, #0x1 + /* move $SP to the bottom of pt_regs */ + addi $sp, $sp, -OSP_OFFSET + + /* push $r0 ~ $r25 */ + smw.bim $r0, [$sp], $r25 + /* push $fp, $gp, $lp */ + smw.bim $sp, [$sp], $sp, #0xe + + mfsr $r12, $SP_USR + mfsr $r13, $IPC +#ifdef CONFIG_HWZOL + push_zol +#endif + movi $r17, -1 + move $r18, $r0 + mfsr $r19, $PSW + mfsr $r20, $IPSW + mfsr $r21, $P_IPSW + mfsr $r22, $P_IPC + mfsr $r23, $P_P0 + mfsr $r24, $P_P1 + smw.bim $r12, [$sp], $r24, #0 + addi $sp, $sp, -FUCOP_CTL_OFFSET + + /* Initialize kernel space $fp */ + andi $p0, $r20, #PSW_mskPOM + movi $p1, #0x0 + cmovz $fp, $p1, $p0 + + andi $r16, $r19, #PSW_mskINTL + slti $r17, $r16, #4 + bnez $r17, 1f + addi $r17, $r19, #-2 + mtsr $r17, $PSW + isb +1: + /* If it was superuser mode, we don't need to update $r25 */ + bnez $p0, 2f + la $p0, __entry_task + lw $r25, [$p0] +2: + .endm + + .text + +/* + * Exception Vector + */ +exception_handlers: + .long unhandled_exceptions !Reset/NMI + .long unhandled_exceptions !TLB fill + .long do_page_fault !PTE not present + .long do_dispatch_tlb_misc !TLB misc + .long unhandled_exceptions !TLB VLPT + .long unhandled_exceptions !Machine Error + .long do_debug_trap !Debug related + .long do_dispatch_general !General exception + .long eh_syscall !Syscall + .long asm_do_IRQ !IRQ + +common_exception_handler: + save_user_regs + mfsr $p0, $ITYPE + andi $p0, $p0, #ITYPE_mskVECTOR + srli $p0, $p0, #ITYPE_offVECTOR + andi $p1, $p0, #NDS32_VECTOR_mskNONEXCEPTION + bnez $p1, 1f + sethi $lp, hi20(ret_from_exception) + ori $lp, $lp, lo12(ret_from_exception) + sethi $p1, hi20(exception_handlers) + ori $p1, $p1, lo12(exception_handlers) + lw $p1, [$p1+$p0<<2] + move $r0, $p0 + mfsr $r1, $EVA + mfsr $r2, $ITYPE + move $r3, $sp + mfsr $r4, $OIPC + /* enable gie if it is enabled in IPSW. */ + mfsr $r21, $PSW + andi $r20, $r20, #PSW_mskGIE /* r20 is $IPSW*/ + or $r21, $r21, $r20 + mtsr $r21, $PSW + dsb + jr $p1 + + /* syscall */ +1: + addi $p1, $p0, #-NDS32_VECTOR_offEXCEPTION + bnez $p1, 2f + sethi $lp, hi20(ret_from_exception) + ori $lp, $lp, lo12(ret_from_exception) + sethi $p1, hi20(exception_handlers) + ori $p1, $p1, lo12(exception_handlers) + lwi $p1, [$p1+#NDS32_VECTOR_offEXCEPTION<<2] + jr $p1 + + /* interrupt */ +2: +#ifdef CONFIG_TRACE_IRQFLAGS + jal arch_trace_hardirqs_off +#endif + move $r0, $sp + sethi $lp, hi20(ret_from_intr) + ori $lp, $lp, lo12(ret_from_intr) + sethi $p0, hi20(exception_handlers) + ori $p0, $p0, lo12(exception_handlers) + lwi $p0, [$p0+#NDS32_VECTOR_offINTERRUPT<<2] + jr $p0 + + .macro EXCEPTION_VECTOR_DEBUG + .align 4 + mfsr $p0, $EDM_CTL + andi $p0, $p0, EDM_CTL_mskV3_EDM_MODE + tnez $p0, SWID_RAISE_INTERRUPT_LEVEL + .endm + + .macro EXCEPTION_VECTOR + .align 4 + sethi $p0, hi20(common_exception_handler) + ori $p0, $p0, lo12(common_exception_handler) + jral.ton $p0, $p0 + .endm + + .section ".text.init", #alloc, #execinstr + .global exception_vector +exception_vector: +.rept 6 + EXCEPTION_VECTOR +.endr + EXCEPTION_VECTOR_DEBUG +.rept 121 + EXCEPTION_VECTOR +.endr + .align 4 + .global exception_vector_end +exception_vector_end: |