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