e56ed115e334253d13f0bc7c138453401b7affbe
[akaros.git] / kern / arch / x86 / trap32.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_TRAP32_H
11 #define ROS_KERN_ARCH_TRAP32_H
12
13 #ifndef ROS_KERN_ARCH_TRAP_H
14 #error "Do not include arch/trap32.h directly."
15 #endif
16
17 /* For kernel contexts, when we save/restore/move them around. */
18 struct kernel_ctx {
19         struct hw_trapframe             hw_tf;
20 };
21
22 static inline bool in_kernel(struct hw_trapframe *hw_tf)
23 {
24         return (hw_tf->tf_cs & ~3) == GD_KT;
25 }
26
27 static inline void save_kernel_ctx(struct kernel_ctx *ctx)
28 {
29         /* Save the regs and the future esp. */
30         /* Careful when updating; %0, %1, and %2 are not listed as clobbers */
31         asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/
32                      "pushl %%eax;           " /* temp save eax */
33                      "leal 1f,%%eax;         " /* get future eip */
34                      "movl %%eax,(%1);       " /* store future eip */
35                      "popl %%eax;            " /* restore eax */
36                      "movl %2,%%esp;         " /* move to the beginning of the tf */
37                      "addl $0x20,%%esp;      " /* move to after the push_regs */
38                      "pushal;                " /* save regs */
39                      "addl $0x44,%%esp;      " /* move to esp slot */
40                      "popl %%esp;            " /* restore esp */
41                      "1:                     " /* where this tf will restart */
42                      : 
43                      : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip),
44                        "g"(&ctx->hw_tf)
45                      : "eax", "memory", "cc");
46 }
47
48 static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
49 {
50         return hw_tf->tf_eip;
51 }
52
53 static inline void x86_advance_ip(struct hw_trapframe *hw_tf, size_t bytes)
54 {
55         hw_tf->tf_eip += bytes;
56 }
57
58 static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
59 {
60         uint64_t tsc_time = read_tsc();
61         hw_tf->tf_eip += 3;
62         hw_tf->tf_regs.reg_eax = tsc_time & 0xffffffff;
63         hw_tf->tf_regs.reg_edx = tsc_time >> 32;
64         hw_tf->tf_regs.reg_ecx = core_id();
65 }
66
67 static inline void x86_sysenter_init(uintptr_t stacktop)
68 {
69         write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
70         write_msr(MSR_IA32_SYSENTER_ESP, stacktop);
71         write_msr(MSR_IA32_SYSENTER_EIP, (uintptr_t) &sysenter_handler);
72 }
73
74 static inline void x86_set_sysenter_stacktop(uintptr_t stacktop)
75 {
76         write_msr(MSR_IA32_SYSENTER_ESP, stacktop);
77 }
78
79 static inline long x86_get_sysenter_arg0(struct hw_trapframe *hw_tf)
80 {
81         return hw_tf->tf_regs.reg_eax;
82 }
83
84 static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
85 {
86         return hw_tf->tf_regs.reg_esi;
87 }
88
89 static inline long x86_get_systrap_arg0(struct hw_trapframe *hw_tf)
90 {
91         return hw_tf->tf_regs.reg_eax;
92 }
93
94 static inline long x86_get_systrap_arg1(struct hw_trapframe *hw_tf)
95 {
96         return hw_tf->tf_regs.reg_edx;
97 }
98
99 static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
100 {
101         return tss->ts_esp0;
102 }
103
104 static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
105 {
106         tss->ts_esp0 = top;
107         tss->ts_ss0 = GD_KD;
108 }
109
110 static inline uintptr_t x86_get_hwtf_pc(struct hw_trapframe *hw_tf)
111 {
112         return hw_tf->tf_eip;
113 }
114
115 static inline uintptr_t x86_get_hwtf_fp(struct hw_trapframe *hw_tf)
116 {
117         return hw_tf->tf_regs.reg_ebp;
118 }
119
120 #endif /* ROS_KERN_ARCH_TRAP32_H */