axhal/arch/x86_64/
syscall.rs1use x86_64::addr::VirtAddr;
2use x86_64::registers::model_specific::{Efer, EferFlags, KernelGsBase, LStar, SFMask, Star};
3use x86_64::registers::rflags::RFlags;
4use x86_64::structures::tss::TaskStateSegment;
5
6use super::{GdtStruct, TrapFrame};
7
8#[unsafe(no_mangle)]
9#[percpu::def_percpu]
10static USER_RSP_OFFSET: usize = 0;
11
12core::arch::global_asm!(
13 include_str!("syscall.S"),
14 tss_rsp0_offset = const core::mem::offset_of!(TaskStateSegment, privilege_stack_table),
15 ucode64 = const GdtStruct::UCODE64_SELECTOR.0,
16);
17
18pub(super) fn handle_syscall(tf: &mut TrapFrame) {
19 tf.rax = crate::trap::handle_syscall(tf, tf.rax as usize) as u64;
20}
21
22#[unsafe(no_mangle)]
23fn x86_syscall_handler(tf: &mut TrapFrame) {
24 super::tls::switch_to_kernel_fs_base(tf);
25 #[cfg(target_os = "none")]
26 super::trap::unmask_irqs(tf);
27 handle_syscall(tf);
28 crate::trap::post_trap_callback(tf, true);
29 super::tls::switch_to_user_fs_base(tf);
30 #[cfg(target_os = "none")]
31 super::trap::mask_irqs();
32}
33
34pub fn init_syscall() {
36 unsafe extern "C" {
37 fn syscall_entry();
38 }
39 unsafe {
40 LStar::write(VirtAddr::new(syscall_entry as usize as _));
41 Star::write(
42 GdtStruct::UCODE64_SELECTOR,
43 GdtStruct::UDATA_SELECTOR,
44 GdtStruct::KCODE64_SELECTOR,
45 GdtStruct::KDATA_SELECTOR,
46 )
47 .unwrap();
48 SFMask::write(
49 RFlags::TRAP_FLAG
50 | RFlags::INTERRUPT_FLAG
51 | RFlags::DIRECTION_FLAG
52 | RFlags::IOPL_LOW
53 | RFlags::IOPL_HIGH
54 | RFlags::NESTED_TASK
55 | RFlags::ALIGNMENT_CHECK,
56 ); Efer::update(|efer| *efer |= EferFlags::SYSTEM_CALL_EXTENSIONS);
58 KernelGsBase::write(VirtAddr::new(0));
59 }
60}