good_os_framework/user/
syscall.rs1use core::arch::asm;
2use spin::Mutex;
3use x86_64::registers::model_specific::{Efer, EferFlags};
4use x86_64::registers::model_specific::{LStar, SFMask, Star};
5use x86_64::registers::rflags::RFlags;
6use x86_64::VirtAddr;
7
8use crate::arch::gdt::Selectors;
9
10pub fn init() {
11 let handler_addr = syscall_handler as *const () as u64;
12
13 SFMask::write(RFlags::INTERRUPT_FLAG);
14 LStar::write(VirtAddr::new(handler_addr as u64));
15
16 let (code_selector, data_selector) = Selectors::get_kernel_segments();
17 let (user_code_selector, user_data_selector) = Selectors::get_user_segments();
18
19 Star::write(
20 user_code_selector,
21 user_data_selector,
22 code_selector,
23 data_selector,
24 )
25 .unwrap();
26
27 unsafe {
28 Efer::write(Efer::read() | EferFlags::SYSTEM_CALL_EXTENSIONS);
29 }
30}
31
32#[naked]
33extern "C" fn syscall_handler() {
34 unsafe {
35 asm!(
36 "push rcx",
37 "push r11",
38 "push rbp",
39 "push rbx",
40 "push r12",
41 "push r13",
42 "push r14",
43 "push r15",
44
45 "mov rcx, r10",
47 "call {syscall_handle_fn}",
48
49 "pop r15",
50 "pop r14",
51 "pop r13",
52 "pop r12",
53 "pop rbx",
54 "pop rbp",
55 "pop r11",
56 "pop rcx",
57 "sysretq",
58 syscall_handle_fn = sym syscall_handle_fn,
59 options(noreturn)
60 );
61 }
62}
63
64#[allow(unused_variables)]
65pub extern "C" fn syscall_handle_fn(
66 arg1: usize,
67 arg2: usize,
68 arg3: usize,
69 arg4: usize,
70 arg5: usize,
71 arg6: usize,
72) -> usize {
73 let syscall_number_raw: usize;
74 unsafe { asm!("mov {0}, rax", out(reg) syscall_number_raw) };
75
76 SYSCALL_HANDLER.lock()(syscall_number_raw, arg1, arg2, arg3, arg4, arg5, arg6)
77}
78
79fn tmp_syscall_handler(
80 _idx: usize,
81 _arg1: usize,
82 _arg2: usize,
83 _arg3: usize,
84 _arg4: usize,
85 _arg5: usize,
86 _arg6: usize,
87) -> usize {
88 0
89}
90
91pub type SyscallHandlerFn = fn(
93 idx: usize,
94 arg1: usize,
95 arg2: usize,
96 arg3: usize,
97 arg4: usize,
98 arg5: usize,
99 arg6: usize,
100) -> usize;
101
102static SYSCALL_HANDLER: Mutex<SyscallHandlerFn> = Mutex::new(tmp_syscall_handler);
103
104pub fn regist_syscall_handler(handler: SyscallHandlerFn) {
106 *SYSCALL_HANDLER.lock() = handler;
107}