xref: /DragonOS/kernel/src/arch/x86_64/syscall/mod.rs (revision 7401bec5e3c42015399a46e29c370abe7c7388b5)
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 system_error::SystemError;
15 
16 use super::{
17     interrupt::{entry::set_system_trap_gate, TrapFrame},
18     mm::barrier::mfence,
19 };
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_disable();
72         }
73     } else {
74         unsafe {
75             CurrentIrqArch::interrupt_enable();
76         }
77     }
78 
79     let args = [
80         frame.rdi as usize,
81         frame.rsi as usize,
82         frame.rdx as usize,
83         frame.r10 as usize,
84         frame.r8 as usize,
85         frame.r9 as usize,
86     ];
87     mfence();
88     let pid = ProcessManager::current_pcb().pid();
89     let show = false;
90     // let show = if syscall_num != SYS_SCHED && pid.data() >= 7 {
91     //     true
92     // } else {
93     //     false
94     // };
95 
96     if show {
97         crate::kdebug!("syscall: pid: {:?}, num={:?}\n", pid, syscall_num);
98     }
99 
100     // Arch specific syscall
101     match syscall_num {
102         SYS_RT_SIGRETURN => {
103             syscall_return!(
104                 X86_64SignalArch::sys_rt_sigreturn(frame) as usize,
105                 frame,
106                 show
107             );
108         }
109         SYS_ARCH_PRCTL => {
110             syscall_return!(
111                 Syscall::arch_prctl(args[0], args[1])
112                     .unwrap_or_else(|e| e.to_posix_errno() as usize),
113                 frame,
114                 show
115             );
116         }
117         _ => {}
118     }
119     syscall_return!(
120         Syscall::handle(syscall_num, &args, frame).unwrap_or_else(|e| e.to_posix_errno() as usize)
121             as u64,
122         frame,
123         show
124     );
125 }
126 
127 /// 系统调用初始化
128 pub fn arch_syscall_init() -> Result<(), SystemError> {
129     // kinfo!("arch_syscall_init\n");
130     unsafe { set_system_trap_gate(0x80, 0, VirtAddr::new(syscall_int as usize)) }; // 系统调用门
131     unsafe { init_syscall_64() };
132     return Ok(());
133 }
134 
135 /// syscall指令初始化函数
136 pub(super) unsafe fn init_syscall_64() {
137     let mut efer = x86::msr::rdmsr(x86::msr::IA32_EFER);
138     efer |= 0x1;
139     x86::msr::wrmsr(x86::msr::IA32_EFER, efer);
140 
141     let syscall_base = (1_u16) << 3;
142     let sysret_base = ((4_u16) << 3) | 3;
143     let high = (u32::from(sysret_base) << 16) | u32::from(syscall_base);
144     // 初始化STAR寄存器
145     x86::msr::wrmsr(x86::msr::IA32_STAR, u64::from(high) << 32);
146 
147     // 初始化LSTAR,该寄存器存储syscall指令入口
148     x86::msr::wrmsr(x86::msr::IA32_LSTAR, syscall_64 as usize as u64);
149     x86::msr::wrmsr(x86::msr::IA32_FMASK, 0xfffffffe);
150 }
151