<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>