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
mod gen;
mod file;
pub use gen::*;
use crate::process::{TrapFrame, Register, my_proc, fork, exec, exit, Process};
use crate::{info, panic, print, println};
use crate::page;
use crate::mem::{align_val, page_down};
use crate::symbols::{PAGE_ORDER, PAGE_SIZE};
use file::*;
use alloc::sync::Arc;
use crate::file::File;
use alloc::boxed::Box;
use crate::spinlock::Mutex;
pub fn argraw(tf: &TrapFrame, pos: usize) -> usize {
match pos {
0 => tf.regs[Register::a0 as usize],
1 => tf.regs[Register::a1 as usize],
2 => tf.regs[Register::a2 as usize],
3 => tf.regs[Register::a3 as usize],
4 => tf.regs[Register::a4 as usize],
5 => tf.regs[Register::a5 as usize],
_ => unreachable!()
}
}
pub fn arg_int(tf: &TrapFrame, pos: usize) -> i32 {
argraw(tf, pos) as i32
}
pub fn arg_uint(tf: &TrapFrame, pos: usize) -> usize {
let sz = argraw(tf, pos) as i32;
if sz < 0 {
panic!("invalid unsigned int");
}
sz as usize
}
pub fn arg_ptr(pgtable: &page::Table, tf: &TrapFrame, pos: usize, sz: usize) -> *const u8 {
let ptr = argraw(tf, pos);
let pg_begin = page_down(ptr);
if ptr + sz >= pg_begin + PAGE_SIZE {
panic!("out of bound!");
}
let paddr = pgtable.paddr_of(pg_begin).unwrap();
unsafe { (paddr as *const u8).add(ptr - pg_begin) }
}
pub fn arg_ptr_mut(pgtable: &page::Table, tf: &TrapFrame, pos: usize, sz: usize) -> *mut u8 {
arg_ptr(pgtable, tf, pos, sz) as *mut u8
}
pub fn arg_fd(p: &Process, pos: usize) -> &Arc<File> {
let fd = argraw(&p.trapframe, pos);
match &p.files[fd] {
Some(x) => return x,
None => panic!("invalid file handler {}", fd)
}
}
fn sys_fork() -> i32 {
fork()
}
fn sys_exec() -> i32 {
let path;
{
let p = my_proc();
let sz = arg_uint(&p.trapframe, 1);
let ptr = arg_ptr(&p.pgtable, &p.trapframe, 0, sz);
path = unsafe {
let slice = core::slice::from_raw_parts(ptr, sz);
core::str::from_utf8(slice).unwrap()
};
}
if path == "/init" {
info!("running tests before init...");
crate::test::run_tests();
}
exec(path);
0
}
fn sys_exit() -> i32 {
let code;
{
let p = my_proc();
code = arg_int(&p.trapframe, 0);
}
exit(code);
}
pub fn syscall() -> i32 {
let syscall_id;
{
let p = my_proc();
let tf = &p.trapframe;
syscall_id = tf.regs[Register::a7 as usize] as i64;
}
match syscall_id {
SYS_WRITE => sys_write(),
SYS_READ => sys_read(),
SYS_FORK => sys_fork(),
SYS_EXEC => sys_exec(),
SYS_EXIT => sys_exit(),
SYS_DUP => sys_dup(),
SYS_OPEN => sys_open(),
SYS_CLOSE => sys_close(),
_ => unreachable!()
}
}