1 use core::{ffi::c_void, panic};
2
3 use alloc::{string::String, vec::Vec};
4
5 use crate::{
6 arch::{asm::current::current_pcb, CurrentIrqArch},
7 exception::InterruptArch,
8 filesystem::vfs::MAX_PATHLEN,
9 include::bindings::bindings::{
10 pt_regs, set_system_trap_gate, CLONE_FS, CLONE_SIGNAL, CLONE_VM, USER_CS, USER_DS,
11 },
12 ipc::signal::sys_rt_sigreturn,
13 mm::{ucontext::AddressSpace, verify_area, VirtAddr},
14 process::exec::{load_binary_file, ExecParam, ExecParamFlags},
15 syscall::{
16 user_access::{check_and_clone_cstr, check_and_clone_cstr_array},
17 Syscall, SystemError, SYS_EXECVE, SYS_FORK, SYS_RT_SIGRETURN, SYS_VFORK,
18 },
19 };
20
21 use super::{asm::ptrace::user_mode, mm::barrier::mfence};
22
23 extern "C" {
do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u6424 fn do_fork(regs: *mut pt_regs, clone_flags: u64, stack_start: u64, stack_size: u64) -> u64;
25
syscall_int()26 fn syscall_int();
27 }
28
29 macro_rules! syscall_return {
30 ($val:expr, $regs:expr) => {{
31 let ret = $val;
32 $regs.rax = ret as u64;
33 return;
34 }};
35 }
36
37 #[no_mangle]
syscall_handler(regs: &mut pt_regs) -> ()38 pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
39 let syscall_num = regs.rax as usize;
40 let args = [
41 regs.r8 as usize,
42 regs.r9 as usize,
43 regs.r10 as usize,
44 regs.r11 as usize,
45 regs.r12 as usize,
46 regs.r13 as usize,
47 regs.r14 as usize,
48 regs.r15 as usize,
49 ];
50 mfence();
51 mfence();
52 let from_user = user_mode(regs);
53
54 // 由于进程管理未完成重构,有些系统调用需要在这里临时处理,以后这里的特殊处理要删掉。
55 match syscall_num {
56 SYS_FORK => unsafe {
57 syscall_return!(do_fork(regs, 0, regs.rsp, 0), regs);
58 },
59 SYS_VFORK => unsafe {
60 syscall_return!(
61 do_fork(
62 regs,
63 (CLONE_VM | CLONE_FS | CLONE_SIGNAL) as u64,
64 regs.rsp,
65 0,
66 ),
67 regs
68 );
69 },
70 SYS_EXECVE => {
71 let path_ptr = args[0];
72 let argv_ptr = args[1];
73 let env_ptr = args[2];
74
75 // 权限校验
76 if from_user
77 && (verify_area(VirtAddr::new(path_ptr), MAX_PATHLEN).is_err()
78 || verify_area(VirtAddr::new(argv_ptr), MAX_PATHLEN).is_err()
79 || verify_area(VirtAddr::new(env_ptr), MAX_PATHLEN).is_err())
80 {
81 syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs);
82 } else {
83 unsafe {
84 // kdebug!("syscall: execve\n");
85 syscall_return!(
86 rs_do_execve(
87 path_ptr as *const u8,
88 argv_ptr as *const *const u8,
89 env_ptr as *const *const u8,
90 regs
91 ),
92 regs
93 );
94 // let path = String::from("/bin/about.elf");
95 // let argv = vec![String::from("/bin/about.elf")];
96 // let envp = vec![String::from("PATH=/bin")];
97 // let r = tmp_rs_execve(path, argv, envp, regs);
98 // kdebug!("syscall: execve r: {:?}\n", r);
99
100 // syscall_return!(
101 // r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize),
102 // regs
103 // )
104 }
105 }
106 }
107
108 SYS_RT_SIGRETURN => {
109 syscall_return!(sys_rt_sigreturn(regs), regs);
110 }
111 // SYS_SCHED => {
112 // syscall_return!(sched(from_user) as u64, regs);
113 // }
114 _ => {}
115 }
116 syscall_return!(Syscall::handle(syscall_num, &args, from_user) as u64, regs);
117 }
118
119 /// 系统调用初始化
arch_syscall_init() -> Result<(), SystemError>120 pub fn arch_syscall_init() -> Result<(), SystemError> {
121 // kinfo!("arch_syscall_init\n");
122 unsafe { set_system_trap_gate(0x80, 0, syscall_int as *mut c_void) }; // 系统调用门
123 return Ok(());
124 }
125
126 #[no_mangle]
rs_do_execve( path: *const u8, argv: *const *const u8, envp: *const *const u8, regs: &mut pt_regs, ) -> usize127 pub unsafe extern "C" fn rs_do_execve(
128 path: *const u8,
129 argv: *const *const u8,
130 envp: *const *const u8,
131 regs: &mut pt_regs,
132 ) -> usize {
133 if path.is_null() {
134 return SystemError::EINVAL.to_posix_errno() as usize;
135 }
136
137 let x = || {
138 let path: String = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
139 let argv: Vec<String> = check_and_clone_cstr_array(argv)?;
140 let envp: Vec<String> = check_and_clone_cstr_array(envp)?;
141 Ok((path, argv, envp))
142 };
143 let r: Result<(String, Vec<String>, Vec<String>), SystemError> = x();
144 if let Err(e) = r {
145 panic!("Failed to execve: {:?}", e);
146 }
147 let (path, argv, envp) = r.unwrap();
148
149 return tmp_rs_execve(path, argv, envp, regs)
150 .map(|_| 0)
151 .unwrap_or_else(|e| {
152 panic!(
153 "Failed to execve, pid: {} error: {:?}",
154 current_pcb().pid,
155 e
156 )
157 });
158 }
159
160 /// 执行第一个用户进程的函数(只应该被调用一次)
161 ///
162 /// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。
163 #[no_mangle]
rs_exec_init_process(regs: &mut pt_regs) -> usize164 pub extern "C" fn rs_exec_init_process(regs: &mut pt_regs) -> usize {
165 let path = String::from("/bin/shell.elf");
166 let argv = vec![String::from("/bin/shell.elf")];
167 let envp = vec![String::from("PATH=/bin")];
168 let r = tmp_rs_execve(path, argv, envp, regs);
169 // kdebug!("rs_exec_init_process: r: {:?}\n", r);
170 return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize);
171 }
172
173 /// 临时的execve系统调用实现,以后要把它改为普通的系统调用。
174 ///
175 /// 现在放在这里的原因是,还没有重构中断管理模块,未实现TrapFrame这个抽象,
176 /// 导致我们必须手动设置中断返回时,各个寄存器的值,这个过程很繁琐,所以暂时放在这里。
tmp_rs_execve( path: String, argv: Vec<String>, envp: Vec<String>, regs: &mut pt_regs, ) -> Result<(), SystemError>177 fn tmp_rs_execve(
178 path: String,
179 argv: Vec<String>,
180 envp: Vec<String>,
181 regs: &mut pt_regs,
182 ) -> Result<(), SystemError> {
183 // kdebug!(
184 // "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
185 // path,
186 // argv,
187 // envp
188 // );
189 // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
190 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
191 // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
192 let old_address_space = current_pcb().address_space();
193 // 在pcb中原来的用户地址空间
194 unsafe {
195 current_pcb().drop_address_space();
196 }
197 // 创建新的地址空间并设置为当前地址空间
198 let address_space = AddressSpace::new(true).expect("Failed to create new address space");
199 unsafe {
200 current_pcb().set_address_space(address_space.clone());
201 }
202 assert!(
203 AddressSpace::is_current(&address_space),
204 "Failed to set address space"
205 );
206 // kdebug!("Switch to new address space");
207
208 // 切换到新的用户地址空间
209 unsafe { address_space.read().user_mapper.utable.make_current() };
210
211 drop(old_address_space);
212 drop(irq_guard);
213 // kdebug!("to load binary file");
214 let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
215 // 加载可执行文件
216 let load_result = load_binary_file(&mut param)
217 .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
218 // kdebug!("load binary file done");
219
220 param.init_info_mut().args = argv;
221 param.init_info_mut().envs = envp;
222
223 // 把proc_init_info写到用户栈上
224
225 let (user_sp, argv_ptr) = unsafe {
226 param
227 .init_info()
228 .push_at(
229 address_space
230 .write()
231 .user_stack_mut()
232 .expect("No user stack found"),
233 )
234 .expect("Failed to push proc_init_info to user stack")
235 };
236
237 // kdebug!("write proc_init_info to user stack done");
238
239 // (兼容旧版libc)把argv的指针写到寄存器内
240 // TODO: 改写旧版libc,不再需要这个兼容
241 regs.rdi = param.init_info().args.len() as u64;
242 regs.rsi = argv_ptr.data() as u64;
243
244 // 设置系统调用返回时的寄存器状态
245 // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
246 regs.rsp = user_sp.data() as u64;
247 regs.rbp = user_sp.data() as u64;
248 regs.rip = load_result.entry_point().data() as u64;
249
250 regs.cs = USER_CS as u64 | 3;
251 regs.ds = USER_DS as u64 | 3;
252 regs.ss = USER_DS as u64 | 3;
253 regs.es = 0;
254 regs.rflags = 0x200;
255 regs.rax = 1;
256
257 // kdebug!("regs: {:?}\n", regs);
258
259 // kdebug!(
260 // "tmp_rs_execve: done, load_result.entry_point()={:?}",
261 // load_result.entry_point()
262 // );
263 return Ok(());
264 }
265