2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
3 * Distributed under the terms of the MIT License.
7 #include "x86_syscalls.h"
9 #include <KernelExport.h>
15 // SYSCALL handler (in interrupts.S).
16 extern "C" void x86_64_syscall_entry(void);
20 init_syscall_registers(void* dummy
, int cpuNum
)
22 // Enable SYSCALL (EFER.SCE = 1).
23 x86_write_msr(IA32_MSR_EFER
, x86_read_msr(IA32_MSR_EFER
)
24 | IA32_MSR_EFER_SYSCALL
);
26 // Flags to clear upon entry. Want interrupts disabled and the direction
28 x86_write_msr(IA32_MSR_FMASK
, X86_EFLAGS_INTERRUPT
| X86_EFLAGS_DIRECTION
);
30 // Entry point address.
31 x86_write_msr(IA32_MSR_LSTAR
, (addr_t
)x86_64_syscall_entry
);
33 // Segments that will be set upon entry and return. This is very strange
34 // and requires a specific ordering of segments in the GDT. Upon entry:
35 // - CS is set to IA32_STAR[47:32]
36 // - SS is set to IA32_STAR[47:32] + 8
38 // - CS is set to IA32_STAR[63:48] + 16
39 // - SS is set to IA32_STAR[63:48] + 8
41 // - Entry CS = KERNEL_CODE_SELECTOR
42 // - Entry SS = KERNEL_CODE_SELECTOR + 8 = KERNEL_DATA_SELECTOR
43 // - Return CS = KERNEL_DATA_SELECTOR + 16 = USER_CODE_SELECTOR
44 // - Return SS = KERNEL_DATA_SELECTOR + 8 = USER_DATA_SLECTORG
45 x86_write_msr(IA32_MSR_STAR
, ((uint64
)(KERNEL_DATA_SELECTOR
| 3) << 48)
46 | ((uint64
)KERNEL_CODE_SELECTOR
<< 32));
54 x86_initialize_syscall(void)
56 // SYSCALL/SYSRET are always available on x86_64 so we just use them, no
57 // need to use the commpage. Tell all CPUs to initialize the SYSCALL MSRs.
58 call_all_cpus_sync(&init_syscall_registers
, NULL
);