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