x86_64: Syscall/Sysenter/int 0x80 (XCC)
[akaros.git] / kern / arch / x86 / trap64.h
1 /* Copyright (c) 2009-13 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * x86 trap.h bit-specific functions.  This is included by trap.h, do not
6  * include it directly.  Any function beginning with x86_ is internal to x86,
7  * and not to be called by the main kernel.  Other functions are part of the
8  * kernel-arch interface. */
9
10 #ifndef ROS_KERN_ARCH_TRAP64_H
11 #define ROS_KERN_ARCH_TRAP64_H
12
13 #ifndef ROS_KERN_ARCH_TRAP_H
14 #error "Do not include arch/trap64.h directly."
15 #endif
16
17 void print_swtrapframe(struct sw_trapframe *sw_tf);
18
19 static inline bool in_kernel(struct hw_trapframe *hw_tf)
20 {
21         return (hw_tf->tf_cs & ~3) == GD_KT;
22 }
23
24 static inline void save_kernel_ctx(struct kernel_ctx *ctx)
25 {
26         #if 0
27         /* Save the regs and the future esp. */
28         asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/
29                      "pushl %%eax;           " /* temp save eax */
30                      "leal 1f,%%eax;         " /* get future eip */
31                      "movl %%eax,(%1);       " /* store future eip */
32                      "popl %%eax;            " /* restore eax */
33                      "movl %2,%%esp;         " /* move to the beginning of the tf */
34                      "addl $0x20,%%esp;      " /* move to after the push_regs */
35                      "pushal;                " /* save regs */
36                      "addl $0x44,%%esp;      " /* move to esp slot */
37                      "popl %%esp;            " /* restore esp */
38                      "1:                     " /* where this tf will restart */
39                      : 
40                      : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip),
41                        "g"(&ctx->hw_tf)
42                      : "eax", "memory", "cc");
43         #endif
44 }
45
46 static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
47 {
48         return hw_tf->tf_rip;
49 }
50
51 static inline void x86_advance_ip(struct hw_trapframe *hw_tf, size_t bytes)
52 {
53                 hw_tf->tf_rip += bytes;
54 }
55
56 static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
57 {
58         uint64_t tsc_time = read_tsc();
59         hw_tf->tf_rip += 3;
60         hw_tf->tf_rax = tsc_time & 0xffffffff;
61         hw_tf->tf_rdx = tsc_time >> 32;
62         hw_tf->tf_rcx = core_id();
63 }
64
65 static inline void x86_sysenter_init(uintptr_t stacktop)
66 {
67         /* check amd 2:6.1.1 for details.  they have some expectations about the GDT
68          * layout. */
69         write_msr(MSR_STAR, ((((uint64_t)GD_UD - 8) | 0x3) << 48) |
70                             ((uint64_t)GD_KT << 32));
71         write_msr(MSR_LSTAR, (uintptr_t)&sysenter_handler);
72         /* Masking all flags.  when we syscall, we'll get rflags = 0 */
73         write_msr(MSR_SFMASK, 0xffffffff);
74         write_msr(IA32_EFER_MSR, read_msr(IA32_EFER_MSR) | IA32_EFER_SYSCALL);
75         asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
76 }
77
78 /* these are used for both sysenter and traps on 32 bit */
79 static inline void x86_set_sysenter_stacktop(uintptr_t stacktop)
80 {
81         asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
82 }
83
84 static inline long x86_get_sysenter_arg0(struct hw_trapframe *hw_tf)
85 {
86         return hw_tf->tf_rdi;
87 }
88
89 static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
90 {
91         return hw_tf->tf_rsi;
92 }
93
94 static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
95 {
96         return tss->ts_rsp0;
97 }
98
99 static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
100 {
101         tss->ts_rsp0 = top;
102 }
103
104 #endif /* ROS_KERN_ARCH_TRAP64_H */