syscall.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. use alloc::{ffi::CString, string::String, vec::Vec};
  2. use riscv::register::sstatus::{FS, SPP};
  3. use system_error::SystemError;
  4. use crate::{
  5. arch::{interrupt::TrapFrame, CurrentIrqArch},
  6. exception::InterruptArch,
  7. mm::ucontext::AddressSpace,
  8. process::{
  9. exec::{load_binary_file, ExecParam, ExecParamFlags},
  10. ProcessManager,
  11. },
  12. syscall::Syscall,
  13. };
  14. impl Syscall {
  15. pub fn do_execve(
  16. path: String,
  17. argv: Vec<CString>,
  18. envp: Vec<CString>,
  19. regs: &mut TrapFrame,
  20. ) -> Result<(), SystemError> {
  21. // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。
  22. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  23. let pcb = ProcessManager::current_pcb();
  24. // crate::debug!(
  25. // "pid: {:?} do_execve: path: {:?}, argv: {:?}, envp: {:?}\n",
  26. // pcb.pid(),
  27. // path,
  28. // argv,
  29. // envp
  30. // );
  31. let mut basic_info = pcb.basic_mut();
  32. // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free)
  33. let old_address_space = basic_info.user_vm();
  34. // 在pcb中原来的用户地址空间
  35. unsafe {
  36. basic_info.set_user_vm(None);
  37. }
  38. // 创建新的地址空间并设置为当前地址空间
  39. let address_space = AddressSpace::new(true).expect("Failed to create new address space");
  40. unsafe {
  41. basic_info.set_user_vm(Some(address_space.clone()));
  42. }
  43. // to avoid deadlock
  44. drop(basic_info);
  45. assert!(
  46. AddressSpace::is_current(&address_space),
  47. "Failed to set address space"
  48. );
  49. // debug!("Switch to new address space");
  50. // 切换到新的用户地址空间
  51. unsafe { address_space.read().user_mapper.utable.make_current() };
  52. drop(old_address_space);
  53. drop(irq_guard);
  54. // debug!("to load binary file");
  55. let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
  56. // 加载可执行文件
  57. let load_result = load_binary_file(&mut param)?;
  58. // debug!("load binary file done");
  59. // debug!("argv: {:?}, envp: {:?}", argv, envp);
  60. param.init_info_mut().args = argv;
  61. param.init_info_mut().envs = envp;
  62. // 把proc_init_info写到用户栈上
  63. let mut ustack_message = unsafe {
  64. address_space
  65. .write()
  66. .user_stack_mut()
  67. .expect("No user stack found")
  68. .clone_info_only()
  69. };
  70. let (user_sp, argv_ptr) = unsafe {
  71. param
  72. .init_info_mut()
  73. .push_at(&mut ustack_message)
  74. .expect("Failed to push proc_init_info to user stack")
  75. };
  76. address_space.write().user_stack = Some(ustack_message);
  77. // debug!("write proc_init_info to user stack done");
  78. regs.a0 = param.init_info().args.len();
  79. regs.a1 = argv_ptr.data();
  80. // 设置系统调用返回时的寄存器状态
  81. regs.sp = user_sp.data();
  82. regs.epc = load_result.entry_point().data();
  83. regs.status.update_spp(SPP::User);
  84. regs.status.update_fs(FS::Clean);
  85. regs.status.update_sum(true);
  86. drop(param);
  87. return Ok(());
  88. }
  89. /// ## 用于控制和查询与体系结构相关的进程特定选项
  90. #[allow(dead_code)]
  91. pub fn arch_prctl(_option: usize, _arg2: usize) -> Result<usize, SystemError> {
  92. unimplemented!("Syscall::arch_prctl")
  93. }
  94. }