xref: /DragonOS/kernel/src/arch/x86_64/syscall/mod.rs (revision 91e9d4ab55ef960f57a1b6287bc523ca4341f67a)
1 use core::ffi::c_void;
2 
3 use crate::{
4     arch::{
5         ipc::signal::X86_64SignalArch,
6         syscall::nr::{SYS_ARCH_PRCTL, SYS_RT_SIGRETURN},
7         CurrentIrqArch,
8     },
9     exception::InterruptArch,
10     include::bindings::bindings::set_system_trap_gate,
11     ipc::signal_types::SignalArch,
12     libs::align::SafeForZero,
13     mm::VirtAddr,
14     process::ProcessManager,
15     syscall::{Syscall, SYS_SCHED},
16 };
17 use alloc::string::String;
18 use system_error::SystemError;
19 
20 use super::{interrupt::TrapFrame, mm::barrier::mfence};
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_enable();
73         }
74     }
75 
76     let args = [
77         frame.rdi as usize,
78         frame.rsi as usize,
79         frame.rdx as usize,
80         frame.r10 as usize,
81         frame.r8 as usize,
82         frame.r9 as usize,
83     ];
84     mfence();
85     let pid = ProcessManager::current_pcb().pid();
86     let show = false;
87     // let show = if syscall_num != SYS_SCHED && pid.data() > 3 {
88     //     true
89     // } else {
90     //     false
91     // };
92 
93     if show {
94         crate::kdebug!("syscall: pid: {:?}, num={:?}\n", pid, syscall_num);
95     }
96 
97     // Arch specific syscall
98     match syscall_num {
99         SYS_RT_SIGRETURN => {
100             syscall_return!(
101                 X86_64SignalArch::sys_rt_sigreturn(frame) as usize,
102                 frame,
103                 show
104             );
105         }
106         SYS_ARCH_PRCTL => {
107             syscall_return!(
108                 Syscall::arch_prctl(args[0], args[1])
109                     .unwrap_or_else(|e| e.to_posix_errno() as usize),
110                 frame,
111                 show
112             );
113         }
114         _ => {}
115     }
116     syscall_return!(
117         Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize)
118             as u64,
119         frame,
120         show
121     );
122 }
123 
124 /// 系统调用初始化
125 pub fn arch_syscall_init() -> Result<(), SystemError> {
126     // kinfo!("arch_syscall_init\n");
127     unsafe { set_system_trap_gate(0x80, 0, syscall_int as *mut c_void) }; // 系统调用门
128     unsafe { init_syscall_64() };
129     return Ok(());
130 }
131 
132 /// 执行第一个用户进程的函数(只应该被调用一次)
133 ///
134 /// 当进程管理重构完成后,这个函数应该被删除。调整为别的函数。
135 #[no_mangle]
136 pub extern "C" fn rs_exec_init_process(frame: &mut TrapFrame) -> usize {
137     let path = String::from("/bin/shell.elf");
138     let argv = vec![String::from("/bin/shell.elf")];
139     let envp = vec![String::from("PATH=/bin")];
140     let r = Syscall::do_execve(path, argv, envp, frame);
141     // kdebug!("rs_exec_init_process: r: {:?}\n", r);
142     return r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize);
143 }
144 
145 /// syscall指令初始化函数
146 pub(super) unsafe fn init_syscall_64() {
147     let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER);
148     efer |= 0x1;
149     x86::msr::wrmsr(x86::msr::IA32_EFER, efer);
150 
151     let syscall_base = (1 as u16) << 3;
152     let sysret_base = ((4 as u16) << 3) | 3;
153     let high = (u32::from(sysret_base) << 16) | u32::from(syscall_base);
154     // 初始化STAR寄存器
155     x86::msr::wrmsr(x86::msr::IA32_STAR, u64::from(high) << 32);
156 
157     // 初始化LSTAR,该寄存器存储syscall指令入口
158     x86::msr::wrmsr(x86::msr::IA32_LSTAR, syscall_64 as u64);
159     x86::msr::wrmsr(x86::msr::IA32_FMASK, 0xfffffffe);
160 }
161