xref: /DragonOS/kernel/src/arch/x86_64/process/syscall.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1 use alloc::{ffi::CString, 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<CString>,
23         envp: Vec<CString>,
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         // log::debug!(
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         // debug!("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         // debug!("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         // debug!("load binary file done");
71         // debug!("argv: {:?}, envp: {:?}", argv, envp);
72         param.init_info_mut().args = argv;
73         param.init_info_mut().envs = envp;
74 
75         // 把proc_init_info写到用户栈上
76         let mut ustack_message = unsafe {
77             address_space
78                 .write()
79                 .user_stack_mut()
80                 .expect("No user stack found")
81                 .clone_info_only()
82         };
83         let (user_sp, argv_ptr) = unsafe {
84             param
85                 .init_info()
86                 .push_at(
87                     // address_space
88                     //     .write()
89                     //     .user_stack_mut()
90                     //     .expect("No user stack found"),
91                     &mut ustack_message,
92                 )
93                 .expect("Failed to push proc_init_info to user stack")
94         };
95         address_space.write().user_stack = Some(ustack_message);
96 
97         // debug!("write proc_init_info to user stack done");
98 
99         // (兼容旧版libc)把argv的指针写到寄存器内
100         // TODO: 改写旧版libc,不再需要这个兼容
101         regs.rdi = param.init_info().args.len() as u64;
102         regs.rsi = argv_ptr.data() as u64;
103 
104         // 设置系统调用返回时的寄存器状态
105         // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
106         regs.rsp = user_sp.data() as u64;
107         regs.rbp = user_sp.data() as u64;
108         regs.rip = load_result.entry_point().data() as u64;
109 
110         regs.cs = USER_CS.bits() as u64;
111         regs.ds = USER_DS.bits() as u64;
112         regs.ss = USER_DS.bits() as u64;
113         regs.es = 0;
114         regs.rflags = 0x200;
115         regs.rax = 1;
116 
117         drop(param);
118 
119         // debug!("regs: {:?}\n", regs);
120 
121         // crate::debug!(
122         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
123         //     load_result.entry_point()
124         // );
125 
126         return Ok(());
127     }
128 
129     /// ## 用于控制和查询与体系结构相关的进程特定选项
130     pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
131         let pcb = ProcessManager::current_pcb();
132         if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
133             Self::do_arch_prctl_common(option, arg2)?;
134         }
135         Ok(0)
136     }
137 
138     /// ## 64位下控制fs/gs base寄存器的方法
139     pub fn do_arch_prctl_64(
140         pcb: &Arc<ProcessControlBlock>,
141         option: usize,
142         arg2: usize,
143         from_user: bool,
144     ) -> Result<usize, SystemError> {
145         let mut arch_info = pcb.arch_info_irqsave();
146         match option {
147             ARCH_GET_FS => {
148                 unsafe { arch_info.save_fsbase() };
149                 let mut writer = UserBufferWriter::new(
150                     arg2 as *mut usize,
151                     core::mem::size_of::<usize>(),
152                     from_user,
153                 )?;
154                 writer.copy_one_to_user(&arch_info.fsbase, 0)?;
155             }
156             ARCH_GET_GS => {
157                 unsafe { arch_info.save_gsbase() };
158                 let mut writer = UserBufferWriter::new(
159                     arg2 as *mut usize,
160                     core::mem::size_of::<usize>(),
161                     from_user,
162                 )?;
163                 writer.copy_one_to_user(&arch_info.gsbase, 0)?;
164             }
165             ARCH_SET_FS => {
166                 arch_info.fsbase = arg2;
167                 // 如果是当前进程则直接写入寄存器
168                 if pcb.pid() == ProcessManager::current_pcb().pid() {
169                     unsafe { arch_info.restore_fsbase() }
170                 }
171             }
172             ARCH_SET_GS => {
173                 arch_info.gsbase = arg2;
174                 if pcb.pid() == ProcessManager::current_pcb().pid() {
175                     unsafe { arch_info.restore_gsbase() }
176                 }
177             }
178             _ => {
179                 return Err(SystemError::EINVAL);
180             }
181         }
182         Ok(0)
183     }
184 
185     #[allow(dead_code)]
186     pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
187         todo!("do_arch_prctl_common not unimplemented");
188     }
189 }
190 
191 pub const ARCH_SET_GS: usize = 0x1001;
192 pub const ARCH_SET_FS: usize = 0x1002;
193 pub const ARCH_GET_FS: usize = 0x1003;
194 pub const ARCH_GET_GS: usize = 0x1004;
195