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