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
|
/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-10-02 Bernard The first version
* 2018-12-27 Jesven Add SMP schedule
* 2021-02-02 lizhirui Add userspace support
* 2021-12-24 JasonHu Add user setting save/restore
* 2022-10-22 Shell Support kernel mode RVV;
* Rewrite trap handling routine
* 2025-04-20 GuEe-GUI Support SMP
*/
#include <asm.h>
#include <csr.h>
.section ".text","ax"
.align 6
START_POINT(system_vectors)
#ifdef ARCH_RISCV_USING_IRQ_STACK
/*
* Keep the exception frame on the interrupted stack so the scheduler can
* store it in the thread TCB. Only C-level trap handling uses the IRQ
* stack. A zero xscratch means that a nested trap is already on it.
*/
csrrw sp, CSR_SCRATCH, sp
beqz sp, _irq_stack_nested
/* Recover the interrupted SP without losing the original t0 and t1. */
addi sp, sp, -(2 * SZREG)
REG_S t0, 0 * SZREG(sp)
REG_S t1, 1 * SZREG(sp)
mv t1, sp
csrr t0, CSR_SCRATCH
mv sp, t0
REG_L t0, 0 * SZREG(t1)
REG_L t1, 1 * SZREG(t1)
csrw CSR_SCRATCH, sp
SAVE_ALL
mv s0, sp
li s1, 1
call riscv_irq_stack_top
mv sp, a0
csrw CSR_SCRATCH, zero
j _context_saved
_irq_stack_nested:
csrr sp, CSR_SCRATCH
SAVE_ALL
mv s0, sp
mv s1, zero
csrw CSR_SCRATCH, zero
#else
/* Distingush exception from kernel or user */
csrrw sp, CSR_SCRATCH, sp
bnez sp, _save_context
/*
* BE REALLY careful with xscratch,
* if it's wrong, we could looping here forever
* or accessing random memory and seeing things totally
* messy after a long time and don't even know why
*/
_from_kernel:
csrr sp, CSR_SCRATCH
j _save_context
_save_context:
SAVE_ALL
/* Clear xscratch to say 'now in kernel mode' */
csrw CSR_SCRATCH, zero
#endif /* ARCH_RISCV_USING_IRQ_STACK */
_context_saved:
LOAD_GLOBAL_POINTER
/* Now we are ready to enter interrupt / excepiton handler */
#ifdef RT_USING_SMART
_distinguish_syscall:
csrr t0, CSR_CAUSE
li t1, EXC_SYSCALL
bne t0, t1, _handle_interrupt_and_exception
call syscall_entry
/* Syscall never return here */
#endif /* RT_USING_SMART */
_handle_interrupt_and_exception:
mv a0, sp
#ifdef ARCH_RISCV_USING_IRQ_STACK
mv a0, s0
#endif
call rt_hw_trap
_interrupt_exit:
#ifdef ARCH_RISCV_USING_IRQ_STACK
/* Restore the exception stack before invoking the scheduler. */
mv sp, s0
beqz s1, 1f
call riscv_irq_stack_top
csrw CSR_SCRATCH, a0
j 2f
1:
csrw CSR_SCRATCH, zero
2:
#endif
#ifdef RT_USING_SMP
mv a0, sp
call rt_scheduler_do_irq_switch
#else
la t0, rt_thread_switch_interrupt_flag
lw t1, 0(t0)
beqz t1, _resume_execution
sw zero, 0(t0)
_context_switch:
la t0, rt_interrupt_from_thread
REG_L a0, 0(t0)
la t0, rt_interrupt_to_thread
REG_L a1, 0(t0)
csrr t0, CSR_STATUS
andi t0, t0, ~SR_PIE
csrw CSR_STATUS, t0
jal rt_hw_context_switch
#endif /* RT_USING_SMP */
_resume_execution:
.globl rt_hw_resume_interrupt
rt_hw_resume_interrupt:
#ifdef RT_USING_SMART
REG_L t0, FRAME_OFF_XSTATUS(sp)
andi t0, t0, SR_PP
bnez t0, rt_hw_resume_kernel
call arch_ret_to_user
#endif /* RT_USING_SMART */
j rt_hw_resume_kernel
START_POINT_END(system_vectors)
.globl rt_hw_resume_kernel
rt_hw_resume_kernel:
RESTORE_ALL
#ifndef ARCH_RISCV_USING_IRQ_STACK
csrw CSR_SCRATCH, zero
#endif
XRET
.align 2
.weak fast_irq_vectors
START_POINT(fast_irq_vectors)
j system_vectors
START_POINT_END(fast_irq_vectors)
|