158 lines
3.3 KiB
ArmAsm
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 __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:
|