x86_64: save/pop kernel contexts
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 9 Jul 2013 23:08:15 +0000 (16:08 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Jul 2013 02:30:02 +0000 (19:30 -0700)
Kernel contexts are now arch-specific, and x86_64 is using SW contexts
(smaller, simpler).

kern/arch/riscv/trap.h
kern/arch/x86/process64.c
kern/arch/x86/trap32.h
kern/arch/x86/trap64.c
kern/arch/x86/trap64.h
kern/include/trap.h

index cd4dfef..0336a8f 100644 (file)
 /* Kernel message interrupt vector.  ignored, for the most part */
 #define I_KERNEL_MSG 255
 
+/* For kernel contexts, when we save/restore/move them around. */
+struct kernel_ctx {
+       /* RISCV's current pop_kernel_ctx assumes the hw_tf is the first member */
+       struct hw_trapframe             hw_tf;
+};
+
 static inline bool in_kernel(struct hw_trapframe *hw_tf)
 {
        return hw_tf->sr & SR_PS;
index 315057d..a5e3fa5 100644 (file)
@@ -73,9 +73,7 @@ void proc_init_ctx(struct user_context *ctx, uint32_t vcoreid, uintptr_t entryp,
 {
        struct hw_trapframe *tf = &ctx->tf.hw_tf;
        ctx->type = ROS_HW_CTX;
-
-       memset(tf,0,sizeof(*tf));
-
+       memset(tf, 0, sizeof(*tf));
        /* Set up appropriate initial values for the segment registers.
         * GD_UD is the user data segment selector in the GDT, and
         * GD_UT is the user text segment selector (see inc/memlayout.h).
@@ -86,40 +84,31 @@ void proc_init_ctx(struct user_context *ctx, uint32_t vcoreid, uintptr_t entryp,
        tf->tf_cs = GD_UT | 3;
        /* set the env's EFLAGSs to have interrupts enabled */
        tf->tf_rflags |= 0x00000200; // bit 9 is the interrupts-enabled
-
        tf->tf_rip = entryp;
-
        /* Coupled closely with user's entry.S.  id is the vcoreid, which entry.S
         * uses to determine what to do.  vcoreid == 0 is the main core/context. */
        tf->tf_rax = vcoreid;
 }
 
-/* TODO: handle both HW and SW contexts */
+/* TODO: handle both HW and SW contexts.  Though I think this is only ever
+ * called on HW ctxs (we never try to pop a SW ctx that userspace had access
+ * to). */
 void proc_secure_ctx(struct user_context *ctx)
 {
        struct hw_trapframe *tf = &ctx->tf.hw_tf;
        ctx->type = ROS_HW_CTX;
-       /* we normally don't need to set the non-CS regs, but they could be
-        * gibberish and cause a GPF.  gs can still be gibberish, but we don't
-        * necessarily know what it ought to be (we could check, but that's a pain).
-        * the code protecting the kernel from TLS related things ought to be able
-        * to handle GPFs on popping gs. TODO: (TLSV) */
-       //tf->tf_fs = 0;
-       //tf->tf_gs = whatevs.  ignoring this.
        tf->tf_ss = GD_UD | 3;
-       tf->tf_cs ? GD_UT | 3 : 0; // can be 0 for sysenter TFs.
+       tf->tf_cs = GD_UT | 3;
        tf->tf_rflags |= 0x00000200; // bit 9 is the interrupts-enabled
 }
 
 /* Called when we are currently running an address space on our core and want to
  * abandon it.  We need a known good pgdir before releasing the old one.  We
  * decref, since current no longer tracks the proc (and current no longer
- * protects the cr3).  We also need to clear out the TLS registers (before
- * unmapping the address space!) */
+ * protects the cr3). */
 void __abandon_core(void)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       asm volatile ("movw %%ax,%%gs; lldt %%ax" :: "a"(0));
        lcr3(boot_cr3);
        proc_decref(pcpui->cur_proc);
        pcpui->cur_proc = 0;
index fa5651e..9d286d0 100644 (file)
 #error "Do not include arch/trap32.h directly."
 #endif
 
+/* For kernel contexts, when we save/restore/move them around. */
+struct kernel_ctx {
+       struct hw_trapframe             hw_tf;
+};
+
 static inline bool in_kernel(struct hw_trapframe *hw_tf)
 {
        return (hw_tf->tf_cs & ~3) == GD_KT;
index cc8beb2..0b032ed 100644 (file)
 /* Starts running the current TF, just using ret. */
 void pop_kernel_ctx(struct kernel_ctx *ctx)
 {
-       #if 0
-       asm volatile ("movl %1,%%esp;           " /* move to future stack */
-                     "pushl %2;                " /* push cs */
-                     "movl %0,%%esp;           " /* move to TF */
-                     "addl $0x20,%%esp;        " /* move to tf_gs slot */
-                     "movl %1,(%%esp);         " /* write future esp */
-                     "subl $0x20,%%esp;        " /* move back to tf start */
-                     "popal;                   " /* restore regs */
-                     "popl %%esp;              " /* set stack ptr */
-                     "subl $0x4,%%esp;         " /* jump down past CS */
-                     "ret                      " /* return to the EIP */
-                     :
-                     : "g"(&ctx->hw_tf), "r"(ctx->hw_tf.tf_esp),
-                       "r"(ctx->hw_tf.tf_eip)
-                     : "memory");
-       #endif
+       struct sw_trapframe *tf = &ctx->sw_tf;
+       /* We're starting at rbx's spot in the sw_tf */
+       asm volatile ("movq %0, %%rsp;          "
+                                 "popq %%rbx;              "
+                                 "popq %%rbp;              "
+                                 "popq %%r12;              "
+                                 "popq %%r13;              "
+                                 "popq %%r14;              "
+                                 "popq %%r15;              "
+                                 "popq %%rax;              " /* pop rip */
+                                 "popq %%rsp;              "
+                                 "jmp *%%rax;              " /* stored rip */
+                                 : : "g"(&ctx->sw_tf.tf_rbx) : "memory");
        panic("ret failed");
 }
 
index b7fbd3c..958ad63 100644 (file)
 #error "Do not include arch/trap64.h directly."
 #endif
 
+/* For kernel contexts, when we save/restore/move them around. */
+struct kernel_ctx {
+       struct sw_trapframe             sw_tf;
+};
+
 void print_swtrapframe(struct sw_trapframe *sw_tf);
 
 static inline bool in_kernel(struct hw_trapframe *hw_tf)
@@ -21,26 +26,24 @@ static inline bool in_kernel(struct hw_trapframe *hw_tf)
        return (hw_tf->tf_cs & ~3) == GD_KT;
 }
 
+/* Using SW contexts for now, for x86_64 */
 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 */
+       /* not bothering with the FP fields */
+       asm volatile("mov %%rsp, 0x48(%0);   " /* save rsp in its slot*/
+                    "leaq 1f, %%rax;        " /* get future rip */
+                    "mov %%rax, 0x40(%0);   " /* save rip in its slot*/
+                    "mov %%r15, 0x38(%0);   "
+                    "mov %%r14, 0x30(%0);   "
+                    "mov %%r13, 0x28(%0);   "
+                    "mov %%r12, 0x20(%0);   "
+                    "mov %%rbp, 0x18(%0);   "
+                    "mov %%rbx, 0x10(%0);   "
                     "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
+                                : "D"(&ctx->sw_tf)
+                    : "rax", "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11",
+                      "memory", "cc");
 }
 
 static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
@@ -50,7 +53,7 @@ static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf)
 
 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)
index 78deb69..22a9bed 100644 (file)
@@ -7,18 +7,6 @@
 #include <arch/arch.h>
 #include <arch/mmu.h>
 #include <sys/queue.h>
-/* #include <arch/trap.h> included below */
-
-/* For kernel contexts, when we save/restore/move them around.  For now, we'll
- * just use the old trapframe/hw_trap, but in the future we can slim this down a
- * bit.  Additionally, we might have different types of these in the future, if
- * we ever do non-cooperative kthread scheduling. */
-struct kernel_ctx {
-       /* RISCV's current pop_kernel_ctx assumes the hw_tf is the first member */
-       struct hw_trapframe             hw_tf;
-};
-
-/* Arch needs to hear about kernel_ctx */
 #include <arch/trap.h>
 
 // func ptr for interrupt service routines