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
use crate::{executor::ControlFlow, mem::UserPtr, task::Thread};
mod fs;
mod process;
mod timer;
const SYSCALL_READ: usize = 63;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
const SYSCALL_SCHED_YIELD: usize = 128;
const SYSCALL_GET_TIME: usize = 169;
const SYSCALL_FORK: usize = 220;
const SYSCALL_EXEC: usize = 221;
const SYSCALL_WAITPID: usize = 260;
pub struct SystemCall<'a> {
thread: &'a Thread,
}
impl<'a> SystemCall<'a> {
pub fn new(thread: &'a Thread) -> Self {
Self { thread }
}
pub async fn execute(&mut self) -> ControlFlow {
let trap_context = self.thread.state().lock().kernel_trap_context_mut();
trap_context.set_user_sepc(trap_context.user_sepc() + 4);
let system_call_id = trap_context.user_register(17);
let argument_0 = trap_context.user_register(10);
let argument_1 = trap_context.user_register(11);
let argument_2 = trap_context.user_register(12);
let (exit_code, control_flow) = match system_call_id {
SYSCALL_READ => {
self.sys_read(
argument_0,
UserPtr::new(self.thread.satp(), argument_1),
argument_2,
)
.await
}
SYSCALL_WRITE => self.sys_write(
argument_0,
UserPtr::new(self.thread.satp(), argument_1),
argument_2,
),
SYSCALL_EXIT => self.sys_exit(argument_0),
SYSCALL_SCHED_YIELD => self.sys_sched_yield(),
SYSCALL_GET_TIME => self.sys_get_time(),
SYSCALL_FORK => self.sys_fork(),
SYSCALL_EXEC => self.sys_exec(UserPtr::new(self.thread.satp(), argument_0)),
SYSCALL_WAITPID => {
self.sys_waitpid(
argument_0 as isize,
UserPtr::new(self.thread.satp(), argument_1),
)
.await
}
_ => panic!("unsupported syscall {}", system_call_id),
};
if control_flow == ControlFlow::Continue || control_flow == ControlFlow::Yield {
trap_context.set_user_register(10, exit_code as usize);
}
control_flow
}
}