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