xref: /DragonOS/kernel/src/arch/x86_64/process/syscall.rs (revision bf4a48994a2b284ee34aa49a66b4dec1b6ebc07c)
1 use alloc::{string::String, sync::Arc, 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         ProcessControlBlock, ProcessManager,
14     },
15     syscall::{user_access::UserBufferWriter, 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         // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
26         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
27         let pcb = ProcessManager::current_pcb();
28         // crate::kdebug!(
29         //     "pid: {:?}  do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
30         //     pcb.pid(),
31         //     path,
32         //     argv,
33         //     envp
34         // );
35 
36         let mut basic_info = pcb.basic_mut();
37         // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
38         let old_address_space = basic_info.user_vm();
39 
40         // 在pcb中原来的用户地址空间
41         unsafe {
42             basic_info.set_user_vm(None);
43         }
44         // 创建新的地址空间并设置为当前地址空间
45         let address_space = AddressSpace::new(true).expect("Failed to create new address space");
46         unsafe {
47             basic_info.set_user_vm(Some(address_space.clone()));
48         }
49 
50         // to avoid deadlock
51         drop(basic_info);
52 
53         assert!(
54             AddressSpace::is_current(&address_space),
55             "Failed to set address space"
56         );
57         // kdebug!("Switch to new address space");
58 
59         // 切换到新的用户地址空间
60         unsafe { address_space.read().user_mapper.utable.make_current() };
61 
62         drop(old_address_space);
63         drop(irq_guard);
64         // kdebug!("to load binary file");
65         let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
66 
67         // 加载可执行文件
68         let load_result = load_binary_file(&mut param)
69             .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path));
70         // kdebug!("load binary file done");
71         // kdebug!("argv: {:?}, envp: {:?}", argv, envp);
72         param.init_info_mut().args = argv;
73         param.init_info_mut().envs = envp;
74 
75         // 把proc_init_info写到用户栈上
76 
77         let (user_sp, argv_ptr) = unsafe {
78             param
79                 .init_info()
80                 .push_at(
81                     address_space
82                         .write()
83                         .user_stack_mut()
84                         .expect("No user stack found"),
85                 )
86                 .expect("Failed to push proc_init_info to user stack")
87         };
88 
89         // kdebug!("write proc_init_info to user stack done");
90 
91         // (兼容旧版libc)把argv的指针写到寄存器内
92         // TODO: 改写旧版libc,不再需要这个兼容
93         regs.rdi = param.init_info().args.len() as u64;
94         regs.rsi = argv_ptr.data() as u64;
95 
96         // 设置系统调用返回时的寄存器状态
97         // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
98         regs.rsp = user_sp.data() as u64;
99         regs.rbp = user_sp.data() as u64;
100         regs.rip = load_result.entry_point().data() as u64;
101 
102         regs.cs = USER_CS.bits() as u64;
103         regs.ds = USER_DS.bits() as u64;
104         regs.ss = USER_DS.bits() as u64;
105         regs.es = 0;
106         regs.rflags = 0x200;
107         regs.rax = 1;
108 
109         drop(param);
110 
111         // kdebug!("regs: {:?}\n", regs);
112 
113         // crate::kdebug!(
114         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
115         //     load_result.entry_point()
116         // );
117 
118         return Ok(());
119     }
120 
121     /// ## 用于控制和查询与体系结构相关的进程特定选项
122     pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
123         let pcb = ProcessManager::current_pcb();
124         if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
125             Self::do_arch_prctl_common(option, arg2)?;
126         }
127         Ok(0)
128     }
129 
130     /// ## 64位下控制fs/gs base寄存器的方法
131     pub fn do_arch_prctl_64(
132         pcb: &Arc<ProcessControlBlock>,
133         option: usize,
134         arg2: usize,
135         from_user: bool,
136     ) -> Result<usize, SystemError> {
137         let mut arch_info = pcb.arch_info_irqsave();
138         match option {
139             ARCH_GET_FS => {
140                 unsafe { arch_info.save_fsbase() };
141                 let mut writer = UserBufferWriter::new(
142                     arg2 as *mut usize,
143                     core::mem::size_of::<usize>(),
144                     from_user,
145                 )?;
146                 writer.copy_one_to_user(&arch_info.fsbase, 0)?;
147             }
148             ARCH_GET_GS => {
149                 unsafe { arch_info.save_gsbase() };
150                 let mut writer = UserBufferWriter::new(
151                     arg2 as *mut usize,
152                     core::mem::size_of::<usize>(),
153                     from_user,
154                 )?;
155                 writer.copy_one_to_user(&arch_info.gsbase, 0)?;
156             }
157             ARCH_SET_FS => {
158                 arch_info.fsbase = arg2;
159                 // 如果是当前进程则直接写入寄存器
160                 if pcb.pid() == ProcessManager::current_pcb().pid() {
161                     unsafe { arch_info.restore_fsbase() }
162                 }
163             }
164             ARCH_SET_GS => {
165                 arch_info.gsbase = arg2;
166                 if pcb.pid() == ProcessManager::current_pcb().pid() {
167                     unsafe { arch_info.restore_gsbase() }
168                 }
169             }
170             _ => {
171                 return Err(SystemError::EINVAL);
172             }
173         }
174         Ok(0)
175     }
176 
177     #[allow(dead_code)]
178     pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
179         todo!("do_arch_prctl_common not unimplemented");
180     }
181 }
182 
183 pub const ARCH_SET_GS: usize = 0x1001;
184 pub const ARCH_SET_FS: usize = 0x1002;
185 pub const ARCH_GET_FS: usize = 0x1003;
186 pub const ARCH_GET_GS: usize = 0x1004;
187