xref: /DragonOS/kernel/src/arch/x86_64/process/syscall.rs (revision afc95d5c2541c27c762091ad38fdffabe355db5a)
1 use alloc::{string::String, vec::Vec};
2 
3 use crate::{
4     arch::{
5         interrupt::TrapFrame,
6         process::table::{USER_CS, USER_DS},
7         CurrentIrqArch,
8     },
9     exception::InterruptArch,
10     mm::ucontext::AddressSpace,
11     process::{
12         exec::{load_binary_file, ExecParam, ExecParamFlags},
13         ProcessManager,
14     },
15     syscall::{Syscall, SystemError},
16 };
17 
18 impl Syscall {
19     pub fn do_execve(
20         path: String,
21         argv: Vec<String>,
22         envp: Vec<String>,
23         regs: &mut TrapFrame,
24     ) -> Result<(), SystemError> {
25         // kdebug!(
26         //     "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
27         //     path,
28         //     argv,
29         //     envp
30         // );
31         // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
32         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
33         let pcb = ProcessManager::current_pcb();
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 
76         let (user_sp, argv_ptr) = unsafe {
77             param
78                 .init_info()
79                 .push_at(
80                     address_space
81                         .write()
82                         .user_stack_mut()
83                         .expect("No user stack found"),
84                 )
85                 .expect("Failed to push proc_init_info to user stack")
86         };
87 
88         // kdebug!("write proc_init_info to user stack done");
89 
90         // (兼容旧版libc)把argv的指针写到寄存器内
91         // TODO: 改写旧版libc,不再需要这个兼容
92         regs.rdi = param.init_info().args.len() as u64;
93         regs.rsi = argv_ptr.data() as u64;
94 
95         // 设置系统调用返回时的寄存器状态
96         // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
97         regs.rsp = user_sp.data() as u64;
98         regs.rbp = user_sp.data() as u64;
99         regs.rip = load_result.entry_point().data() as u64;
100 
101         regs.cs = USER_CS.bits() as u64;
102         regs.ds = USER_DS.bits() as u64;
103         regs.ss = USER_DS.bits() as u64;
104         regs.es = 0;
105         regs.rflags = 0x200;
106         regs.rax = 1;
107 
108         // kdebug!("regs: {:?}\n", regs);
109 
110         // kdebug!(
111         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
112         //     load_result.entry_point()
113         // );
114 
115         return Ok(());
116     }
117 }
118