handle RISC-V keyboard interrupts properly
authorAndrew Waterman <waterman@cs.berkeley.edu>
Sat, 23 Mar 2013 23:39:25 +0000 (16:39 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Sat, 23 Mar 2013 23:39:25 +0000 (16:39 -0700)
Rather than piggybacking on the IPI handler, that is.

kern/arch/riscv/console.c
kern/arch/riscv/console.h
kern/arch/riscv/pcr.h
kern/arch/riscv/trap.c

index 29c7b46..8aabab4 100644 (file)
@@ -12,10 +12,10 @@ int cons_get_any_char(void)
        assert(0);
 }
 
-void
-cons_init(void)
+void cons_init()
 {
-       while (mtpcr(PCR_TOHOST, 0x0180000000000000));
+       mtpcr(PCR_SR, mfpcr(PCR_SR) | (1 << (IRQ_HOST+SR_IM_SHIFT)));
+       while (mtpcr(PCR_TOHOST, 0x01L << 56));
 }
 
 // `High'-level console I/O.  Used by readline and cprintf.
@@ -29,18 +29,6 @@ cputbuf(const char* str, int len)
 
 void poll_keyboard()
 {
-       uintptr_t fh = mtpcr(PCR_FROMHOST, 0);
-       if (fh == 0)
-               return;
-       assert((fh >> 56) == 0x01);
-
-       char c = fh;
-       if (c == 'G')
-               send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
-       else
-               send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf,
-                                   (long)c, 0, KMSG_ROUTINE);
-       cons_init();
 }
 
 // Low-level console I/O
index a9e8683..209fc45 100644 (file)
@@ -15,6 +15,5 @@
 void cons_init(void);
 /* Returns any available character, or 0 for none (legacy helper) */
 int cons_get_any_char(void);
-void poll_keyboard();
 
 #endif /* _CONSOLE_H_ */
index 7659a97..33939d8 100644 (file)
 #define SR_S64   0x00000080
 #define SR_VM    0x00000100
 #define SR_IM    0x00FF0000
-#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IP    0xFF000000
+#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM|SR_IP)
 #define SR_IM_SHIFT 16
+#define SR_IP_SHIFT 24
 
 #define PCR_SR       0
 #define PCR_EPC      1
@@ -35,6 +37,7 @@
 #define PCR_FROMHOST 31
 
 #define IRQ_IPI   5
+#define IRQ_HOST  6
 #define IRQ_TIMER 7
 
 #define CAUSE_MISALIGNED_FETCH 0
index 8cf342a..a1273f0 100644 (file)
@@ -2,6 +2,7 @@
 #include <assert.h>
 #include <arch/trap.h>
 #include <arch/console.h>
+#include <console.h>
 #include <string.h>
 #include <process.h>
 #include <syscall.h>
@@ -111,6 +112,7 @@ print_trapframe(trapframe_t* tf)
        int len = format_trapframe(tf,buf,sizeof(buf));
        cputbuf(buf,len);
 }
+
 static void exit_halt_loop(trapframe_t* tf)
 {
        extern char after_cpu_halt;
@@ -118,18 +120,33 @@ static void exit_halt_loop(trapframe_t* tf)
                tf->epc = tf->gpr[1];
 }
 
-/* Assumes that any IPI you get is really a kernel message */
-static void
-handle_ipi(trapframe_t* tf)
+static void handle_keypress(char c)
 {
-       clear_ipi();
-       poll_keyboard(); // keypresses can trigger IPIs
+       amr_t handler = c == 'G' ? __run_mon : __cons_add_char;
+       send_kernel_message(core_id(), handler, (long)&cons_buf, (long)c, 0,
+                           KMSG_ROUTINE);
+       cons_init();
+}
 
-       if (!in_kernel(tf))
-               set_current_tf(&per_cpu_info[core_id()], tf);
-       else
-               exit_halt_loop(tf);
+static void handle_host_interrupt(trapframe_t* tf)
+{
+       uintptr_t fh = mtpcr(PCR_FROMHOST, 0);
+       switch (fh >> 56)
+       {
+         case 0x01: handle_keypress(fh); return;
+         default: assert(0);
+       }
+}
 
+static void handle_timer_interrupt(trapframe_t* tf)
+{
+       timer_interrupt(tf, NULL);
+}
+
+/* Assumes that any IPI you get is really a kernel message */
+static void handle_interprocessor_interrupt(trapframe_t* tf)
+{
+       clear_ipi();
        handle_kmsg_ipi(tf, 0);
 }
 
@@ -160,17 +177,6 @@ unhandled_trap(trapframe_t* state, const char* name)
 }
 
 static void
-handle_timer_interrupt(trapframe_t* tf)
-{
-       if (!in_kernel(tf))
-               set_current_tf(&per_cpu_info[core_id()], tf);
-       else
-               exit_halt_loop(tf);
-       
-       timer_interrupt(tf, NULL);
-}
-
-static void
 handle_misaligned_fetch(trapframe_t* state)
 {
        unhandled_trap(state, "Misaligned Fetch");
@@ -226,7 +232,7 @@ handle_fault_store(trapframe_t* state)
                print_trapframe(state);
                panic("Store Page Fault in the Kernel at %p!", state->badvaddr);
        }
-       
+
        set_current_tf(&per_cpu_info[core_id()], state);
 
        if(handle_page_fault(current, state->badvaddr, PROT_WRITE))
@@ -238,10 +244,6 @@ handle_illegal_instruction(trapframe_t* state)
 {
        assert(!in_kernel(state));
 
-       // XXX for noFP demo purposes we're ignoring illegal insts in the user.
-       advance_pc(state);
-       env_pop_tf(state); /* We didn't save our TF, so don't use proc_restartcore */
-
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        set_current_tf(pcpui, state);
        if (emulate_fpu(state) == 0)
@@ -301,7 +303,8 @@ handle_trap(trapframe_t* tf)
 
        static void (*const irq_handlers[])(trapframe_t*) = {
          [IRQ_TIMER] = handle_timer_interrupt,
-         [IRQ_IPI] = handle_ipi,
+         [IRQ_HOST] = handle_host_interrupt,
+         [IRQ_IPI] = handle_interprocessor_interrupt,
        };
        
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
@@ -310,6 +313,12 @@ handle_trap(trapframe_t* tf)
                uint8_t irq = tf->cause;
                assert(irq < sizeof(irq_handlers)/sizeof(irq_handlers[0]) &&
                       irq_handlers[irq]);
+
+               if (in_kernel(tf))
+                       exit_halt_loop(tf);
+               else
+                       set_current_tf(&per_cpu_info[core_id()], tf);
+
                inc_irq_depth(pcpui);
                irq_handlers[irq](tf);
                dec_irq_depth(pcpui);