xref: /DragonOS/kernel/src/arch/x86_64/process/syscall.rs (revision 4935c74f326cd4e0854959c0ec8ab1d726c05e41)
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         // 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         drop(param);
109 
110         // kdebug!("regs: {:?}\n", regs);
111 
112         // kdebug!(
113         //     "tmp_rs_execve: done, load_result.entry_point()={:?}",
114         //     load_result.entry_point()
115         // );
116 
117         return Ok(());
118     }
119 
120     /// ## 用于控制和查询与体系结构相关的进程特定选项
121     pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
122         let pcb = ProcessManager::current_pcb();
123         if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
124             Self::do_arch_prctl_common(option, arg2)?;
125         }
126         Ok(0)
127     }
128 
129     /// ## 64位下控制fs/gs base寄存器的方法
130     pub fn do_arch_prctl_64(
131         pcb: &Arc<ProcessControlBlock>,
132         option: usize,
133         arg2: usize,
134         from_user: bool,
135     ) -> Result<usize, SystemError> {
136         let mut arch_info = pcb.arch_info_irqsave();
137         match option {
138             ARCH_GET_FS => {
139                 unsafe { arch_info.save_fsbase() };
140                 let mut writer = UserBufferWriter::new(
141                     arg2 as *mut usize,
142                     core::mem::size_of::<usize>(),
143                     from_user,
144                 )?;
145                 writer.copy_one_to_user(&arch_info.fsbase, 0)?;
146             }
147             ARCH_GET_GS => {
148                 unsafe { arch_info.save_gsbase() };
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.gsbase, 0)?;
155             }
156             ARCH_SET_FS => {
157                 arch_info.fsbase = arg2;
158                 // 如果是当前进程则直接写入寄存器
159                 if pcb.pid() == ProcessManager::current_pcb().pid() {
160                     unsafe { arch_info.restore_fsbase() }
161                 }
162             }
163             ARCH_SET_GS => {
164                 arch_info.gsbase = arg2;
165                 if pcb.pid() == ProcessManager::current_pcb().pid() {
166                     unsafe { arch_info.restore_gsbase() }
167                 }
168             }
169             _ => {
170                 return Err(SystemError::EINVAL);
171             }
172         }
173         Ok(0)
174     }
175 
176     #[allow(dead_code)]
177     pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
178         todo!("do_arch_prctl_common not unimplemented");
179     }
180 }
181 
182 pub const ARCH_SET_GS: usize = 0x1001;
183 pub const ARCH_SET_FS: usize = 0x1002;
184 pub const ARCH_GET_FS: usize = 0x1003;
185 pub const ARCH_GET_GS: usize = 0x1004;
186