Moves 9ns endian helpers
[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 /* For kernel contexts, when we save/restore/move them around. */
18 struct kernel_ctx {
19         struct sw_trapframe             sw_tf;
20 };
21
22 void print_swtrapframe(struct sw_trapframe *sw_tf);
23
24 static inline bool in_kernel(struct hw_trapframe *hw_tf)
25 {
26         return (hw_tf->tf_cs & ~3) == GD_KT;
27 }
28
29 static inline uintptr_t get_hwtf_pc(struct hw_trapframe *hw_tf)
30 {
31         return hw_tf->tf_rip;
32 }
33
34 static inline uintptr_t get_hwtf_fp(struct hw_trapframe *hw_tf)
35 {
36         return hw_tf->tf_rbp;
37 }
38
39 /* Using SW contexts for now, for x86_64 */
40 static inline void save_kernel_ctx(struct kernel_ctx *ctx)
41 {
42         long dummy;
43         /* not bothering with the FP fields */
44         asm volatile("mov %%rsp, 0x48(%0);   " /* save rsp in its slot*/
45                      "leaq 1f, %%rax;        " /* get future rip */
46                      "mov %%rax, 0x40(%0);   " /* save rip in its slot*/
47                      "mov %%r15, 0x38(%0);   "
48                      "mov %%r14, 0x30(%0);   "
49                      "mov %%r13, 0x28(%0);   "
50                      "mov %%r12, 0x20(%0);   "
51                      "mov %%rbp, 0x18(%0);   "
52                      "mov %%rbx, 0x10(%0);   "
53                      "1:                     " /* where this tf will restart */
54                                  : "=D"(dummy) /* force rdi clobber */
55                                  : "D"(&ctx->sw_tf)
56                      : "rax", "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11",
57                        "memory", "cc");
58 }
59
60 static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
61 {
62         return hw_tf->tf_rip;
63 }
64
65 static inline void x86_advance_ip(struct hw_trapframe *hw_tf, size_t bytes)
66 {
67         hw_tf->tf_rip += bytes;
68 }
69
70 static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
71 {
72         uint64_t tsc_time = read_tsc();
73         hw_tf->tf_rip += 3;
74         hw_tf->tf_rax = tsc_time & 0xffffffff;
75         hw_tf->tf_rdx = tsc_time >> 32;
76         hw_tf->tf_rcx = core_id();
77 }
78
79 static inline void x86_sysenter_init(uintptr_t stacktop)
80 {
81         /* check amd 2:6.1.1 for details.  they have some expectations about the GDT
82          * layout. */
83         write_msr(MSR_STAR, ((((uint64_t)GD_UD - 8) | 0x3) << 48) |
84                             ((uint64_t)GD_KT << 32));
85         write_msr(MSR_LSTAR, (uintptr_t)&sysenter_handler);
86         /* Masking all flags.  when we syscall, we'll get rflags = 0 */
87         write_msr(MSR_SFMASK, 0xffffffff);
88         write_msr(IA32_EFER_MSR, read_msr(IA32_EFER_MSR) | IA32_EFER_SYSCALL);
89         asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
90 }
91
92 /* these are used for both sysenter and traps on 32 bit */
93 static inline void x86_set_sysenter_stacktop(uintptr_t stacktop)
94 {
95         asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
96 }
97
98 static inline long x86_get_sysenter_arg0(struct hw_trapframe *hw_tf)
99 {
100         return hw_tf->tf_rdi;
101 }
102
103 static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
104 {
105         return hw_tf->tf_rsi;
106 }
107
108 static inline long x86_get_systrap_arg0(struct hw_trapframe *hw_tf)
109 {
110         return hw_tf->tf_rdi;
111 }
112
113 static inline long x86_get_systrap_arg1(struct hw_trapframe *hw_tf)
114 {
115         return hw_tf->tf_rsi;
116 }
117
118 static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
119 {
120         return tss->ts_rsp0;
121 }
122
123 static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
124 {
125         tss->ts_rsp0 = top;
126 }
127
128 #endif /* ROS_KERN_ARCH_TRAP64_H */