summaryrefslogtreecommitdiff
path: root/bsp/xuantie/libraries/xuantie_libraries/lib_cpu/context_gcc.S
blob: d577c975783f7e4ad6bb668279603071c0f90f70 (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
158
159
160
161
162
163
/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018/10/28     Bernard      The unify RISC-V porting implementation
 * 2018/12/27     Jesven       Add SMP support
 * 2021/02/02     lizhirui     Add userspace support
 */
#define __ASSEMBLY__
#include "cpuport.h"
#include "stackframe.h"

    .global rt_hw_context_switch_to
    .type   rt_hw_context_switch_to, %function
rt_hw_context_switch_to:
    LOAD sp, (a0)

#ifdef RT_USING_SMP
    mv    a0, a1
    call  rt_cpus_lock_status_restore
#endif
    RESTORE_ALL
    mret

    .size   rt_hw_context_switch_to, . - rt_hw_context_switch_to

#ifdef RT_USING_SMP
/*
 * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
 *
 * a0 --> from
 * a1 --> to
 * a2 --> to_thread
 */
    .global rt_hw_context_switch
    .type   rt_hw_context_switch, %function
rt_hw_context_switch:
    /* set mstatus.mpp */
    csrr t0, mxstatus
    srli t0, t0, 30
    andi t0, t0, 0x3
    slli t0, t0, 11
    csrs mstatus, t0//if enter here,caller must be in system thread
    csrw mepc, ra//return address
    //saved from thread context
    SAVE_ALL

    STORE sp, (a0)

    //restore to thread context
    LOAD sp, (a1)

    mv   a0, a2
    call  rt_cpus_lock_status_restore

    RESTORE_ALL
    mret

    .size   rt_hw_context_switch, . - rt_hw_context_switch

/*
 * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
 *
 * a0 --> context
 * a1 --> from
 * a2 --> to
 * a3 --> to_thread
 */
    .global rt_hw_context_switch_interrupt
    .type   rt_hw_context_switch_interrupt, %function
rt_hw_context_switch_interrupt:

    STORE a0, 0(a1)

    LOAD  sp, 0(a2)
    move  a0, a3
    call rt_cpus_lock_status_restore

    RESTORE_ALL
    mret

    .size   rt_hw_context_switch_interrupt, . - rt_hw_context_switch_interrupt
#else
/*
 * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
 *
 * a0 --> from
 * a1 --> to
 */
/*
 * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread);
 *
 * a0 --> from
 * a1 --> to
 * a2 --> from_thread
 * a3 --> to_thread
 */
    .global rt_hw_context_switch
    .type   rt_hw_context_switch, %function
    .global rt_hw_context_switch_interrupt
    .type   rt_hw_context_switch_interrupt, %function
rt_hw_context_switch:
rt_hw_context_switch_interrupt:
    /* set rt_thread_switch_interrupt_flag to 1 */
    la    t0, rt_thread_switch_interrupt_flag
    LOAD  t2, 0(t0)
    bnez  t2, _reswitch
    li    t1, 1
    STORE t1, 0(t0)

    /* set rt_interrupt_from_thread */
    la    t0, rt_interrupt_from_thread
    STORE a0, 0(t0)

_reswitch:
    /* set rt_interrupt_to_thread */
    la    t0, rt_interrupt_to_thread
    STORE a1, 0(t0)

#if CONFIG_INTC_CLIC || CONFIG_INTC_CLIC_PLIC
    /* trigger the tspend exception (causes context switch) */
    li    t0, 0xE080100C
    lb    t1, (t0)
    li    t2, 0x01
    or    t1, t1, t2
    sb    t1, (t0)

    fence
    nop
    nop
    nop
    nop
    nop

    ret
#else
    /* trigger the tspend exception (causes context switch) */
    li      t0, RISCV_VIC_TSPDR
    li      t2, 0x1
    sw      t2, 0(t0)

__loop:
    lw      t2, 0(t0)
    seqz    t1, t2
#if defined(CONFIG_RISCV_SMODE) && CONFIG_RISCV_SMODE
    csrr    t2, sip
    andi    t2, t2, 0x2
#else
    csrr    t2, mip
    andi    t2, t2, 0x8
#endif
    snez    t3, t2
    add     t2, t3, t1
    beqz    t2, __loop
    ret
#endif

    .size   rt_hw_context_switch, . - rt_hw_context_switch
    .size   rt_hw_context_switch_interrupt, . - rt_hw_context_switch_interrupt
#endif /* RT_USING_SMP */