xref: /linux/arch/loongarch/include/asm/stackframe.h (revision 9557b4376d02088a33e5f4116bcc324d35a3b64c)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4  */
5 #ifndef _ASM_STACKFRAME_H
6 #define _ASM_STACKFRAME_H
7 
8 #include <linux/threads.h>
9 
10 #include <asm/addrspace.h>
11 #include <asm/asm.h>
12 #include <asm/asmmacro.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/loongarch.h>
15 #include <asm/thread_info.h>
16 #include <asm/unwind_hints.h>
17 
18 /* Make the addition of cfi info a little easier. */
19 	.macro cfi_rel_offset reg offset=0 docfi=0
20 	.if \docfi
21 	.cfi_rel_offset \reg, \offset
22 	.endif
23 	.endm
24 
25 	.macro cfi_st reg offset=0 docfi=0
26 	cfi_rel_offset \reg, \offset, \docfi
27 	LONG_S	\reg, sp, \offset
28 	.endm
29 
30 	.macro cfi_restore reg offset=0 docfi=0
31 	.if \docfi
32 	.cfi_restore \reg
33 	.endif
34 	.endm
35 
36 	.macro cfi_ld reg offset=0 docfi=0
37 	LONG_L	\reg, sp, \offset
38 	cfi_restore \reg \offset \docfi
39 	.endm
40 
41 	.macro SETUP_DMWINS temp
42 	li.d	\temp, CSR_DMW0_INIT	# WUC, PLV0, 0x8000 xxxx xxxx xxxx
43 	csrwr	\temp, LOONGARCH_CSR_DMWIN0
44 	li.d	\temp, CSR_DMW1_INIT	# CAC, PLV0, 0x9000 xxxx xxxx xxxx
45 	csrwr	\temp, LOONGARCH_CSR_DMWIN1
46 	li.d	\temp, CSR_DMW2_INIT	# WUC, PLV0, 0xa000 xxxx xxxx xxxx
47 	csrwr	\temp, LOONGARCH_CSR_DMWIN2
48 	li.d	\temp, CSR_DMW3_INIT	# 0x0, unused
49 	csrwr	\temp, LOONGARCH_CSR_DMWIN3
50 	.endm
51 
52 /* Jump to the runtime virtual address. */
53 	.macro JUMP_VIRT_ADDR temp1 temp2
54 	li.d	\temp1, CACHE_BASE
55 	pcaddi	\temp2, 0
56 	bstrins.d  \temp1, \temp2, (DMW_PABITS - 1), 0
57 	jirl	zero, \temp1, 0xc
58 	.endm
59 
60 	.macro BACKUP_T0T1
61 	csrwr	t0, EXCEPTION_KS0
62 	csrwr	t1, EXCEPTION_KS1
63 	.endm
64 
65 	.macro RELOAD_T0T1
66 	csrrd   t0, EXCEPTION_KS0
67 	csrrd   t1, EXCEPTION_KS1
68 	.endm
69 
70 	.macro	SAVE_TEMP docfi=0
71 	RELOAD_T0T1
72 	cfi_st	t0, PT_R12, \docfi
73 	cfi_st	t1, PT_R13, \docfi
74 	cfi_st	t2, PT_R14, \docfi
75 	cfi_st	t3, PT_R15, \docfi
76 	cfi_st	t4, PT_R16, \docfi
77 	cfi_st	t5, PT_R17, \docfi
78 	cfi_st	t6, PT_R18, \docfi
79 	cfi_st	t7, PT_R19, \docfi
80 	cfi_st	t8, PT_R20, \docfi
81 	.endm
82 
83 	.macro	SAVE_STATIC docfi=0
84 	cfi_st	s0, PT_R23, \docfi
85 	cfi_st	s1, PT_R24, \docfi
86 	cfi_st	s2, PT_R25, \docfi
87 	cfi_st	s3, PT_R26, \docfi
88 	cfi_st	s4, PT_R27, \docfi
89 	cfi_st	s5, PT_R28, \docfi
90 	cfi_st	s6, PT_R29, \docfi
91 	cfi_st	s7, PT_R30, \docfi
92 	cfi_st	s8, PT_R31, \docfi
93 	.endm
94 
95 /*
96  * get_saved_sp returns the SP for the current CPU by looking in the
97  * kernelsp array for it. It stores the current sp in t0 and loads the
98  * new value in sp.
99  */
100 	.macro	get_saved_sp docfi=0
101 	la_abs	  t1, kernelsp
102 #ifdef CONFIG_SMP
103 	csrrd	  t0, PERCPU_BASE_KS
104 	LONG_ADD  t1, t1, t0
105 #endif
106 	move	  t0, sp
107 	.if \docfi
108 	.cfi_register sp, t0
109 	.endif
110 	LONG_L	  sp, t1, 0
111 	.endm
112 
113 	.macro	set_saved_sp stackp temp temp2
114 	la.pcrel  \temp, kernelsp
115 #ifdef CONFIG_SMP
116 	LONG_ADD  \temp, \temp, u0
117 #endif
118 	LONG_S	  \stackp, \temp, 0
119 	.endm
120 
121 	.macro	SAVE_SOME docfi=0
122 	csrrd	t1, LOONGARCH_CSR_PRMD
123 	andi	t1, t1, 0x3	/* extract pplv bit */
124 	move	t0, sp
125 	beqz	t1, 8f
126 	/* Called from user mode, new stack. */
127 	get_saved_sp docfi=\docfi
128 8:
129 	PTR_ADDI sp, sp, -PT_SIZE
130 	.if \docfi
131 	.cfi_def_cfa sp, 0
132 	.endif
133 	cfi_st	t0, PT_R3, \docfi
134 	cfi_rel_offset  sp, PT_R3, \docfi
135 	LONG_S	zero, sp, PT_R0
136 	csrrd	t0, LOONGARCH_CSR_PRMD
137 	LONG_S	t0, sp, PT_PRMD
138 	csrrd	t0, LOONGARCH_CSR_CRMD
139 	LONG_S	t0, sp, PT_CRMD
140 	csrrd	t0, LOONGARCH_CSR_EUEN
141 	LONG_S  t0, sp, PT_EUEN
142 	csrrd	t0, LOONGARCH_CSR_ECFG
143 	LONG_S	t0, sp, PT_ECFG
144 	csrrd	t0, LOONGARCH_CSR_ESTAT
145 	PTR_S	t0, sp, PT_ESTAT
146 	cfi_st	ra, PT_R1, \docfi
147 	cfi_st	a0, PT_R4, \docfi
148 	cfi_st	a1, PT_R5, \docfi
149 	cfi_st	a2, PT_R6, \docfi
150 	cfi_st	a3, PT_R7, \docfi
151 	cfi_st	a4, PT_R8, \docfi
152 	cfi_st	a5, PT_R9, \docfi
153 	cfi_st	a6, PT_R10, \docfi
154 	cfi_st	a7, PT_R11, \docfi
155 	csrrd	ra, LOONGARCH_CSR_ERA
156 	LONG_S	ra, sp, PT_ERA
157 	.if \docfi
158 	.cfi_rel_offset ra, PT_ERA
159 	.endif
160 	cfi_st	tp, PT_R2, \docfi
161 	cfi_st	fp, PT_R22, \docfi
162 
163 	/* Set thread_info if we're coming from user mode */
164 	csrrd	t0, LOONGARCH_CSR_PRMD
165 	andi	t0, t0, 0x3	/* extract pplv bit */
166 	beqz	t0, 9f
167 
168 	li.d	tp, ~_THREAD_MASK
169 	and	tp, tp, sp
170 	cfi_st  u0, PT_R21, \docfi
171 	csrrd	u0, PERCPU_BASE_KS
172 9:
173 #ifdef CONFIG_KGDB
174 	li.w	t0, CSR_CRMD_WE
175 	csrxchg	t0, t0, LOONGARCH_CSR_CRMD
176 #endif
177 	UNWIND_HINT_REGS
178 	.endm
179 
180 	.macro	SAVE_ALL docfi=0
181 	SAVE_SOME \docfi
182 	SAVE_TEMP \docfi
183 	SAVE_STATIC \docfi
184 	.endm
185 
186 	.macro	RESTORE_TEMP docfi=0
187 	cfi_ld	t0, PT_R12, \docfi
188 	cfi_ld	t1, PT_R13, \docfi
189 	cfi_ld	t2, PT_R14, \docfi
190 	cfi_ld	t3, PT_R15, \docfi
191 	cfi_ld	t4, PT_R16, \docfi
192 	cfi_ld	t5, PT_R17, \docfi
193 	cfi_ld	t6, PT_R18, \docfi
194 	cfi_ld	t7, PT_R19, \docfi
195 	cfi_ld	t8, PT_R20, \docfi
196 	.endm
197 
198 	.macro	RESTORE_STATIC docfi=0
199 	cfi_ld	s0, PT_R23, \docfi
200 	cfi_ld	s1, PT_R24, \docfi
201 	cfi_ld	s2, PT_R25, \docfi
202 	cfi_ld	s3, PT_R26, \docfi
203 	cfi_ld	s4, PT_R27, \docfi
204 	cfi_ld	s5, PT_R28, \docfi
205 	cfi_ld	s6, PT_R29, \docfi
206 	cfi_ld	s7, PT_R30, \docfi
207 	cfi_ld	s8, PT_R31, \docfi
208 	.endm
209 
210 	.macro	RESTORE_SOME docfi=0
211 	LONG_L	a0, sp, PT_PRMD
212 	andi    a0, a0, 0x3	/* extract pplv bit */
213 	beqz    a0, 8f
214 	cfi_ld  u0, PT_R21, \docfi
215 8:
216 	LONG_L	a0, sp, PT_ERA
217 	csrwr	a0, LOONGARCH_CSR_ERA
218 	LONG_L	a0, sp, PT_PRMD
219 	csrwr	a0, LOONGARCH_CSR_PRMD
220 	cfi_ld	ra, PT_R1, \docfi
221 	cfi_ld	a0, PT_R4, \docfi
222 	cfi_ld	a1, PT_R5, \docfi
223 	cfi_ld	a2, PT_R6, \docfi
224 	cfi_ld	a3, PT_R7, \docfi
225 	cfi_ld	a4, PT_R8, \docfi
226 	cfi_ld	a5, PT_R9, \docfi
227 	cfi_ld	a6, PT_R10, \docfi
228 	cfi_ld	a7, PT_R11, \docfi
229 	cfi_ld	tp, PT_R2, \docfi
230 	cfi_ld	fp, PT_R22, \docfi
231 	.endm
232 
233 	.macro	RESTORE_SP_AND_RET docfi=0
234 	cfi_ld	sp, PT_R3, \docfi
235 	UNWIND_HINT_FUNC
236 	ertn
237 	.endm
238 
239 	.macro	RESTORE_ALL_AND_RET docfi=0
240 	RESTORE_STATIC \docfi
241 	RESTORE_TEMP \docfi
242 	RESTORE_SOME \docfi
243 	RESTORE_SP_AND_RET \docfi
244 	.endm
245 
246 #endif /* _ASM_STACKFRAME_H */
247