strace: Qstrace controls whether tracing is on
[akaros.git] / kern / arch / x86 / trap64.h
index dc40db1..b3165d5 100644 (file)
@@ -7,48 +7,22 @@
  * and not to be called by the main kernel.  Other functions are part of the
  * kernel-arch interface. */
 
-#ifndef ROS_KERN_ARCH_TRAP64_H
-#define ROS_KERN_ARCH_TRAP64_H
+#pragma once
 
 #ifndef ROS_KERN_ARCH_TRAP_H
 #error "Do not include arch/trap64.h directly."
 #endif
 
+#include <arch/fsgsbase.h>
+
 static inline bool in_kernel(struct hw_trapframe *hw_tf)
 {
        return (hw_tf->tf_cs & ~3) == GD_KT;
 }
 
-static inline void save_kernel_ctx(struct kernel_ctx *ctx)
-{
-       #if 0
-       /* Save the regs and the future esp. */
-       asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/
-                    "pushl %%eax;           " /* temp save eax */
-                    "leal 1f,%%eax;         " /* get future eip */
-                    "movl %%eax,(%1);       " /* store future eip */
-                    "popl %%eax;            " /* restore eax */
-                    "movl %2,%%esp;         " /* move to the beginning of the tf */
-                    "addl $0x20,%%esp;      " /* move to after the push_regs */
-                    "pushal;                " /* save regs */
-                    "addl $0x44,%%esp;      " /* move to esp slot */
-                    "popl %%esp;            " /* restore esp */
-                    "1:                     " /* where this tf will restart */
-                    : 
-                    : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip),
-                      "g"(&ctx->hw_tf)
-                    : "eax", "memory", "cc");
-       #endif
-}
-
-static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
-{
-       return hw_tf->tf_rip;
-}
-
 static inline void x86_advance_ip(struct hw_trapframe *hw_tf, size_t bytes)
 {
-               hw_tf->tf_rip += bytes;
+       hw_tf->tf_rip += bytes;
 }
 
 static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
@@ -60,14 +34,23 @@ static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf)
        hw_tf->tf_rcx = core_id();
 }
 
-/* TODO: use syscall.  all of this sysenter stuff is wrong  */
-static inline void x86_sysenter_init(uintptr_t stacktop)
+#define AKAROS_MSR_STAR (((((uint64_t)GD_UD - 8) | 0x3) << 48) |             \
+                            ((uint64_t)GD_KT << 32))
+#define AKAROS_MSR_LSTAR ((uintptr_t)&sysenter_handler)
+/* Masking all flags.  when we syscall, we'll get rflags = 0 */
+#define AKAROS_MSR_SFMASK (FL_AC | FL_NT | FL_IOPL_MASK | FL_DF | FL_IF | FL_TF)
+
+static inline void x86_sysenter_init(void)
 {
-       //write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
-       //write_msr(MSR_IA32_SYSENTER_EIP, (uintptr_t) &sysenter_handler);
-       asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
+       /* check amd 2:6.1.1 for details.  they have some expectations about the GDT
+        * layout. */
+       write_msr(MSR_STAR, AKAROS_MSR_STAR);
+       write_msr(MSR_LSTAR, AKAROS_MSR_LSTAR);
+       write_msr(MSR_SFMASK, AKAROS_MSR_SFMASK);
+       write_msr(IA32_EFER_MSR, read_msr(IA32_EFER_MSR) | IA32_EFER_SYSCALL);
 }
 
+/* these are used for both sysenter and traps on 32 bit */
 static inline void x86_set_sysenter_stacktop(uintptr_t stacktop)
 {
        asm volatile ("movq %0, %%gs:0" : : "r"(stacktop));
@@ -75,12 +58,22 @@ static inline void x86_set_sysenter_stacktop(uintptr_t stacktop)
 
 static inline long x86_get_sysenter_arg0(struct hw_trapframe *hw_tf)
 {
-       return hw_tf->tf_rax;   // XXX probably wrong
+       return hw_tf->tf_rdi;
 }
 
 static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf)
 {
-       return hw_tf->tf_rsi;   // XXX probably wrong
+       return hw_tf->tf_rsi;
+}
+
+static inline long x86_get_systrap_arg0(struct hw_trapframe *hw_tf)
+{
+       return hw_tf->tf_rdi;
+}
+
+static inline long x86_get_systrap_arg1(struct hw_trapframe *hw_tf)
+{
+       return hw_tf->tf_rsi;
 }
 
 static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss)
@@ -93,4 +86,46 @@ static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top)
        tss->ts_rsp0 = top;
 }
 
-#endif /* ROS_KERN_ARCH_TRAP64_H */
+/* Keep tf_padding0 in sync with trapentry64.S */
+static inline bool x86_hwtf_is_partial(struct hw_trapframe *tf)
+{
+       return tf->tf_padding0 == 1;
+}
+
+static inline bool x86_swtf_is_partial(struct sw_trapframe *tf)
+{
+       return tf->tf_padding0 == 1;
+}
+
+static inline bool x86_vmtf_is_partial(struct vm_trapframe *tf)
+{
+       return tf->tf_flags & VMCTX_FL_PARTIAL ? TRUE : FALSE;
+}
+
+static inline void x86_hwtf_clear_partial(struct hw_trapframe *tf)
+{
+       tf->tf_padding0 = 0;
+}
+
+static inline void x86_swtf_clear_partial(struct sw_trapframe *tf)
+{
+       tf->tf_padding0 = 0;
+}
+
+static inline void x86_vmtf_clear_partial(struct vm_trapframe *tf)
+{
+       tf->tf_flags &= ~VMCTX_FL_PARTIAL;
+}
+
+static inline bool arch_ctx_is_partial(struct user_context *ctx)
+{
+       switch (ctx->type) {
+       case ROS_HW_CTX:
+               return x86_hwtf_is_partial(&ctx->tf.hw_tf);
+       case ROS_SW_CTX:
+               return x86_swtf_is_partial(&ctx->tf.sw_tf);
+       case ROS_VM_CTX:
+               return x86_vmtf_is_partial(&ctx->tf.vm_tf);
+       }
+       return FALSE;
+}