MOS Source Code
Loading...
Searching...
No Matches
riscv64_platform_api.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/assert.h"
6#include "mos/tasks/signal.h"
8
9#include <mos/platform_syscall.h>
10#include <mos_stdlib.h>
11
12// Platform Context Switching APIs
13typedef void (*switch_func_t)();
14extern void riscv64_do_context_switch(ptr_t *old_stack, ptr_t new_stack, switch_func_t switcher, bool *lock);
15
22
24{
26 const thread_entry_t entry = (thread_entry_t) regs->sepc;
27 void *const arg = (void *) regs->a0;
28 entry(arg);
30}
31
33
35{
36 (*(volatile u32 *) pa_va(0x100000)) = 0x5555;
37 while (1)
39}
40
42{
43 return 0;
44}
45
47{
48 __asm__ volatile("wfi");
49}
50
52{
53 pr_info("General Purpose Registers:");
54 pr_info2(" ra/x1: " PTR_FMT " sp/x2: " PTR_FMT " gp/x3: " PTR_FMT " tp/x4: " PTR_FMT, regs->ra, regs->sp, regs->gp, regs->tp);
55 pr_info2(" t0/x5: " PTR_FMT " t1/x6: " PTR_FMT " t2/x7: " PTR_FMT " fp/x8: " PTR_FMT, regs->t0, regs->t1, regs->t2, regs->fp);
56 pr_info2(" s1/x9: " PTR_FMT " a0/x10: " PTR_FMT " a1/x11: " PTR_FMT " a2/x12: " PTR_FMT, regs->s1, regs->a0, regs->a1, regs->a2);
57 pr_info2(" a3/x13: " PTR_FMT " a4/x14: " PTR_FMT " a5/x15: " PTR_FMT " a6/x16: " PTR_FMT, regs->a3, regs->a4, regs->a5, regs->a6);
58 pr_info2(" a7/x17: " PTR_FMT " s2/x18: " PTR_FMT " s3/x19: " PTR_FMT " s4/x20: " PTR_FMT, regs->a7, regs->s2, regs->s3, regs->s4);
59 pr_info2(" s5/x21: " PTR_FMT " s6/x22: " PTR_FMT " s7/x23: " PTR_FMT " s8/x24: " PTR_FMT, regs->s5, regs->s6, regs->s7, regs->s8);
60 pr_info2(" s9/x25: " PTR_FMT " s10/x26: " PTR_FMT " s11/x27: " PTR_FMT " t3/x28: " PTR_FMT, regs->s9, regs->s10, regs->s11, regs->t3);
61 pr_info2(" t4/x29: " PTR_FMT " t5/x30: " PTR_FMT " t6/x31: " PTR_FMT, regs->t4, regs->t5, regs->t6);
62}
63
65{
66 return (platform_regs_t *) (thread->k_stack.top - sizeof(platform_regs_t));
67}
68
69static void thread_setup_common(thread_t *thread)
70{
71 thread->k_stack.head = thread->k_stack.top - sizeof(platform_regs_t);
72}
73
74// Platform Thread / Process APIs
76{
77 thread_setup_common(thread);
79 regs->sepc = entry;
80 regs->a0 = argc;
81 regs->a1 = argv;
82 regs->a2 = envp;
83 regs->sp = sp;
84}
85
87{
88 thread_setup_common(thread);
90 regs->a0 = (ptr_t) arg;
91 regs->sepc = (ptr_t) entry;
92
93 if (thread->mode == THREAD_MODE_KERNEL)
94 return;
95
96 // for user threads, set up the global pointer
97 if (thread->owner == current_process)
99
100 MOS_ASSERT(thread->owner->mm == current_mm);
101 MOS_ASSERT(thread != thread->owner->main_thread);
102
103 regs->sp = thread->u_stack.head; // update the stack pointer
104}
105
107{
109 platform_regs_t *from_regs = platform_thread_regs(from);
110 *to_regs = *from_regs;
111 to_regs->a0 = 0; // return 0 for the child
112 if (to->mode == THREAD_MODE_USER)
113 {
114 to->u_stack.head = to_regs->sp;
115 }
116 to->k_stack.head -= sizeof(platform_regs_t);
117}
118
120{
121 MOS_UNUSED(thread);
122 // nothing to cleanup
123}
124
126{
127 const reg_t sstatus = read_csr(sstatus);
128 write_csr(sstatus, sstatus & ~SSTATUS_SIE);
129}
130
132{
133 const reg_t sstatus = read_csr(sstatus);
134 write_csr(sstatus, sstatus | SSTATUS_SIE);
135}
136
138{
139 write_csr(satp, make_satp(SATP_MODE_SV48, 0, pgd_pfn(new_mm->pgd)));
140 __asm__ volatile("sfence.vma zero, zero");
141}
142
143#define FLEN 64 // D extension
144
145static void do_save_fp_context(thread_t *thread)
146{
147 if (thread->mode == THREAD_MODE_KERNEL)
148 return;
149
150#define f_op(reg, val) __asm__ volatile("fld " #reg ", %0" : : "m"(thread->platform_options.f[val]))
151 f_op(f0, 0);
152 f_op(f1, 1);
153 f_op(f2, 2);
154 f_op(f3, 3);
155 f_op(f4, 4);
156 f_op(f5, 5);
157 f_op(f6, 6);
158 f_op(f7, 7);
159 f_op(f8, 8);
160 f_op(f9, 9);
161 f_op(f10, 10);
162 f_op(f11, 11);
163 f_op(f12, 12);
164 f_op(f13, 13);
165 f_op(f14, 14);
166 f_op(f15, 15);
167 f_op(f16, 16);
168 f_op(f17, 17);
169 f_op(f18, 18);
170 f_op(f19, 19);
171 f_op(f20, 20);
172 f_op(f21, 21);
173 f_op(f22, 22);
174 f_op(f23, 23);
175 f_op(f24, 24);
176 f_op(f25, 25);
177 f_op(f26, 26);
178 f_op(f27, 27);
179 f_op(f28, 28);
180 f_op(f29, 29);
181 f_op(f30, 30);
182 f_op(f31, 31);
183 thread->platform_options.fcsr = read_csr(fcsr);
184#undef f_op
185}
186
188{
189 if (thread->mode == THREAD_MODE_KERNEL)
190 return;
191#define f_op(reg, val) __asm__ volatile("fsd " #reg ", %0" : : "m"(thread->platform_options.f[val]))
192 write_csr(fcsr, thread->platform_options.fcsr);
193 f_op(f0, 0);
194 f_op(f1, 1);
195 f_op(f2, 2);
196 f_op(f3, 3);
197 f_op(f4, 4);
198 f_op(f5, 5);
199 f_op(f6, 6);
200 f_op(f7, 7);
201 f_op(f8, 8);
202 f_op(f9, 9);
203 f_op(f10, 10);
204 f_op(f11, 11);
205 f_op(f12, 12);
206 f_op(f13, 13);
207 f_op(f14, 14);
208 f_op(f15, 15);
209 f_op(f16, 16);
210 f_op(f17, 17);
211 f_op(f18, 18);
212 f_op(f19, 19);
213 f_op(f20, 20);
214 f_op(f21, 21);
215 f_op(f22, 22);
216 f_op(f23, 23);
217 f_op(f24, 24);
218 f_op(f25, 25);
219 f_op(f26, 26);
220 f_op(f27, 27);
221 f_op(f28, 28);
222 f_op(f29, 29);
223 f_op(f30, 30);
224 f_op(f31, 31);
225#undef f_op
226}
227
229{
230 const switch_func_t switch_func = statement_expr(switch_func_t, {
231 switch (switch_flags)
232 {
235 default: retval = riscv64_normal_switch_impl; break;
236 }
237 });
238
239 if (current)
241 do_restore_fp_context(new_thread);
242
243 __atomic_store_n(&current_cpu->thread, new_thread, __ATOMIC_SEQ_CST);
244
245 ptr_t trash = 0;
246 ptr_t *const stack_ptr = current ? &current->k_stack.head : &trash;
247 bool trash_lock = false;
248 bool *const lock = current ? &current->state_lock.flag : &trash_lock;
249 riscv64_do_context_switch(stack_ptr, new_thread->k_stack.head, switch_func, lock);
250}
251
253{
254 reg_t sstatus = read_csr(sstatus);
255 sstatus &= ~SSTATUS_SPP;
256 sstatus |= SSTATUS_SPIE;
257 sstatus |= SSTATUS_SUM;
258 write_csr(sstatus, sstatus);
259 write_csr(sscratch, current_thread->k_stack.top);
261 write_csr(sepc, regs->sepc);
262 riscv64_trap_exit(regs);
263}
264
265u64 platform_arch_syscall(u64 syscall, u64 arg1, u64 arg2, u64 arg3, u64 arg4)
266{
267 MOS_UNUSED(arg2);
268 MOS_UNUSED(arg3);
269 MOS_UNUSED(arg4);
270
271 switch (syscall)
272 {
274 {
276 current_cpu->interrupt_regs->tp = arg1;
277 return 0;
278 }
279 }
280 return 0;
281}
282
283void platform_ipi_send(u8 target_cpu, ipi_type_t type)
284{
285 MOS_UNUSED(target_cpu);
286 MOS_UNUSED(type);
287 // pr_emerg("platform_ipi_send() not implemented");
288}
289
291{
292 ptr_t *caller_fp = (ptr_t *) regs->fp;
293 pr_info("Stack dump:");
294 for (int i = 0; i < 16; i++)
295 {
296 pr_info(" %p: %ps", (void *) caller_fp, (void *) *(caller_fp - 1));
297 caller_fp = (ptr_t *) *(caller_fp - 2);
298 if (!caller_fp || !is_aligned(caller_fp, 16) || (ptr_t) caller_fp < MOS_KERNEL_START_VADDR)
299 break;
300 }
301}
302
304{
305 regs->a7 = syscall_nr;
306 regs->sepc -= 4; // replay the 'ecall' instruction
307}
308
310{
311 regs->a0 = result;
312}
313
314void platform_jump_to_signal_handler(const platform_regs_t *regs, const sigreturn_data_t *sigreturn_data, const sigaction_t *sa)
315{
316 current_thread->u_stack.head = regs->sp - 128;
317
318 // backup previous frame
319 stack_push_val(&current_thread->u_stack, *regs);
320 stack_push_val(&current_thread->u_stack, *sigreturn_data);
321
322 // Set up the new context
323 platform_regs_t ret_regs = *regs;
324 ret_regs.sepc = (ptr_t) sa->handler;
325 ret_regs.ra = (ptr_t) sa->sa_restorer; // the return address
326 ret_regs.a0 = sigreturn_data->signal; // arg1
327 ret_regs.sp = current_thread->u_stack.head;
329}
330
332{
333 current_thread->u_stack.head = (ptr_t) sp;
334 sigreturn_data_t data;
335 platform_regs_t regs;
336 stack_pop_val(&current_thread->u_stack, data);
337 stack_pop_val(&current_thread->u_stack, regs);
338
339 signal_on_returned(&data);
341}
#define MOS_ASSERT(cond)
Definition assert.h:14
#define MOS_UNREACHABLE()
Definition assert.h:11
#define stack_pop_val(stack, val)
Definition stack.h:35
#define stack_push_val(stack, val)
Definition stack.h:26
void signal_on_returned(sigreturn_data_t *supplimentary_data)
Return from a signal handler.
Definition signal.c:295
void signal_exit_to_user_prepare(platform_regs_t *regs)
Prepare to exit to userspace.
Definition signal.c:245
MOSAPI void(1, 2) fatal_abort(const char *fmt
#define pa_va(pa)
Definition mm.h:80
@ THREAD_MODE_KERNEL
Definition task_types.h:21
@ THREAD_MODE_USER
Definition task_types.h:22
ipi_type_t
The type of IPI to send.
Definition ipi.h:12
const char ** argv
Definition kmain.c:44
size_t argc
Definition kmain.c:43
#define statement_expr(type,...)
Definition mos_global.h:92
#define is_aligned(ptr, alignment)
Definition mos_global.h:55
#define MOS_UNUSED(x)
Definition mos_global.h:64
#define current
struct _platform_regs platform_regs_t
Definition platform.h:86
#define current_thread
Definition platform.h:30
#define current_mm
Definition platform.h:32
#define current_cpu
Definition platform.h:29
#define current_process
Definition platform.h:31
switch_flags_t
Definition platform.h:71
@ SWITCH_TO_NEW_KERNEL_THREAD
Definition platform.h:74
@ SWITCH_TO_NEW_USER_THREAD
Definition platform.h:73
#define pgd_pfn(pgd)
Definition pml_types.h:90
#define pr_info2(fmt,...)
Definition printk.h:36
#define pr_info(fmt,...)
Definition printk.h:35
#define MOS_KERNEL_START_VADDR
#define SSTATUS_SIE
Definition cpu.h:32
#define SSTATUS_SPIE
Definition cpu.h:33
const char __riscv64_usermode_trap_entry[]
void riscv64_trap_exit(platform_regs_t *regs)
#define read_csr(reg)
Definition cpu.h:23
#define write_csr(reg, val)
Definition cpu.h:24
#define make_satp(mode, asid, ppn)
Definition cpu.h:26
#define SATP_MODE_SV48
Definition cpu.h:29
#define SSTATUS_SUM
Definition cpu.h:35
@ RISCV64_SYSCALL_SET_TP
void platform_context_setup_child_thread(thread_t *thread, thread_entry_t entry, void *arg)
void platform_switch_mm(const mm_context_t *new_mm)
void platform_dump_regs(platform_regs_t *regs)
u32 platform_current_cpu_id()
u64 platform_arch_syscall(u64 syscall, u64 arg1, u64 arg2, u64 arg3, u64 arg4)
void platform_return_to_userspace(platform_regs_t *regs)
void(* switch_func_t)()
void do_restore_fp_context(thread_t *thread)
void platform_syscall_setup_restart_context(platform_regs_t *regs, reg_t syscall_nr)
void platform_restore_from_signal_handler(void *sp)
void platform_interrupt_enable()
static void riscv64_start_kernel_thread()
void platform_context_clone(const thread_t *from, thread_t *to)
void platform_cpu_idle()
void platform_jump_to_signal_handler(const platform_regs_t *regs, const sigreturn_data_t *sigreturn_data, const sigaction_t *sa)
static void riscv64_start_user_thread()
void platform_shutdown()
platform_regs_t * platform_thread_regs(const thread_t *thread)
#define f_op(reg, val)
void platform_ipi_send(u8 target_cpu, ipi_type_t type)
void platform_syscall_store_retval(platform_regs_t *regs, reg_t result)
void platform_context_setup_main_thread(thread_t *thread, ptr_t entry, ptr_t sp, int argc, ptr_t argv, ptr_t envp)
void platform_context_cleanup(thread_t *thread)
void riscv64_do_context_switch(ptr_t *old_stack, ptr_t new_stack, switch_func_t switcher, bool *lock)
void platform_interrupt_disable()
void platform_dump_stack(platform_regs_t *regs)
void riscv64_normal_switch_impl()
static void do_save_fp_context(thread_t *thread)
void platform_switch_to_thread(thread_t *current, thread_t *new_thread, switch_flags_t switch_flags)
static void thread_setup_common(thread_t *thread)
pgd_t pgd
Definition platform.h:82
reg_t s4
Definition cpu.h:14
reg_t t4
Definition cpu.h:15
reg_t s1
Definition cpu.h:12
reg_t tp
Definition cpu.h:10
reg_t sepc
Definition cpu.h:18
reg_t a7
Definition cpu.h:13
reg_t s2
Definition cpu.h:14
reg_t s6
Definition cpu.h:14
reg_t t6
Definition cpu.h:15
reg_t s8
Definition cpu.h:14
reg_t t3
Definition cpu.h:15
reg_t a4
Definition cpu.h:13
reg_t t1
Definition cpu.h:11
reg_t ra
Definition cpu.h:10
reg_t a0
Definition cpu.h:13
reg_t s9
Definition cpu.h:14
reg_t sp
Definition cpu.h:10
reg_t a5
Definition cpu.h:13
reg_t gp
Definition cpu.h:10
reg_t s10
Definition cpu.h:14
reg_t t0
Definition cpu.h:11
reg_t t2
Definition cpu.h:11
reg_t a3
Definition cpu.h:13
reg_t a1
Definition cpu.h:13
reg_t s5
Definition cpu.h:14
reg_t t5
Definition cpu.h:15
reg_t a2
Definition cpu.h:13
reg_t s7
Definition cpu.h:14
reg_t s11
Definition cpu.h:14
reg_t fp
Definition cpu.h:12
reg_t s3
Definition cpu.h:14
reg_t a6
Definition cpu.h:13
mm_context_t * mm
Definition task_types.h:59
thread_t * main_thread
Definition task_types.h:56
__sighandler handler
void(* sa_restorer)(void)
signal_t signal
Definition signal.h:66
platform_thread_options_t platform_options
platform-specific thread options
Definition task_types.h:87
thread_mode mode
user-mode thread or kernel-mode
Definition task_types.h:81
downwards_stack_t u_stack
user-mode stack
Definition task_types.h:84
downwards_stack_t k_stack
kernel-mode stack
Definition task_types.h:85
process_t * owner
Definition task_types.h:79
uintn reg_t
Definition types.h:51
unsigned int u32
Definition types.h:21
void(* thread_entry_t)(void *arg)
Definition types.h:109
#define PTR_FMT
Definition types.h:33
unsigned long ptr_t
Definition types.h:25
unsigned long long u64
Definition types.h:23
unsigned char u8
Definition types.h:19