x86_64: TLS FS base changing 'fast call' (XCC)
[akaros.git] / kern / arch / x86 / ros / syscall64.h
1 #ifndef ROS_INC_ARCH_SYSCALL64_H
2 #define ROS_INC_ARCH_SYSCALL64_H
3
4 #ifndef ROS_INC_ARCH_SYSCALL_H
5 #error "Do not include include ros/arch/syscall64.h directly"
6 #endif
7
8 #define T_SYSCALL       0x80
9
10 #ifndef ROS_KERNEL
11
12 #include <sys/types.h>
13 #include <stdint.h>
14 #include <ros/common.h>
15 #include <ros/arch/mmu.h>
16 #include <assert.h>
17
18 static inline intreg_t __syscall_sysenter(uintreg_t a0, uintreg_t a1)
19 {
20         intreg_t ret = 0;
21         /* we're calling using the amd function call abi.  this asm and the kernel
22          * will save the callee-saved state.  We'll use the clobber list to force
23          * the compiler to save caller-saved state.  As with uthread code, you need
24          * to make sure you have one ABI-compliant, non-inlined function call
25          * between any floating point ops and this.
26          *
27          * Note that syscall doesn't save the stack pointer - using rdx for that.
28          * The kernel will restore it for us. */
29         asm volatile ("movq %%rsp, %%rdx;       "
30                       "syscall;                 "
31                       : "=a" (ret)
32                       : "D" (a0),
33                         "S" (a1)
34                       : "cc", "memory", "rcx", "rdx", "r8", "r9", "r10", "r11");
35         return ret;
36 }
37
38 static inline intreg_t __syscall_trap(uintreg_t a0, uintreg_t a1)
39 {
40         intreg_t ret;
41         /* If you change this, change pop_user_ctx() */
42         asm volatile("int %1"
43                      : "=a" (ret)
44                      : "i" (T_SYSCALL),
45                        "D" (a0),
46                        "S" (a1)
47                      : "cc", "memory");
48         return ret;
49 }
50
51 /* The kernel has a fast path for setting the fs base, used for TLS changes on
52  * machines that can't do it from user space.  The magic value for rdi (D) is a
53  * non-canonical address, which should never be a legitamate syscall. */
54 static inline void __fastcall_setfsbase(uintptr_t fsbase)
55 {
56         asm volatile ("syscall" : : "D"(FASTCALL_SETFSBASE), "S"(fsbase)
57                                 : "rax", "r11", "rcx", "rdx", "memory");
58 }
59
60 #endif
61
62 #endif /* ROS_INC_ARCH_SYSCALL64_H */