xref: /DragonOS/kernel/src/arch/riscv64/process/syscall.rs (revision 4dd4856f933be0b4624c7f7ffa9e3d0c8c218873)
1 use alloc::{ffi::CString, string::String, vec::Vec};
2 use riscv::register::sstatus::{FS, SPP};
3 use system_error::SystemError;
4 
5 use crate::{
6     arch::{interrupt::TrapFrame, CurrentIrqArch},
7     exception::InterruptArch,
8     mm::ucontext::AddressSpace,
9     process::{
10         exec::{load_binary_file, ExecParam, ExecParamFlags},
11         ProcessManager,
12     },
13     syscall::Syscall,
14 };
15 
16 impl Syscall {
17     pub fn do_execve(
18         path: String,
19         argv: Vec<CString>,
20         envp: Vec<CString>,
21         regs: &mut TrapFrame,
22     ) -> Result<(), SystemError> {
23         // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
24         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
25         let pcb = ProcessManager::current_pcb();
26         // crate::debug!(
27         //     "pid: {:?}  do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
28         //     pcb.pid(),
29         //     path,
30         //     argv,
31         //     envp
32         // );
33 
34         let mut basic_info = pcb.basic_mut();
35         // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
36         let old_address_space = basic_info.user_vm();
37 
38         // 在pcb中原来的用户地址空间
39         unsafe {
40             basic_info.set_user_vm(None);
41         }
42         // 创建新的地址空间并设置为当前地址空间
43         let address_space = AddressSpace::new(true).expect("Failed to create new address space");
44         unsafe {
45             basic_info.set_user_vm(Some(address_space.clone()));
46         }
47 
48         // to avoid deadlock
49         drop(basic_info);
50 
51         assert!(
52             AddressSpace::is_current(&address_space),
53             "Failed to set address space"
54         );
55         // debug!("Switch to new address space");
56 
57         // 切换到新的用户地址空间
58         unsafe { address_space.read().user_mapper.utable.make_current() };
59 
60         drop(old_address_space);
61         drop(irq_guard);
62         // debug!("to load binary file");
63         let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
64 
65         // 加载可执行文件
66         let load_result = load_binary_file(&mut param)?;
67         // debug!("load binary file done");
68         // debug!("argv: {:?}, envp: {:?}", argv, envp);
69         param.init_info_mut().args = argv;
70         param.init_info_mut().envs = envp;
71 
72         // 把proc_init_info写到用户栈上
73         let mut ustack_message = unsafe {
74             address_space
75                 .write()
76                 .user_stack_mut()
77                 .expect("No user stack found")
78                 .clone_info_only()
79         };
80         let (user_sp, argv_ptr) = unsafe {
81             param
82                 .init_info()
83                 .push_at(
84                     // address_space
85                     //     .write()
86                     //     .user_stack_mut()
87                     //     .expect("No user stack found"),
88                     &mut ustack_message,
89                 )
90                 .expect("Failed to push proc_init_info to user stack")
91         };
92         address_space.write().user_stack = Some(ustack_message);
93 
94         // debug!("write proc_init_info to user stack done");
95 
96         regs.a0 = param.init_info().args.len();
97         regs.a1 = argv_ptr.data();
98 
99         // 设置系统调用返回时的寄存器状态
100         regs.sp = user_sp.data();
101 
102         regs.epc = load_result.entry_point().data();
103         regs.status.update_spp(SPP::User);
104         regs.status.update_fs(FS::Clean);
105         regs.status.update_sum(true);
106 
107         drop(param);
108 
109         return Ok(());
110     }
111 
112     /// ## 用于控制和查询与体系结构相关的进程特定选项
113     #[allow(dead_code)]
114     pub fn arch_prctl(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
115         unimplemented!("Syscall::arch_prctl")
116     }
117 }
118