xref: /DragonOS/kernel/src/arch/x86_64/process/syscall.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
1*1496ba7bSLoGin use alloc::{string::String, vec::Vec};
2*1496ba7bSLoGin 
3*1496ba7bSLoGin use crate::{
4*1496ba7bSLoGin     arch::{
5*1496ba7bSLoGin         interrupt::TrapFrame,
6*1496ba7bSLoGin         process::table::{USER_CS, USER_DS},
7*1496ba7bSLoGin         CurrentIrqArch,
8*1496ba7bSLoGin     },
9*1496ba7bSLoGin     exception::InterruptArch,
10*1496ba7bSLoGin     mm::ucontext::AddressSpace,
11*1496ba7bSLoGin     process::{
12*1496ba7bSLoGin         exec::{load_binary_file, ExecParam, ExecParamFlags},
13*1496ba7bSLoGin         ProcessManager,
14*1496ba7bSLoGin     },
15*1496ba7bSLoGin     syscall::{Syscall, SystemError},
16*1496ba7bSLoGin };
17*1496ba7bSLoGin 
18*1496ba7bSLoGin impl Syscall {
19*1496ba7bSLoGin     pub fn do_execve(
20*1496ba7bSLoGin         path: String,
21*1496ba7bSLoGin         argv: Vec<String>,
22*1496ba7bSLoGin         envp: Vec<String>,
23*1496ba7bSLoGin         regs: &mut TrapFrame,
24*1496ba7bSLoGin     ) -> Result<(), SystemError> {
25*1496ba7bSLoGin         // kdebug!(
26*1496ba7bSLoGin         //     "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
27*1496ba7bSLoGin         //     path,
28*1496ba7bSLoGin         //     argv,
29*1496ba7bSLoGin         //     envp
30*1496ba7bSLoGin         // );
31*1496ba7bSLoGin         // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
32*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
33*1496ba7bSLoGin         let pcb = ProcessManager::current_pcb();
34*1496ba7bSLoGin 
35*1496ba7bSLoGin         let mut basic_info = pcb.basic_mut();
36*1496ba7bSLoGin         // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
37*1496ba7bSLoGin         let old_address_space = basic_info.user_vm();
38*1496ba7bSLoGin 
39*1496ba7bSLoGin         // 在pcb中原来的用户地址空间
40*1496ba7bSLoGin         unsafe {
41*1496ba7bSLoGin             basic_info.set_user_vm(None);
42*1496ba7bSLoGin         }
43*1496ba7bSLoGin         // 创建新的地址空间并设置为当前地址空间
44*1496ba7bSLoGin         let address_space = AddressSpace::new(true).expect("Failed to create new address space");
45*1496ba7bSLoGin         unsafe {
46*1496ba7bSLoGin             basic_info.set_user_vm(Some(address_space.clone()));
47*1496ba7bSLoGin         }
48*1496ba7bSLoGin 
49*1496ba7bSLoGin         // to avoid deadlock
50*1496ba7bSLoGin         drop(basic_info);
51*1496ba7bSLoGin 
52*1496ba7bSLoGin         assert!(
53*1496ba7bSLoGin             AddressSpace::is_current(&address_space),
54*1496ba7bSLoGin             "Failed to set address space"
55*1496ba7bSLoGin         );
56*1496ba7bSLoGin         // kdebug!("Switch to new address space");
57*1496ba7bSLoGin 
58*1496ba7bSLoGin         // 切换到新的用户地址空间
59*1496ba7bSLoGin         unsafe { address_space.read().user_mapper.utable.make_current() };
60*1496ba7bSLoGin 
61*1496ba7bSLoGin         drop(old_address_space);
62*1496ba7bSLoGin         drop(irq_guard);
63*1496ba7bSLoGin         // kdebug!("to load binary file");
64*1496ba7bSLoGin         let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
65*1496ba7bSLoGin 
66*1496ba7bSLoGin         // 加载可执行文件
67*1496ba7bSLoGin         let load_result = load_binary_file(&mut param)
68*1496ba7bSLoGin             .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
69*1496ba7bSLoGin         // kdebug!("load binary file done");
70*1496ba7bSLoGin         // kdebug!("argv: {:?}, envp: {:?}", argv, envp);
71*1496ba7bSLoGin         param.init_info_mut().args = argv;
72*1496ba7bSLoGin         param.init_info_mut().envs = envp;
73*1496ba7bSLoGin 
74*1496ba7bSLoGin         // 把proc_init_info写到用户栈上
75*1496ba7bSLoGin 
76*1496ba7bSLoGin         let (user_sp, argv_ptr) = unsafe {
77*1496ba7bSLoGin             param
78*1496ba7bSLoGin                 .init_info()
79*1496ba7bSLoGin                 .push_at(
80*1496ba7bSLoGin                     address_space
81*1496ba7bSLoGin                         .write()
82*1496ba7bSLoGin                         .user_stack_mut()
83*1496ba7bSLoGin                         .expect("No user stack found"),
84*1496ba7bSLoGin                 )
85*1496ba7bSLoGin                 .expect("Failed to push proc_init_info to user stack")
86*1496ba7bSLoGin         };
87*1496ba7bSLoGin 
88*1496ba7bSLoGin         // kdebug!("write proc_init_info to user stack done");
89*1496ba7bSLoGin 
90*1496ba7bSLoGin         // (兼容旧版libc)把argv的指针写到寄存器内
91*1496ba7bSLoGin         // TODO: 改写旧版libc,不再需要这个兼容
92*1496ba7bSLoGin         regs.rdi = param.init_info().args.len() as u64;
93*1496ba7bSLoGin         regs.rsi = argv_ptr.data() as u64;
94*1496ba7bSLoGin 
95*1496ba7bSLoGin         // 设置系统调用返回时的寄存器状态
96*1496ba7bSLoGin         // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
97*1496ba7bSLoGin         regs.rsp = user_sp.data() as u64;
98*1496ba7bSLoGin         regs.rbp = user_sp.data() as u64;
99*1496ba7bSLoGin         regs.rip = load_result.entry_point().data() as u64;
100*1496ba7bSLoGin 
101*1496ba7bSLoGin         regs.cs = USER_CS.bits() as u64;
102*1496ba7bSLoGin         regs.ds = USER_DS.bits() as u64;
103*1496ba7bSLoGin         regs.ss = USER_DS.bits() as u64;
104*1496ba7bSLoGin         regs.es = 0;
105*1496ba7bSLoGin         regs.rflags = 0x200;
106*1496ba7bSLoGin         regs.rax = 1;
107*1496ba7bSLoGin 
108*1496ba7bSLoGin         // kdebug!("regs: {:?}\n", regs);
109*1496ba7bSLoGin 
110*1496ba7bSLoGin         // kdebug!(
111*1496ba7bSLoGin         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
112*1496ba7bSLoGin         //     load_result.entry_point()
113*1496ba7bSLoGin         // );
114*1496ba7bSLoGin         return Ok(());
115*1496ba7bSLoGin     }
116*1496ba7bSLoGin }
117