syscall.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. use alloc::{ffi::CString, string::String, sync::Arc, vec::Vec};
  2. use system_error::SystemError;
  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},
  16. };
  17. impl Syscall {
  18. pub fn do_execve(
  19. path: String,
  20. argv: Vec<CString>,
  21. envp: Vec<CString>,
  22. regs: &mut TrapFrame,
  23. ) -> Result<(), SystemError> {
  24. // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
  25. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  26. let pcb = ProcessManager::current_pcb();
  27. // log::debug!(
  28. // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
  29. // pcb.pid(),
  30. // path,
  31. // argv,
  32. // envp
  33. // );
  34. let mut basic_info = pcb.basic_mut();
  35. // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
  36. let old_address_space = basic_info.user_vm();
  37. // 在pcb中原来的用户地址空间
  38. unsafe {
  39. basic_info.set_user_vm(None);
  40. }
  41. // 创建新的地址空间并设置为当前地址空间
  42. let address_space = AddressSpace::new(true).expect("Failed to create new address space");
  43. unsafe {
  44. basic_info.set_user_vm(Some(address_space.clone()));
  45. }
  46. // to avoid deadlock
  47. drop(basic_info);
  48. assert!(
  49. AddressSpace::is_current(&address_space),
  50. "Failed to set address space"
  51. );
  52. // debug!("Switch to new address space");
  53. // 切换到新的用户地址空间
  54. unsafe { address_space.read().user_mapper.utable.make_current() };
  55. drop(old_address_space);
  56. drop(irq_guard);
  57. // debug!("to load binary file");
  58. let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
  59. // 加载可执行文件
  60. let load_result = load_binary_file(&mut param)?;
  61. // debug!("load binary file done");
  62. // debug!("argv: {:?}, envp: {:?}", argv, envp);
  63. param.init_info_mut().args = argv;
  64. param.init_info_mut().envs = envp;
  65. // 把proc_init_info写到用户栈上
  66. let mut ustack_message = unsafe {
  67. address_space
  68. .write()
  69. .user_stack_mut()
  70. .expect("No user stack found")
  71. .clone_info_only()
  72. };
  73. let (user_sp, argv_ptr) = unsafe {
  74. param
  75. .init_info()
  76. .push_at(
  77. // address_space
  78. // .write()
  79. // .user_stack_mut()
  80. // .expect("No user stack found"),
  81. &mut ustack_message,
  82. )
  83. .expect("Failed to push proc_init_info to user stack")
  84. };
  85. address_space.write().user_stack = Some(ustack_message);
  86. // debug!("write proc_init_info to user stack done");
  87. // (兼容旧版libc)把argv的指针写到寄存器内
  88. // TODO: 改写旧版libc,不再需要这个兼容
  89. regs.rdi = param.init_info().args.len() as u64;
  90. regs.rsi = argv_ptr.data() as u64;
  91. // 设置系统调用返回时的寄存器状态
  92. // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。
  93. regs.rsp = user_sp.data() as u64;
  94. regs.rbp = user_sp.data() as u64;
  95. regs.rip = load_result.entry_point().data() as u64;
  96. regs.cs = USER_CS.bits() as u64;
  97. regs.ds = USER_DS.bits() as u64;
  98. regs.ss = USER_DS.bits() as u64;
  99. regs.es = 0;
  100. regs.rflags = 0x200;
  101. regs.rax = 1;
  102. drop(param);
  103. // debug!("regs: {:?}\n", regs);
  104. // crate::debug!(
  105. // "tmp_rs_execve: done, load_result.entry_point()={:?}",
  106. // load_result.entry_point()
  107. // );
  108. return Ok(());
  109. }
  110. /// ## 用于控制和查询与体系结构相关的进程特定选项
  111. pub fn arch_prctl(option: usize, arg2: usize) -> Result<usize, SystemError> {
  112. let pcb = ProcessManager::current_pcb();
  113. if let Err(SystemError::EINVAL) = Self::do_arch_prctl_64(&pcb, option, arg2, true) {
  114. Self::do_arch_prctl_common(option, arg2)?;
  115. }
  116. Ok(0)
  117. }
  118. /// ## 64位下控制fs/gs base寄存器的方法
  119. pub fn do_arch_prctl_64(
  120. pcb: &Arc<ProcessControlBlock>,
  121. option: usize,
  122. arg2: usize,
  123. from_user: bool,
  124. ) -> Result<usize, SystemError> {
  125. let mut arch_info = pcb.arch_info_irqsave();
  126. match option {
  127. ARCH_GET_FS => {
  128. unsafe { arch_info.save_fsbase() };
  129. let mut writer = UserBufferWriter::new(
  130. arg2 as *mut usize,
  131. core::mem::size_of::<usize>(),
  132. from_user,
  133. )?;
  134. writer.copy_one_to_user(&arch_info.fsbase, 0)?;
  135. }
  136. ARCH_GET_GS => {
  137. unsafe { arch_info.save_gsbase() };
  138. let mut writer = UserBufferWriter::new(
  139. arg2 as *mut usize,
  140. core::mem::size_of::<usize>(),
  141. from_user,
  142. )?;
  143. writer.copy_one_to_user(&arch_info.gsbase, 0)?;
  144. }
  145. ARCH_SET_FS => {
  146. arch_info.fsbase = arg2;
  147. // 如果是当前进程则直接写入寄存器
  148. if pcb.pid() == ProcessManager::current_pcb().pid() {
  149. unsafe { arch_info.restore_fsbase() }
  150. }
  151. }
  152. ARCH_SET_GS => {
  153. arch_info.gsbase = arg2;
  154. if pcb.pid() == ProcessManager::current_pcb().pid() {
  155. unsafe { arch_info.restore_gsbase() }
  156. }
  157. }
  158. _ => {
  159. return Err(SystemError::EINVAL);
  160. }
  161. }
  162. Ok(0)
  163. }
  164. #[allow(dead_code)]
  165. pub fn do_arch_prctl_common(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
  166. todo!("do_arch_prctl_common not unimplemented");
  167. }
  168. }
  169. pub const ARCH_SET_GS: usize = 0x1001;
  170. pub const ARCH_SET_FS: usize = 0x1002;
  171. pub const ARCH_GET_FS: usize = 0x1003;
  172. pub const ARCH_GET_GS: usize = 0x1004;