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