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