1971462beSGnoCiYeH use alloc::{string::String, sync::Arc, vec::Vec}; 291e9d4abSLoGin use system_error::SystemError; 31496ba7bSLoGin 41496ba7bSLoGin use crate::{ 51496ba7bSLoGin arch::{ 61496ba7bSLoGin interrupt::TrapFrame, 71496ba7bSLoGin process::table::{USER_CS, USER_DS}, 81496ba7bSLoGin CurrentIrqArch, 91496ba7bSLoGin }, 101496ba7bSLoGin exception::InterruptArch, 111496ba7bSLoGin mm::ucontext::AddressSpace, 121496ba7bSLoGin process::{ 131496ba7bSLoGin exec::{load_binary_file, ExecParam, ExecParamFlags}, 14971462beSGnoCiYeH ProcessControlBlock, ProcessManager, 151496ba7bSLoGin }, 1691e9d4abSLoGin syscall::{user_access::UserBufferWriter, Syscall}, 171496ba7bSLoGin }; 181496ba7bSLoGin 191496ba7bSLoGin impl Syscall { 201496ba7bSLoGin pub fn do_execve( 211496ba7bSLoGin path: String, 221496ba7bSLoGin argv: Vec<String>, 231496ba7bSLoGin envp: Vec<String>, 241496ba7bSLoGin regs: &mut TrapFrame, 251496ba7bSLoGin ) -> Result<(), SystemError> { 26bf4a4899SLoGin // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 27bf4a4899SLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 28bf4a4899SLoGin let pcb = ProcessManager::current_pcb(); 29*2eab6dd7S曾俊 // crate::debug!( 30bf4a4899SLoGin // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n", 31bf4a4899SLoGin // pcb.pid(), 321496ba7bSLoGin // path, 331496ba7bSLoGin // argv, 341496ba7bSLoGin // envp 351496ba7bSLoGin // ); 361496ba7bSLoGin 371496ba7bSLoGin let mut basic_info = pcb.basic_mut(); 381496ba7bSLoGin // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) 391496ba7bSLoGin let old_address_space = basic_info.user_vm(); 401496ba7bSLoGin 411496ba7bSLoGin // 在pcb中原来的用户地址空间 421496ba7bSLoGin unsafe { 431496ba7bSLoGin basic_info.set_user_vm(None); 441496ba7bSLoGin } 451496ba7bSLoGin // 创建新的地址空间并设置为当前地址空间 461496ba7bSLoGin let address_space = AddressSpace::new(true).expect("Failed to create new address space"); 471496ba7bSLoGin unsafe { 481496ba7bSLoGin basic_info.set_user_vm(Some(address_space.clone())); 491496ba7bSLoGin } 501496ba7bSLoGin 511496ba7bSLoGin // to avoid deadlock 521496ba7bSLoGin drop(basic_info); 531496ba7bSLoGin 541496ba7bSLoGin assert!( 551496ba7bSLoGin AddressSpace::is_current(&address_space), 561496ba7bSLoGin "Failed to set address space" 571496ba7bSLoGin ); 58*2eab6dd7S曾俊 // debug!("Switch to new address space"); 591496ba7bSLoGin 601496ba7bSLoGin // 切换到新的用户地址空间 611496ba7bSLoGin unsafe { address_space.read().user_mapper.utable.make_current() }; 621496ba7bSLoGin 631496ba7bSLoGin drop(old_address_space); 641496ba7bSLoGin drop(irq_guard); 65*2eab6dd7S曾俊 // debug!("to load binary file"); 66a02ce654SChiichen let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?; 671496ba7bSLoGin 681496ba7bSLoGin // 加载可执行文件 69f75cb0f8SLoGin let load_result = load_binary_file(&mut param)?; 70*2eab6dd7S曾俊 // debug!("load binary file done"); 71*2eab6dd7S曾俊 // debug!("argv: {:?}, envp: {:?}", argv, envp); 721496ba7bSLoGin param.init_info_mut().args = argv; 731496ba7bSLoGin param.init_info_mut().envs = envp; 741496ba7bSLoGin 751496ba7bSLoGin // 把proc_init_info写到用户栈上 76a17651b1SMemoryShore let mut ustack_message = unsafe { 77a17651b1SMemoryShore address_space 78a17651b1SMemoryShore .write() 79a17651b1SMemoryShore .user_stack_mut() 80a17651b1SMemoryShore .expect("No user stack found") 81a17651b1SMemoryShore .clone_info_only() 82a17651b1SMemoryShore }; 831496ba7bSLoGin let (user_sp, argv_ptr) = unsafe { 841496ba7bSLoGin param 851496ba7bSLoGin .init_info() 861496ba7bSLoGin .push_at( 87a17651b1SMemoryShore // address_space 88a17651b1SMemoryShore // .write() 89a17651b1SMemoryShore // .user_stack_mut() 90a17651b1SMemoryShore // .expect("No user stack found"), 91a17651b1SMemoryShore &mut ustack_message, 921496ba7bSLoGin ) 931496ba7bSLoGin .expect("Failed to push proc_init_info to user stack") 941496ba7bSLoGin }; 95a17651b1SMemoryShore address_space.write().user_stack = Some(ustack_message); 961496ba7bSLoGin 97*2eab6dd7S曾俊 // debug!("write proc_init_info to user stack done"); 981496ba7bSLoGin 991496ba7bSLoGin // (兼容旧版libc)把argv的指针写到寄存器内 1001496ba7bSLoGin // TODO: 改写旧版libc,不再需要这个兼容 1011496ba7bSLoGin regs.rdi = param.init_info().args.len() as u64; 1021496ba7bSLoGin regs.rsi = argv_ptr.data() as u64; 1031496ba7bSLoGin 1041496ba7bSLoGin // 设置系统调用返回时的寄存器状态 1051496ba7bSLoGin // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。 1061496ba7bSLoGin regs.rsp = user_sp.data() as u64; 1071496ba7bSLoGin regs.rbp = user_sp.data() as u64; 1081496ba7bSLoGin regs.rip = load_result.entry_point().data() as u64; 1091496ba7bSLoGin 1101496ba7bSLoGin regs.cs = USER_CS.bits() as u64; 1111496ba7bSLoGin regs.ds = USER_DS.bits() as u64; 1121496ba7bSLoGin regs.ss = USER_DS.bits() as u64; 1131496ba7bSLoGin regs.es = 0; 1141496ba7bSLoGin regs.rflags = 0x200; 1151496ba7bSLoGin regs.rax = 1; 1161496ba7bSLoGin 117971462beSGnoCiYeH drop(param); 118971462beSGnoCiYeH 119*2eab6dd7S曾俊 // debug!("regs: {:?}\n", regs); 1201496ba7bSLoGin 121*2eab6dd7S曾俊 // crate::debug!( 1221496ba7bSLoGin // "tmp_rs_execve: done, load_result.entry_point()={:?}", 1231496ba7bSLoGin // load_result.entry_point() 1241496ba7bSLoGin // ); 125876cb89eSGnoCiYeH 1261496ba7bSLoGin return Ok(()); 1271496ba7bSLoGin } 128971462beSGnoCiYeH 129971462beSGnoCiYeH /// ## 用于控制和查询与体系结构相关的进程特定选项 130971462beSGnoCiYeH pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> { 131971462beSGnoCiYeH let pcb = ProcessManager::current_pcb(); 132971462beSGnoCiYeH if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) { 133971462beSGnoCiYeH Self::do_arch_prctl_common(option, arg2)?; 1341496ba7bSLoGin } 135971462beSGnoCiYeH Ok(0) 136971462beSGnoCiYeH } 137971462beSGnoCiYeH 138971462beSGnoCiYeH /// ## 64位下控制fs/gs base寄存器的方法 139971462beSGnoCiYeH pub fn do_arch_prctl_64( 140971462beSGnoCiYeH pcb: &Arc<ProcessControlBlock>, 141971462beSGnoCiYeH option: usize, 142971462beSGnoCiYeH arg2: usize, 143971462beSGnoCiYeH from_user: bool, 144971462beSGnoCiYeH ) -> Result<usize, SystemError> { 145971462beSGnoCiYeH let mut arch_info = pcb.arch_info_irqsave(); 146971462beSGnoCiYeH match option { 147971462beSGnoCiYeH ARCH_GET_FS => { 148971462beSGnoCiYeH unsafe { arch_info.save_fsbase() }; 149971462beSGnoCiYeH let mut writer = UserBufferWriter::new( 150971462beSGnoCiYeH arg2 as *mut usize, 151971462beSGnoCiYeH core::mem::size_of::<usize>(), 152971462beSGnoCiYeH from_user, 153971462beSGnoCiYeH )?; 154971462beSGnoCiYeH writer.copy_one_to_user(&arch_info.fsbase, 0)?; 155971462beSGnoCiYeH } 156971462beSGnoCiYeH ARCH_GET_GS => { 157971462beSGnoCiYeH unsafe { arch_info.save_gsbase() }; 158971462beSGnoCiYeH let mut writer = UserBufferWriter::new( 159971462beSGnoCiYeH arg2 as *mut usize, 160971462beSGnoCiYeH core::mem::size_of::<usize>(), 161971462beSGnoCiYeH from_user, 162971462beSGnoCiYeH )?; 163971462beSGnoCiYeH writer.copy_one_to_user(&arch_info.gsbase, 0)?; 164971462beSGnoCiYeH } 165971462beSGnoCiYeH ARCH_SET_FS => { 166971462beSGnoCiYeH arch_info.fsbase = arg2; 167971462beSGnoCiYeH // 如果是当前进程则直接写入寄存器 168971462beSGnoCiYeH if pcb.pid() == ProcessManager::current_pcb().pid() { 169971462beSGnoCiYeH unsafe { arch_info.restore_fsbase() } 170971462beSGnoCiYeH } 171971462beSGnoCiYeH } 172971462beSGnoCiYeH ARCH_SET_GS => { 173971462beSGnoCiYeH arch_info.gsbase = arg2; 174971462beSGnoCiYeH if pcb.pid() == ProcessManager::current_pcb().pid() { 175971462beSGnoCiYeH unsafe { arch_info.restore_gsbase() } 176971462beSGnoCiYeH } 177971462beSGnoCiYeH } 178971462beSGnoCiYeH _ => { 179971462beSGnoCiYeH return Err(SystemError::EINVAL); 180971462beSGnoCiYeH } 181971462beSGnoCiYeH } 182971462beSGnoCiYeH Ok(0) 183971462beSGnoCiYeH } 184971462beSGnoCiYeH 185971462beSGnoCiYeH #[allow(dead_code)] 186971462beSGnoCiYeH pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> { 187971462beSGnoCiYeH todo!("do_arch_prctl_common not unimplemented"); 188971462beSGnoCiYeH } 189971462beSGnoCiYeH } 190971462beSGnoCiYeH 191971462beSGnoCiYeH pub const ARCH_SET_GS: usize = 0x1001; 192971462beSGnoCiYeH pub const ARCH_SET_FS: usize = 0x1002; 193971462beSGnoCiYeH pub const ARCH_GET_FS: usize = 0x1003; 194971462beSGnoCiYeH pub const ARCH_GET_GS: usize = 0x1004; 195