summaryrefslogtreecommitdiff
path: root/arch/nds32/kernel/ex-entry.S
blob: 21a144071566989af1daa55400a0c9fab98b34ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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     __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: