Fixed RISC-V trap entry
authorAndrew Waterman <waterman@s144.Millennium.Berkeley.EDU>
Thu, 27 Oct 2011 11:04:40 +0000 (04:04 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 01:28:05 +0000 (18:28 -0700)
IRQs were being enabled in the wrong place, etc.

kern/arch/riscv/arch.h
kern/arch/riscv/entry.S
kern/arch/riscv/trap.c

index 90f21e9..746e696 100644 (file)
@@ -117,12 +117,6 @@ cpu_relax(void)
 }
 
 static __inline void
-cpu_halt(void)
-{
-  while(1);
-}
-
-static __inline void
 clflush(uintptr_t* addr)
 {
 }
@@ -169,4 +163,6 @@ reboot(void)
        while(1);
 }
 
+extern void cpu_halt(void);
+
 #endif /* !ROS_INC_ARCH_H */
index eb25f97..87c1f25 100644 (file)
@@ -55,7 +55,7 @@ pop_kernel_tf:
   LOAD  sp,30*REGBYTES(a0)
 
   mtpcr  t0,ASM_CR(PCR_SR)
-       ret
+  ret
 
   .end  pop_kernel_tf
 
@@ -187,5 +187,12 @@ trap_entry:
 1:jal   save_tf
   move  sp,x2
   move  a0,x2
-  jal    handle_trap
+  j     handle_trap
   .end  trap_entry
+
+  .global  cpu_halt
+  .ent  cpu_halt
+cpu_halt:
+1:b     1b   # handle_ipi can advance the PC to break out of this loop.
+  ret
+  .end  cpu_halt
index 5ea8afc..ee1268a 100644 (file)
@@ -101,7 +101,8 @@ sysenter_init(void)
 
 /* Helper.  For now, this copies out the TF to pcpui, and sets cur_tf to point
  * to it. */
-static void set_current_tf(struct per_cpu_info *pcpui, struct trapframe *tf)
+static void
+set_current_tf(struct per_cpu_info *pcpui, struct trapframe *tf)
 {
        if (irq_is_enabled())
                warn("Turn off IRQs until cur_tf is set!");
@@ -211,7 +212,8 @@ handle_ipi(trapframe_t* tf)
 
 /* Same as in x86.  Might be diff in the future if there is no way to check for
  * immediate messages or there is the ability to selectively mask IPI vectors.*/
-void process_routine_kmsg(struct trapframe *tf)
+void
+process_routine_kmsg(struct trapframe *tf)
 {
        per_cpu_info_t *myinfo = &per_cpu_info[core_id()];
        kernel_message_t msg_cp, *k_msg;
@@ -387,19 +389,13 @@ handle_fp_disabled(trapframe_t* state)
 static void
 handle_syscall(trapframe_t* state)
 {
-       struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        uintptr_t a0 = state->gpr[4];
        uintptr_t a1 = state->gpr[5];
 
        advance_pc(state);
+       set_current_tf(&per_cpu_info[core_id()], state);
        enable_irq();
-       struct per_cpu_info* coreinfo = &per_cpu_info[core_id()];
-
-       set_current_tf(pcpui, state);
-
        prep_syscalls(current, (struct syscall*)a0, a1);
-
-       proc_restartcore();
 }
 
 static void
@@ -412,9 +408,7 @@ handle_breakpoint(trapframe_t* state)
 void
 handle_trap(trapframe_t* tf)
 {
-       typedef void (*trap_handler)(trapframe_t*);
-       
-       const static trap_handler trap_handlers[NUM_CAUSES] = {
+       static void (*const trap_handlers[NUM_CAUSES])(trapframe_t*) = {
          [CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch,
          [CAUSE_FAULT_FETCH] = handle_fault_fetch,
          [CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
@@ -431,10 +425,15 @@ handle_trap(trapframe_t* tf)
        
        int exccode = (tf->cause & CAUSE_EXCCODE) >> CAUSE_EXCCODE_SHIFT;
        assert(exccode < NUM_CAUSES && trap_handlers[exccode]);
-       
        trap_handlers[exccode](tf);
        
-       env_pop_tf(tf);
+       /* Return to the current process, which should be runnable.  If we're the
+        * kernel, we should just return naturally.  Note that current and tf need
+        * to still be okay (might not be after blocking) */
+       if (in_kernel(tf))
+               env_pop_tf(tf);
+       else
+               proc_restartcore();
 }
 
 /* We don't have NMIs now. */