xref: /DragonOS/kernel/src/arch/x86_64/syscall/mod.rs (revision dfe53cf087ef4c7b6db63d992906b062dc63e93f)
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() > 3 {
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