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