<p>Philipp Hug has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/29340">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">riscv: simplify timer interrupt handling<br><br>Just disable the timer interrupt and notify supervisor.<br>To receive another timer interrupt just set timecmp and<br>enable machine mode timer interrupt again.<br><br>Change-Id: I5d693f872bd492c9d0017b514882a4cebd5ccadd<br>Signed-off-by: Philipp Hug <philipp@hug.cx><br>---<br>M src/arch/riscv/trap_handler.c<br>1 file changed, 45 insertions(+), 84 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/40/29340/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/arch/riscv/trap_handler.c b/src/arch/riscv/trap_handler.c</span><br><span>index 772be64..c56dc0c 100644</span><br><span>--- a/src/arch/riscv/trap_handler.c</span><br><span>+++ b/src/arch/riscv/trap_handler.c</span><br><span>@@ -20,9 +20,6 @@</span><br><span> #include <string.h></span><br><span> #include <vm.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static uint64_t *time;</span><br><span style="color: hsl(0, 100%, 40%);">-static uint64_t *timecmp;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static const char *const exception_names[] = {</span><br><span>     "Instruction address misaligned",</span><br><span>  "Instruction access fault",</span><br><span>@@ -45,10 +42,14 @@</span><br><span> static const char *mstatus_to_previous_mode(uintptr_t ms)</span><br><span> {</span><br><span>        switch (ms & MSTATUS_MPP) {</span><br><span style="color: hsl(0, 100%, 40%);">-         case 0x00000000: return "user";</span><br><span style="color: hsl(0, 100%, 40%);">-               case 0x00000800: return "supervisor";</span><br><span style="color: hsl(0, 100%, 40%);">-         case 0x00001000: return "hypervisor";</span><br><span style="color: hsl(0, 100%, 40%);">-         case 0x00001800: return "machine";</span><br><span style="color: hsl(120, 100%, 40%);">+  case 0x00000000:</span><br><span style="color: hsl(120, 100%, 40%);">+              return "user";</span><br><span style="color: hsl(120, 100%, 40%);">+      case 0x00000800:</span><br><span style="color: hsl(120, 100%, 40%);">+              return "supervisor";</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0x00001000:</span><br><span style="color: hsl(120, 100%, 40%);">+              return "hypervisor";</span><br><span style="color: hsl(120, 100%, 40%);">+        case 0x00001800:</span><br><span style="color: hsl(120, 100%, 40%);">+              return "machine";</span><br><span>  }</span><br><span> </span><br><span>        return "unknown";</span><br><span>@@ -64,76 +65,36 @@</span><br><span> </span><br><span>        if (tf->cause < ARRAY_SIZE(exception_names))</span><br><span>           printk(BIOS_DEBUG, "Exception:          %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                                exception_names[tf->cause]);</span><br><span style="color: hsl(120, 100%, 40%);">+                      exception_names[tf->cause]);</span><br><span>       else</span><br><span>                 printk(BIOS_DEBUG, "Trap:               Unknown cause %p\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                          (void *)tf->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+                       (void *)tf->cause);</span><br><span> </span><br><span>    previous_mode = mstatus_to_previous_mode(read_csr(mstatus));</span><br><span>         printk(BIOS_DEBUG, "Previous mode:      %s%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      previous_mode, mprv? " (MPRV)":"");</span><br><span style="color: hsl(120, 100%, 40%);">+              previous_mode, mprv ? " (MPRV)" : "");</span><br><span>    printk(BIOS_DEBUG, "Bad instruction pc: %p\n", (void *)tf->epc);</span><br><span>        printk(BIOS_DEBUG, "Bad address:        %p\n", (void *)tf->badvaddr);</span><br><span style="color: hsl(0, 100%, 40%);">-      printk(BIOS_DEBUG, "Stored ra:          %p\n", (void*) tf->gpr[1]);</span><br><span style="color: hsl(0, 100%, 40%);">-        printk(BIOS_DEBUG, "Stored sp:          %p\n", (void*) tf->gpr[2]);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void gettimer(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * FIXME: This hard-coded value (currently) works on spike, but we</span><br><span style="color: hsl(0, 100%, 40%);">-       * should really read it from the device tree.</span><br><span style="color: hsl(0, 100%, 40%);">-   */</span><br><span style="color: hsl(0, 100%, 40%);">-     uintptr_t clint = 0x02000000;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   time    = (void *)(clint + 0xbff8);</span><br><span style="color: hsl(0, 100%, 40%);">-     timecmp = (void *)(clint + 0x4000);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!time)</span><br><span style="color: hsl(0, 100%, 40%);">-              die("Got timer interrupt but found no timer.");</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!timecmp)</span><br><span style="color: hsl(0, 100%, 40%);">-           die("Got timer interrupt but found no timecmp.");</span><br><span style="color: hsl(120, 100%, 40%);">+   printk(BIOS_DEBUG, "Stored ra:          %p\n", (void *)tf->gpr[1]);</span><br><span style="color: hsl(120, 100%, 40%);">+      printk(BIOS_DEBUG, "Stored sp:          %p\n", (void *)tf->gpr[2]);</span><br><span> }</span><br><span> </span><br><span> static void interrupt_handler(trapframe *tf)</span><br><span> {</span><br><span>       uint64_t cause = tf->cause & ~0x8000000000000000ULL;</span><br><span style="color: hsl(0, 100%, 40%);">-     uint32_t msip, ssie;</span><br><span> </span><br><span>     switch (cause) {</span><br><span>     case IRQ_M_TIMER:</span><br><span style="color: hsl(0, 100%, 40%);">-               // The only way to reset the timer interrupt is to</span><br><span style="color: hsl(0, 100%, 40%);">-              // write mtimecmp. But we also have to ensure the</span><br><span style="color: hsl(0, 100%, 40%);">-               // comparison fails, for a long time, to let</span><br><span style="color: hsl(0, 100%, 40%);">-            // supervisor interrupt handler compute a new value</span><br><span style="color: hsl(0, 100%, 40%);">-             // and set it. Finally, it fires if mtimecmp is <=</span><br><span style="color: hsl(0, 100%, 40%);">-           // mtime, not =, so setting mtimecmp to 0 won't work</span><br><span style="color: hsl(0, 100%, 40%);">-                // to clear the interrupt and disable a new one. We</span><br><span style="color: hsl(0, 100%, 40%);">-             // have to set the mtimecmp far into the future.</span><br><span style="color: hsl(0, 100%, 40%);">-                // Akward!</span><br><span style="color: hsl(0, 100%, 40%);">-              //</span><br><span style="color: hsl(0, 100%, 40%);">-              // Further, maybe the platform doesn't have the</span><br><span style="color: hsl(0, 100%, 40%);">-             // hardware or the payload never uses it. We hold off</span><br><span style="color: hsl(0, 100%, 40%);">-           // querying some things until we are sure we need</span><br><span style="color: hsl(0, 100%, 40%);">-               // them. What to do if we can not find them? There are</span><br><span style="color: hsl(0, 100%, 40%);">-          // no good options.</span><br><span style="color: hsl(120, 100%, 40%);">+           /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * Set interrupt pending for supervisor mode and disable timer</span><br><span style="color: hsl(120, 100%, 40%);">+                 * interrupt in machine mode.</span><br><span style="color: hsl(120, 100%, 40%);">+          * To receive another timer interrupt just set timecmp and</span><br><span style="color: hsl(120, 100%, 40%);">+             * enable machine mode timer interrupt again.</span><br><span style="color: hsl(120, 100%, 40%);">+          */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         // This hart may have disabled timer interrupts.  If</span><br><span style="color: hsl(0, 100%, 40%);">-            // so, just return. Kernels should only enable timer</span><br><span style="color: hsl(0, 100%, 40%);">-            // interrupts on one hart, and that should be hart 0</span><br><span style="color: hsl(0, 100%, 40%);">-            // at present, as we only search for</span><br><span style="color: hsl(0, 100%, 40%);">-            // "core{0{0{timecmp" above.</span><br><span style="color: hsl(0, 100%, 40%);">-          ssie = read_csr(sie);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (!(ssie & SIP_STIP))</span><br><span style="color: hsl(0, 100%, 40%);">-                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+                clear_csr(mie, MIP_MTIP);</span><br><span style="color: hsl(120, 100%, 40%);">+             set_csr(mip, MIP_STIP);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             if (!timecmp)</span><br><span style="color: hsl(0, 100%, 40%);">-                   gettimer();</span><br><span style="color: hsl(0, 100%, 40%);">-             //printk(BIOS_SPEW, "timer interrupt\n");</span><br><span style="color: hsl(0, 100%, 40%);">-             *timecmp = (uint64_t) -1;</span><br><span style="color: hsl(0, 100%, 40%);">-               msip = read_csr(mip);</span><br><span style="color: hsl(0, 100%, 40%);">-           msip |= SIP_STIP;</span><br><span style="color: hsl(0, 100%, 40%);">-               write_csr(mip, msip);</span><br><span>                break;</span><br><span>       default:</span><br><span>             printk(BIOS_EMERG, "======================================\n");</span><br><span>@@ -152,30 +113,30 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   switch(tf->cause) {</span><br><span style="color: hsl(0, 100%, 40%);">-          case CAUSE_MISALIGNED_FETCH:</span><br><span style="color: hsl(0, 100%, 40%);">-            case CAUSE_FETCH_ACCESS:</span><br><span style="color: hsl(0, 100%, 40%);">-                case CAUSE_ILLEGAL_INSTRUCTION:</span><br><span style="color: hsl(0, 100%, 40%);">-         case CAUSE_BREAKPOINT:</span><br><span style="color: hsl(0, 100%, 40%);">-          case CAUSE_LOAD_ACCESS:</span><br><span style="color: hsl(0, 100%, 40%);">-         case CAUSE_STORE_ACCESS:</span><br><span style="color: hsl(0, 100%, 40%);">-                case CAUSE_USER_ECALL:</span><br><span style="color: hsl(0, 100%, 40%);">-          case CAUSE_SUPERVISOR_ECALL:</span><br><span style="color: hsl(0, 100%, 40%);">-            case CAUSE_HYPERVISOR_ECALL:</span><br><span style="color: hsl(0, 100%, 40%);">-            case CAUSE_MACHINE_ECALL:</span><br><span style="color: hsl(0, 100%, 40%);">-                       print_trap_information(tf);</span><br><span style="color: hsl(0, 100%, 40%);">-                     break;</span><br><span style="color: hsl(0, 100%, 40%);">-          case CAUSE_MISALIGNED_LOAD:</span><br><span style="color: hsl(0, 100%, 40%);">-             case CAUSE_MISALIGNED_STORE:</span><br><span style="color: hsl(0, 100%, 40%);">-                    print_trap_information(tf);</span><br><span style="color: hsl(0, 100%, 40%);">-                     handle_misaligned(tf);</span><br><span style="color: hsl(0, 100%, 40%);">-                  return;</span><br><span style="color: hsl(0, 100%, 40%);">-         default:</span><br><span style="color: hsl(0, 100%, 40%);">-                        printk(BIOS_EMERG, "================================\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                     printk(BIOS_EMERG, "coreboot: can not handle a trap:\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                     printk(BIOS_EMERG, "================================\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                     print_trap_information(tf);</span><br><span style="color: hsl(0, 100%, 40%);">-                     break;</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (tf->cause) {</span><br><span style="color: hsl(120, 100%, 40%);">+       case CAUSE_MISALIGNED_FETCH:</span><br><span style="color: hsl(120, 100%, 40%);">+  case CAUSE_FETCH_ACCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+      case CAUSE_ILLEGAL_INSTRUCTION:</span><br><span style="color: hsl(120, 100%, 40%);">+       case CAUSE_BREAKPOINT:</span><br><span style="color: hsl(120, 100%, 40%);">+        case CAUSE_LOAD_ACCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+       case CAUSE_STORE_ACCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+      case CAUSE_USER_ECALL:</span><br><span style="color: hsl(120, 100%, 40%);">+        case CAUSE_SUPERVISOR_ECALL:</span><br><span style="color: hsl(120, 100%, 40%);">+  case CAUSE_HYPERVISOR_ECALL:</span><br><span style="color: hsl(120, 100%, 40%);">+  case CAUSE_MACHINE_ECALL:</span><br><span style="color: hsl(120, 100%, 40%);">+             print_trap_information(tf);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case CAUSE_MISALIGNED_LOAD:</span><br><span style="color: hsl(120, 100%, 40%);">+   case CAUSE_MISALIGNED_STORE:</span><br><span style="color: hsl(120, 100%, 40%);">+          print_trap_information(tf);</span><br><span style="color: hsl(120, 100%, 40%);">+           handle_misaligned(tf);</span><br><span style="color: hsl(120, 100%, 40%);">+                return;</span><br><span style="color: hsl(120, 100%, 40%);">+       default:</span><br><span style="color: hsl(120, 100%, 40%);">+              printk(BIOS_EMERG, "================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           printk(BIOS_EMERG, "coreboot: can not handle a trap:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           printk(BIOS_EMERG, "================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           print_trap_information(tf);</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span>       }</span><br><span> </span><br><span>        die("Can't recover from trap. Halting.\n");</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/29340">change 29340</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/29340"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I5d693f872bd492c9d0017b514882a4cebd5ccadd </div>
<div style="display:none"> Gerrit-Change-Number: 29340 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Philipp Hug <philipp@hug.cx> </div>