1 use crate::{ 2 arch::{ 3 ipc::signal::X86_64SignalArch, 4 syscall::nr::{SYS_ARCH_PRCTL, SYS_RT_SIGRETURN}, 5 CurrentIrqArch, 6 }, 7 exception::InterruptArch, 8 ipc::signal_types::SignalArch, 9 libs::align::SafeForZero, 10 mm::VirtAddr, 11 process::ProcessManager, 12 syscall::{Syscall, SYS_SCHED}, 13 }; 14 use alloc::string::String; 15 use system_error::SystemError; 16 17 use super::{ 18 interrupt::{entry::set_system_trap_gate, TrapFrame}, 19 mm::barrier::mfence, 20 }; 21 22 pub mod nr; 23 24 /// ### 存储PCB系统调用栈以及在syscall过程中暂存用户态rsp的结构体 25 /// 26 /// 在syscall指令中将会从该结构体中读取系统调用栈和暂存rsp, 27 /// 使用`gsbase`寄存器实现,后续如果需要使用gsbase寄存器,需要相应设置正确的偏移量 28 #[repr(C)] 29 #[derive(Debug, Clone)] 30 pub(super) struct X86_64GSData { 31 pub(super) kaddr: VirtAddr, 32 pub(super) uaddr: VirtAddr, 33 } 34 35 impl X86_64GSData { 36 /// ### 设置系统调用栈,将会在下一个调度后写入KernelGsbase 37 pub fn set_kstack(&mut self, kstack: VirtAddr) { 38 self.kaddr = kstack; 39 } 40 } 41 42 unsafe impl SafeForZero for X86_64GSData {} 43 44 extern "C" { 45 fn syscall_int(); 46 fn syscall_64(); 47 } 48 49 macro_rules! syscall_return { 50 ($val:expr, $regs:expr, $show:expr) => {{ 51 let ret = $val; 52 $regs.rax = ret as u64; 53 54 if $show { 55 let pid = ProcessManager::current_pcb().pid(); 56 crate::kdebug!("syscall return:pid={:?},ret= {:?}\n", pid, ret as isize); 57 } 58 59 unsafe { 60 CurrentIrqArch::interrupt_disable(); 61 } 62 return; 63 }}; 64 } 65 66 #[no_mangle] 67 pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) { 68 let syscall_num = frame.rax as usize; 69 // 防止sys_sched由于超时无法退出导致的死锁 70 if syscall_num == SYS_SCHED { 71 unsafe { 72 CurrentIrqArch::interrupt_disable(); 73 } 74 } else { 75 unsafe { 76 CurrentIrqArch::interrupt_enable(); 77 } 78 } 79 80 let args = [ 81 frame.rdi as usize, 82 frame.rsi as usize, 83 frame.rdx as usize, 84 frame.r10 as usize, 85 frame.r8 as usize, 86 frame.r9 as usize, 87 ]; 88 mfence(); 89 let pid = ProcessManager::current_pcb().pid(); 90 let show = false; 91 // let show = if syscall_num != SYS_SCHED && pid.data() >= 7 { 92 // true 93 // } else { 94 // false 95 // }; 96 97 if show { 98 crate::kdebug!("syscall: pid: {:?}, num={:?}\n", pid, syscall_num); 99 } 100 101 // Arch specific syscall 102 match syscall_num { 103 SYS_RT_SIGRETURN => { 104 syscall_return!( 105 X86_64SignalArch::sys_rt_sigreturn(frame) as usize, 106 frame, 107 show 108 ); 109 } 110 SYS_ARCH_PRCTL => { 111 syscall_return!( 112 Syscall::arch_prctl(args[0], args[1]) 113 .unwrap_or_else(|e| e.to_posix_errno() as usize), 114 frame, 115 show 116 ); 117 } 118 _ => {} 119 } 120 syscall_return!( 121 Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize) 122 as u64, 123 frame, 124 show 125 ); 126 } 127 128 /// 系统调用初始化 129 pub fn arch_syscall_init() -> Result<(), SystemError> { 130 // kinfo!("arch_syscall_init\n"); 131 unsafe { set_system_trap_gate(0x80, 0, VirtAddr::new(syscall_int as usize)) }; // 系统调用门 132 unsafe { init_syscall_64() }; 133 return Ok(()); 134 } 135 136 /// 执行第一个用户进程的函数(只应该被调用一次) 137 /// 138 /// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。 139 #[no_mangle] 140 pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> usize { 141 let path = String::from("/bin/shell.elf"); 142 let argv = vec![String::from("/bin/shell.elf")]; 143 let envp = vec![String::from("PATH=/bin")]; 144 let r = Syscall::do_execve(path, argv, envp, frame); 145 // kdebug!("rs_exec_init_process: r: {:?}\n", r); 146 return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize); 147 } 148 149 /// syscall指令初始化函数 150 pub(super) unsafe fn init_syscall_64() { 151 let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER); 152 efer |= 0x1; 153 x86::msr::wrmsr(x86::msr::IA32_EFER, efer); 154 155 let syscall_base = (1_u16) << 3; 156 let sysret_base = ((4_u16) << 3) | 3; 157 let high = (u32::from(sysret_base) << 16) | u32::from(syscall_base); 158 // 初始化STAR寄存器 159 x86::msr::wrmsr(x86::msr::IA32_STAR, u64::from(high) << 32); 160 161 // 初始化LSTAR,该寄存器存储syscall指令入口 162 x86::msr::wrmsr(x86::msr::IA32_LSTAR, syscall_64 as usize as u64); 163 x86::msr::wrmsr(x86::msr::IA32_FMASK, 0xfffffffe); 164 } 165