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 * 2018/10/28     Bernard      The unify RISC-V porting implementation
9 * 2018/12/27     Jesven       Add SMP support
10 * 2021/02/02     lizhirui     Add userspace support
11 * 2022/10/22     Shell        Support User mode RVV;
12 *                             Trimming process switch context
13 */
14
15#include "cpuport.h"
16#include "stackframe.h"
17#define _REG_IDX(name) RT_HW_SWITCH_CONTEXT_##name
18#define REG_IDX(name) _REG_IDX(name)
19
20.macro SAVE_REG reg, index
21    STORE \reg, \index*REGBYTES(sp)
22.endm
23
24.macro LOAD_REG reg, index
25    LOAD \reg, \index*REGBYTES(sp)
26.endm
27
28.macro RESERVE_CONTEXT
29    addi        sp, sp, -(RT_HW_SWITCH_CONTEXT_SIZE * REGBYTES)
30    SAVE_REG    tp, REG_IDX(TP)
31    SAVE_REG    ra, REG_IDX(RA)
32    SAVE_REG    s0, REG_IDX(S0)
33    SAVE_REG    s1, REG_IDX(S1)
34    SAVE_REG    s2, REG_IDX(S2)
35    SAVE_REG    s3, REG_IDX(S3)
36    SAVE_REG    s4, REG_IDX(S4)
37    SAVE_REG    s5, REG_IDX(S5)
38    SAVE_REG    s6, REG_IDX(S6)
39    SAVE_REG    s7, REG_IDX(S7)
40    SAVE_REG    s8, REG_IDX(S8)
41    SAVE_REG    s9, REG_IDX(S9)
42    SAVE_REG    s10, REG_IDX(S10)
43    SAVE_REG    s11, REG_IDX(S11)
44    csrr        s11, sstatus
45    li          s10, (SSTATUS_SPP)
46    or          s11, s11, s10
47    SAVE_REG    s11, REG_IDX(SSTATUS)
48.endm
49
50.macro RESTORE_CONTEXT
51    LOAD_REG    s11, REG_IDX(SSTATUS)
52    csrw        sstatus, s11
53    LOAD_REG    s11, REG_IDX(S11)
54    LOAD_REG    s10, REG_IDX(S10)
55    LOAD_REG    s9, REG_IDX(S9)
56    LOAD_REG    s8, REG_IDX(S8)
57    LOAD_REG    s7, REG_IDX(S7)
58    LOAD_REG    s6, REG_IDX(S6)
59    LOAD_REG    s5, REG_IDX(S5)
60    LOAD_REG    s4, REG_IDX(S4)
61    LOAD_REG    s3, REG_IDX(S3)
62    LOAD_REG    s2, REG_IDX(S2)
63    LOAD_REG    s1, REG_IDX(S1)
64    LOAD_REG    s0, REG_IDX(S0)
65    LOAD_REG    ra, REG_IDX(RA)
66    LOAD_REG    tp, REG_IDX(TP)
67    addi        sp, sp, RT_HW_SWITCH_CONTEXT_SIZE * REGBYTES
68    csrw        sepc, ra
69.endm
70
71/*
72 * void rt_hw_context_switch_to(rt_ubase_t to);
73 *
74 * a0 --> to SP pointer
75 */
76.globl rt_hw_context_switch_to
77rt_hw_context_switch_to:
78    LOAD sp, (a0)
79
80    call rt_thread_self
81    mv s1, a0
82
83    #ifdef RT_USING_SMART
84        call lwp_aspace_switch
85    #endif
86
87    RESTORE_CONTEXT
88    sret
89
90/*
91 * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
92 *
93 * a0 --> from SP pointer
94 * a1 --> to SP pointer
95 *
96 * It should only be used on local interrupt disable
97 */
98.globl rt_hw_context_switch
99rt_hw_context_switch:
100    RESERVE_CONTEXT
101    STORE sp, (a0)
102
103    // restore to thread SP
104    LOAD sp, (a1)
105
106    // restore Address Space
107    call rt_thread_self
108    mv s1, a0
109
110    #ifdef RT_USING_SMART
111        call lwp_aspace_switch
112    #endif
113
114    RESTORE_CONTEXT
115    sret
116