linux/arch/nds32/kernel/ex-entry.S
Greentime Hu 2923f5ea77 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>
2018-02-22 10:44:31 +08:00

158 lines
3.3 KiB
ArmAsm

// 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: