Uses kernel_ctx instead of TF for kthreading
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Apr 2013 16:56:43 +0000 (09:56 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 11 Apr 2013 19:44:54 +0000 (12:44 -0700)
We're trying to be more explicit about what sort of trapframe we're
using at any given time.

This also gives us a layer of code indirection (it should compile the
same for now) that may be helpful later.

Documentation/kthreads.txt
kern/arch/i686/trap.c
kern/arch/i686/trap.h
kern/arch/riscv/entry.S
kern/arch/riscv/trap.h
kern/arch/sparc/trap.c
kern/arch/sparc/trap.h
kern/include/kthread.h
kern/include/trap.h
kern/src/kthread.c

index 3ded61c..a79a318 100644 (file)
@@ -73,7 +73,7 @@ Freeing Stacks and Structs
 -------------------------------
 When we restart a kthread, we have to be careful about freeing the old stack and
 the struct kthread.  We need to delay the freeing of both of these until after
-we pop_kernel_tf().  We can't free the kthread before popping it, and we are on
+we pop_kernel_ctx().  We can't free the kthread before popping it, and we are on
 the stack we need to free (until we pop to the new stack).
 
 To deal with this, we have a "spare" kthread per core, which gets assigned as
@@ -125,7 +125,7 @@ loses the race (unlikely), it can manually unwind.
 
 Note that a lot of this is probably needless worry - we have interrupts disabled
 for most of sleep_on(), though arguably we can be a little more careful with
-pcpui->spare and move the disable_irq() down to right before save_kernel_tf().
+pcpui->spare and move the disable_irq() down to right before save_kernel_ctx().
 
 What's the Deal with Stacks/Stacktops?
 -------------------------------
@@ -166,7 +166,7 @@ kthread run with its stack as the default stacktop.
 
 When restarting a kthread, we eventually will use its stack, instead of the
 current one, but we can't free the current stack until after we actually
-pop_kernel_tf().  this is the same problem as with the struct kthread dealloc.
+pop_kernel_ctx().  this is the same problem as with the struct kthread dealloc.
 So we can have the kthread (which we want to free later) hold on to the page we
 wanted to dealloc.  Likewise, when we would need a fresh kthread, we also need a
 page to use as the default stacktop.  So if we had a cached kthread, we then use
index 1258592..7e38795 100644 (file)
@@ -105,7 +105,7 @@ uintptr_t get_stack_top(void)
 }
 
 /* Starts running the current TF, just using ret. */
-void pop_kernel_tf(struct trapframe *tf)
+void pop_kernel_ctx(struct kernel_ctx *ctx)
 {
        asm volatile ("movl %1,%%esp;           " /* move to future stack */
                      "pushl %2;                " /* push cs */
@@ -118,7 +118,9 @@ void pop_kernel_tf(struct trapframe *tf)
                      "subl $0x4,%%esp;         " /* jump down past CS */
                      "ret                      " /* return to the EIP */
                      :
-                     : "g"(tf), "r"(tf->tf_esp), "r"(tf->tf_eip) : "memory");
+                     : "g"(&ctx->hw_tf), "r"(ctx->hw_tf.tf_esp),
+                       "r"(ctx->hw_tf.tf_eip)
+                     : "memory");
        panic("ret failed");                            /* mostly to placate your mom */
 }
 
index 2108b96..98c40fa 100644 (file)
@@ -94,7 +94,7 @@ set_stack_pointer(uintptr_t sp)
 
 /* Save's the current kernel context into tf, setting the PC to the end of this
  * function.  Note the kernel doesn't need to save a lot. */
-static inline void save_kernel_tf(struct trapframe *tf)
+static inline void save_kernel_ctx(struct kernel_ctx *ctx)
 {
        /* Save the regs and the future esp. */
        asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/
@@ -109,7 +109,8 @@ static inline void save_kernel_tf(struct trapframe *tf)
                     "popl %%esp;            " /* restore esp */
                     "1:                     " /* where this tf will restart */
                     : 
-                    : "r"(&tf->tf_esp), "r"(&tf->tf_eip), "g"(tf)
+                    : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip),
+                      "g"(&ctx->hw_tf)
                     : "eax", "memory", "cc");
 }
 
index 08d0369..47f7b02 100644 (file)
@@ -36,8 +36,8 @@ save_kernel_tf_asm:
   ret
 
   .text
-  .global pop_kernel_tf
-pop_kernel_tf:
+  .global pop_kernel_ctx
+pop_kernel_ctx:
   LOAD  t0,32*REGBYTES(a0)
   LOAD  ra,33*REGBYTES(a0)
 
index 53c63c9..46bf232 100644 (file)
@@ -33,10 +33,10 @@ set_stack_pointer(uintptr_t sp)
 /* Save's the current kernel context into tf, setting the PC to the end of this
  * function.  Note the kernel doesn't need to save a lot.
  * Implemented with extern function to cause compiler to clobber most regs. */
-static inline void save_kernel_tf(struct trapframe *tf)
+static inline void save_kernel_ctx(struct kernel_ctx *ctx)
 {
   extern void save_kernel_tf_asm(struct trapframe*);
-       save_kernel_tf_asm(tf);
+       save_kernel_tf_asm(&ctx->hw_tf);
 }
 
 void handle_trap(struct trapframe *tf);
index bb26e75..391e427 100644 (file)
@@ -60,7 +60,7 @@ uintptr_t get_stack_top(void)
 }
 
 /* Starts running the current TF. */
-void pop_kernel_tf(struct trapframe *tf)
+void pop_kernel_ctx(struct kernel_ctx *ctx)
 {
        /* TODO! also do save_kernel_tf() in kern/arch/sparc/trap.h */
        panic("Not implemented.  =(");
index fce3ee8..d720d3b 100644 (file)
@@ -48,9 +48,10 @@ set_stack_pointer(uintptr_t sp)
 
 /* Save's the current kernel context into tf, setting the PC to the end of this
  * function. */
-static inline void save_kernel_tf(struct trapframe *tf)
+static inline void save_kernel_ctx(struct kernel_ctx *ctx)
 {
        /* TODO: save the registers, stack pointer, and have the PC pt to the end */
+       panic("Not implemented!\n");
 }
 
 #endif /* !__ASSEMBLER__ */
index 98e96a7..43e01d6 100644 (file)
@@ -26,7 +26,7 @@ LIST_HEAD(semaphore_list, semaphore_entry);
  * a kthread is running, we make sure its stacktop is the default kernel stack,
  * meaning it will receive the interrupts from userspace. */
 struct kthread {
-       struct trapframe                        context;
+       struct kernel_ctx                       context;
        uintptr_t                                       stacktop;
        struct proc                                     *proc;
        struct syscall                          *sysc;
index 2ae093a..16811ef 100644 (file)
@@ -7,6 +7,18 @@
 #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
@@ -45,10 +57,10 @@ extern inline void restore_fp_state(struct ancillary_state *silly);
 void set_stack_top(uintptr_t stacktop);
 uintptr_t get_stack_top(void);
 
-/* It's important that this is inline and that tf is not a stack variable */
-static inline void save_kernel_tf(struct trapframe *tf)
+/* It's important that this is inline and that ctx is not a stack variable */
+static inline void save_kernel_ctx(struct kernel_ctx *ctx)
                    __attribute__((always_inline));
-void pop_kernel_tf(struct trapframe *tf) __attribute__((noreturn));
+void pop_kernel_ctx(struct kernel_ctx *ctx) __attribute__((noreturn));
 
 /* Sends a non-maskable interrupt, which we have print a trapframe. */
 void send_nmi(uint32_t os_coreid);
index 3d61b1e..a9250c5 100644 (file)
@@ -73,7 +73,7 @@ void restart_kthread(struct kthread *kthread)
        assert(!pcpui->cur_sysc);       /* catch bugs, prev user should clear */
        pcpui->cur_sysc = kthread->sysc;
        /* Finally, restart our thread */
-       pop_kernel_tf(&kthread->context);
+       pop_kernel_ctx(&kthread->context);
 }
 
 /* Kmsg handler to launch/run a kthread.  This must be a routine message, since
@@ -249,7 +249,7 @@ void sem_down(struct semaphore *sem)
        if (kthread->proc)
                proc_incref(kthread->proc, 1);
        /* Save the context, toggle blocking for the reactivation */
-       save_kernel_tf(&kthread->context);
+       save_kernel_ctx(&kthread->context);
        if (!blocking)
                goto block_return_path;
        blocking = FALSE;                                       /* for when it starts back up */