1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2021-02-02     lizhirui     first version
9  * 2021-02-11     lizhirui     fixed gp save/store bug
10  * 2021-11-18     JasonHu      add fpu registers save/restore
11  * 2022-10-22     Shell        Support kernel mode RVV
12  */
13 
14 #ifndef __STACKFRAME_H__
15 #define __STACKFRAME_H__
16 
17 #include <rtconfig.h>
18 #include "encoding.h"
19 
20 /* bytes of register width */
21 #ifdef ARCH_CPU_64BIT
22 #define STORE                   sd
23 #define LOAD                    ld
24 #define FSTORE                  fsd
25 #define FLOAD                   fld
26 #define REGBYTES                8
27 #else
28 // error here, not portable
29 #error "Not supported XLEN"
30 #endif
31 
32 #include "ext_context.h"
33 
34 /* 33 general register + 1 padding */
35 #define CTX_GENERAL_REG_NR  34
36 
37 /* all context registers */
38 #define CTX_REG_NR  (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR + CTX_VECTOR_REG_NR)
39 
40 #define BYTES(idx)          ((idx) * REGBYTES)
41 #define FRAME_OFF_SSTATUS   BYTES(2)
42 #define FRAME_OFF_SP        BYTES(32)
43 #define FRAME_OFF_GP        BYTES(3)
44 #define FRAME_OFF_TP        BYTES(4)
45 
46 /* switch frame */
47 #define RT_HW_SWITCH_CONTEXT_SSTATUS    0
48 #define RT_HW_SWITCH_CONTEXT_S11        1
49 #define RT_HW_SWITCH_CONTEXT_S10        2
50 #define RT_HW_SWITCH_CONTEXT_S9         3
51 #define RT_HW_SWITCH_CONTEXT_S8         4
52 #define RT_HW_SWITCH_CONTEXT_S7         5
53 #define RT_HW_SWITCH_CONTEXT_S6         6
54 #define RT_HW_SWITCH_CONTEXT_S5         7
55 #define RT_HW_SWITCH_CONTEXT_S4         8
56 #define RT_HW_SWITCH_CONTEXT_S3         9
57 #define RT_HW_SWITCH_CONTEXT_S2         10
58 #define RT_HW_SWITCH_CONTEXT_S1         11
59 #define RT_HW_SWITCH_CONTEXT_S0         12
60 #define RT_HW_SWITCH_CONTEXT_RA         13
61 #define RT_HW_SWITCH_CONTEXT_TP         14
62 #define RT_HW_SWITCH_CONTEXT_ALIGNMENT  15  // Padding for alignment
63 #define RT_HW_SWITCH_CONTEXT_SIZE       16  // Total size of the structure
64 
65 #ifdef __ASSEMBLY__
66 
67 .macro SAVE_ALL
68 
69 #ifdef ARCH_RISCV_FPU
70     /* reserve float registers */
71     addi sp, sp, -CTX_FPU_REG_NR * REGBYTES
72 #endif /* ARCH_RISCV_FPU */
73 #ifdef ARCH_RISCV_VECTOR
74     /* reserve float registers */
75     addi sp, sp, -CTX_VECTOR_REG_NR * REGBYTES
76 #endif /* ARCH_RISCV_VECTOR */
77 
78     /* save general registers */
79     addi sp, sp, -CTX_GENERAL_REG_NR * REGBYTES
80     STORE x1,   1 * REGBYTES(sp)
81 
82     csrr  x1, sstatus
83     STORE x1, FRAME_OFF_SSTATUS(sp)
84 
85     csrr  x1, sepc
86     STORE x1,   0 * REGBYTES(sp)
87 
88     STORE x3,   3 * REGBYTES(sp)
89     STORE x4,   4 * REGBYTES(sp) /* save tp */
90     STORE x5,   5 * REGBYTES(sp)
91     STORE x6,   6 * REGBYTES(sp)
92     STORE x7,   7 * REGBYTES(sp)
93     STORE x8,   8 * REGBYTES(sp)
94     STORE x9,   9 * REGBYTES(sp)
95     STORE x10, 10 * REGBYTES(sp)
96     STORE x11, 11 * REGBYTES(sp)
97     STORE x12, 12 * REGBYTES(sp)
98     STORE x13, 13 * REGBYTES(sp)
99     STORE x14, 14 * REGBYTES(sp)
100     STORE x15, 15 * REGBYTES(sp)
101     STORE x16, 16 * REGBYTES(sp)
102     STORE x17, 17 * REGBYTES(sp)
103     STORE x18, 18 * REGBYTES(sp)
104     STORE x19, 19 * REGBYTES(sp)
105     STORE x20, 20 * REGBYTES(sp)
106     STORE x21, 21 * REGBYTES(sp)
107     STORE x22, 22 * REGBYTES(sp)
108     STORE x23, 23 * REGBYTES(sp)
109     STORE x24, 24 * REGBYTES(sp)
110     STORE x25, 25 * REGBYTES(sp)
111     STORE x26, 26 * REGBYTES(sp)
112     STORE x27, 27 * REGBYTES(sp)
113     STORE x28, 28 * REGBYTES(sp)
114     STORE x29, 29 * REGBYTES(sp)
115     STORE x30, 30 * REGBYTES(sp)
116     STORE x31, 31 * REGBYTES(sp)
117     csrr t0, sscratch
118     STORE t0, 32 * REGBYTES(sp)
119 
120 #ifdef ARCH_RISCV_FPU
121     /* backup sp and adjust sp to save float registers */
122     mv t1, sp
123     addi t1, t1, CTX_GENERAL_REG_NR * REGBYTES
124 
125     li  t0, SSTATUS_FS
126     csrs sstatus, t0
127     FSTORE f0,  FPU_CTX_F0_OFF(t1)
128     FSTORE f1,  FPU_CTX_F1_OFF(t1)
129     FSTORE f2,  FPU_CTX_F2_OFF(t1)
130     FSTORE f3,  FPU_CTX_F3_OFF(t1)
131     FSTORE f4,  FPU_CTX_F4_OFF(t1)
132     FSTORE f5,  FPU_CTX_F5_OFF(t1)
133     FSTORE f6,  FPU_CTX_F6_OFF(t1)
134     FSTORE f7,  FPU_CTX_F7_OFF(t1)
135     FSTORE f8,  FPU_CTX_F8_OFF(t1)
136     FSTORE f9,  FPU_CTX_F9_OFF(t1)
137     FSTORE f10, FPU_CTX_F10_OFF(t1)
138     FSTORE f11, FPU_CTX_F11_OFF(t1)
139     FSTORE f12, FPU_CTX_F12_OFF(t1)
140     FSTORE f13, FPU_CTX_F13_OFF(t1)
141     FSTORE f14, FPU_CTX_F14_OFF(t1)
142     FSTORE f15, FPU_CTX_F15_OFF(t1)
143     FSTORE f16, FPU_CTX_F16_OFF(t1)
144     FSTORE f17, FPU_CTX_F17_OFF(t1)
145     FSTORE f18, FPU_CTX_F18_OFF(t1)
146     FSTORE f19, FPU_CTX_F19_OFF(t1)
147     FSTORE f20, FPU_CTX_F20_OFF(t1)
148     FSTORE f21, FPU_CTX_F21_OFF(t1)
149     FSTORE f22, FPU_CTX_F22_OFF(t1)
150     FSTORE f23, FPU_CTX_F23_OFF(t1)
151     FSTORE f24, FPU_CTX_F24_OFF(t1)
152     FSTORE f25, FPU_CTX_F25_OFF(t1)
153     FSTORE f26, FPU_CTX_F26_OFF(t1)
154     FSTORE f27, FPU_CTX_F27_OFF(t1)
155     FSTORE f28, FPU_CTX_F28_OFF(t1)
156     FSTORE f29, FPU_CTX_F29_OFF(t1)
157     FSTORE f30, FPU_CTX_F30_OFF(t1)
158     FSTORE f31, FPU_CTX_F31_OFF(t1)
159 
160     /* clr FS domain */
161     csrc sstatus, t0
162 
163     /* clean status would clr sr_sd; */
164     li t0, SSTATUS_FS_CLEAN
165     csrs sstatus, t0
166 
167 #endif /* ARCH_RISCV_FPU */
168 
169 #ifdef ARCH_RISCV_VECTOR
170     csrr    t0, sstatus
171     andi    t0, t0, SSTATUS_VS
172     beqz    t0, 0f
173 
174     /* push vector frame */
175     addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * REGBYTES
176 
177     SAVE_VECTOR t1
178 0:
179 #endif /* ARCH_RISCV_VECTOR */
180 .endm
181 
182 /**
183  * @brief Restore All General Registers, for interrupt handling
184  *
185  */
186 .macro RESTORE_ALL
187 
188 #ifdef ARCH_RISCV_VECTOR
189     // skip on close
190     ld      t0, 2 * REGBYTES(sp)
191     // cannot use vector on initial
192     andi    t0, t0, SSTATUS_VS_CLEAN
193     beqz    t0, 0f
194 
195     /* push vector frame */
196     addi t1, sp, (CTX_GENERAL_REG_NR + CTX_FPU_REG_NR) * REGBYTES
197 
198     RESTORE_VECTOR t1
199 0:
200 #endif /* ARCH_RISCV_VECTOR */
201 
202 #ifdef ARCH_RISCV_FPU
203     /* restore float register  */
204     addi t2, sp, CTX_GENERAL_REG_NR * REGBYTES
205 
206     li  t0, SSTATUS_FS
207     csrs sstatus, t0
208     FLOAD f0,  FPU_CTX_F0_OFF(t2)
209     FLOAD f1,  FPU_CTX_F1_OFF(t2)
210     FLOAD f2,  FPU_CTX_F2_OFF(t2)
211     FLOAD f3,  FPU_CTX_F3_OFF(t2)
212     FLOAD f4,  FPU_CTX_F4_OFF(t2)
213     FLOAD f5,  FPU_CTX_F5_OFF(t2)
214     FLOAD f6,  FPU_CTX_F6_OFF(t2)
215     FLOAD f7,  FPU_CTX_F7_OFF(t2)
216     FLOAD f8,  FPU_CTX_F8_OFF(t2)
217     FLOAD f9,  FPU_CTX_F9_OFF(t2)
218     FLOAD f10, FPU_CTX_F10_OFF(t2)
219     FLOAD f11, FPU_CTX_F11_OFF(t2)
220     FLOAD f12, FPU_CTX_F12_OFF(t2)
221     FLOAD f13, FPU_CTX_F13_OFF(t2)
222     FLOAD f14, FPU_CTX_F14_OFF(t2)
223     FLOAD f15, FPU_CTX_F15_OFF(t2)
224     FLOAD f16, FPU_CTX_F16_OFF(t2)
225     FLOAD f17, FPU_CTX_F17_OFF(t2)
226     FLOAD f18, FPU_CTX_F18_OFF(t2)
227     FLOAD f19, FPU_CTX_F19_OFF(t2)
228     FLOAD f20, FPU_CTX_F20_OFF(t2)
229     FLOAD f21, FPU_CTX_F21_OFF(t2)
230     FLOAD f22, FPU_CTX_F22_OFF(t2)
231     FLOAD f23, FPU_CTX_F23_OFF(t2)
232     FLOAD f24, FPU_CTX_F24_OFF(t2)
233     FLOAD f25, FPU_CTX_F25_OFF(t2)
234     FLOAD f26, FPU_CTX_F26_OFF(t2)
235     FLOAD f27, FPU_CTX_F27_OFF(t2)
236     FLOAD f28, FPU_CTX_F28_OFF(t2)
237     FLOAD f29, FPU_CTX_F29_OFF(t2)
238     FLOAD f30, FPU_CTX_F30_OFF(t2)
239     FLOAD f31, FPU_CTX_F31_OFF(t2)
240 
241     /* clr FS domain */
242     csrc sstatus, t0
243 
244     /* clean status would clr sr_sd; */
245     li t0, SSTATUS_FS_CLEAN
246     csrs sstatus, t0
247 
248 #endif /* ARCH_RISCV_FPU */
249 
250     /* restore general register */
251     addi t0, sp, CTX_REG_NR * REGBYTES
252     csrw sscratch, t0
253 
254     /* resw ra to sepc */
255     LOAD x1, 0 * REGBYTES(sp)
256     csrw sepc, x1
257 
258     LOAD x1,   2 * REGBYTES(sp)
259     csrw sstatus, x1
260 
261     LOAD x1,   1 * REGBYTES(sp)
262 
263     LOAD x3,   3 * REGBYTES(sp)
264     LOAD x4,   4 * REGBYTES(sp) /* restore tp */
265     LOAD x5,   5 * REGBYTES(sp)
266     LOAD x6,   6 * REGBYTES(sp)
267     LOAD x7,   7 * REGBYTES(sp)
268     LOAD x8,   8 * REGBYTES(sp)
269     LOAD x9,   9 * REGBYTES(sp)
270     LOAD x10, 10 * REGBYTES(sp)
271     LOAD x11, 11 * REGBYTES(sp)
272     LOAD x12, 12 * REGBYTES(sp)
273     LOAD x13, 13 * REGBYTES(sp)
274     LOAD x14, 14 * REGBYTES(sp)
275     LOAD x15, 15 * REGBYTES(sp)
276     LOAD x16, 16 * REGBYTES(sp)
277     LOAD x17, 17 * REGBYTES(sp)
278     LOAD x18, 18 * REGBYTES(sp)
279     LOAD x19, 19 * REGBYTES(sp)
280     LOAD x20, 20 * REGBYTES(sp)
281     LOAD x21, 21 * REGBYTES(sp)
282     LOAD x22, 22 * REGBYTES(sp)
283     LOAD x23, 23 * REGBYTES(sp)
284     LOAD x24, 24 * REGBYTES(sp)
285     LOAD x25, 25 * REGBYTES(sp)
286     LOAD x26, 26 * REGBYTES(sp)
287     LOAD x27, 27 * REGBYTES(sp)
288     LOAD x28, 28 * REGBYTES(sp)
289     LOAD x29, 29 * REGBYTES(sp)
290     LOAD x30, 30 * REGBYTES(sp)
291     LOAD x31, 31 * REGBYTES(sp)
292 
293     /* restore user sp */
294     LOAD sp, 32 * REGBYTES(sp)
295 .endm
296 
297 .macro RESTORE_SYS_GP
298     .option push
299     .option norelax
300         la gp, __global_pointer$
301     .option pop
302 .endm
303 
304 .macro OPEN_INTERRUPT
305     csrsi sstatus, 2
306 .endm
307 
308 .macro CLOSE_INTERRUPT
309     csrci sstatus, 2
310 .endm
311 
312 #endif /* __ASSEMBLY__ */
313 
314 #endif /* __STACKFRAME_H__ */
315