[coreboot-gerrit] Change in coreboot[master]: riscv: simplify timer interrupt handling

Philipp Hug (Code Review) gerrit at coreboot.org
Mon Oct 29 18:26:55 CET 2018


Philipp Hug has uploaded this change for review. ( https://review.coreboot.org/29340


Change subject: riscv: simplify timer interrupt handling
......................................................................

riscv: simplify timer interrupt handling

Just disable the timer interrupt and notify supervisor.
To receive another timer interrupt just set timecmp and
enable machine mode timer interrupt again.

Change-Id: I5d693f872bd492c9d0017b514882a4cebd5ccadd
Signed-off-by: Philipp Hug <philipp at hug.cx>
---
M src/arch/riscv/trap_handler.c
1 file changed, 45 insertions(+), 84 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/40/29340/1

diff --git a/src/arch/riscv/trap_handler.c b/src/arch/riscv/trap_handler.c
index 772be64..c56dc0c 100644
--- a/src/arch/riscv/trap_handler.c
+++ b/src/arch/riscv/trap_handler.c
@@ -20,9 +20,6 @@
 #include <string.h>
 #include <vm.h>
 
-static uint64_t *time;
-static uint64_t *timecmp;
-
 static const char *const exception_names[] = {
 	"Instruction address misaligned",
 	"Instruction access fault",
@@ -45,10 +42,14 @@
 static const char *mstatus_to_previous_mode(uintptr_t ms)
 {
 	switch (ms & MSTATUS_MPP) {
-		case 0x00000000: return "user";
-		case 0x00000800: return "supervisor";
-		case 0x00001000: return "hypervisor";
-		case 0x00001800: return "machine";
+	case 0x00000000:
+		return "user";
+	case 0x00000800:
+		return "supervisor";
+	case 0x00001000:
+		return "hypervisor";
+	case 0x00001800:
+		return "machine";
 	}
 
 	return "unknown";
@@ -64,76 +65,36 @@
 
 	if (tf->cause < ARRAY_SIZE(exception_names))
 		printk(BIOS_DEBUG, "Exception:          %s\n",
-				exception_names[tf->cause]);
+		       exception_names[tf->cause]);
 	else
 		printk(BIOS_DEBUG, "Trap:               Unknown cause %p\n",
-				(void *)tf->cause);
+		       (void *)tf->cause);
 
 	previous_mode = mstatus_to_previous_mode(read_csr(mstatus));
 	printk(BIOS_DEBUG, "Previous mode:      %s%s\n",
-			previous_mode, mprv? " (MPRV)":"");
+	       previous_mode, mprv ? " (MPRV)" : "");
 	printk(BIOS_DEBUG, "Bad instruction pc: %p\n", (void *)tf->epc);
 	printk(BIOS_DEBUG, "Bad address:        %p\n", (void *)tf->badvaddr);
-	printk(BIOS_DEBUG, "Stored ra:          %p\n", (void*) tf->gpr[1]);
-	printk(BIOS_DEBUG, "Stored sp:          %p\n", (void*) tf->gpr[2]);
-}
-
-static void gettimer(void)
-{
-	/*
-	 * FIXME: This hard-coded value (currently) works on spike, but we
-	 * should really read it from the device tree.
-	 */
-	uintptr_t clint = 0x02000000;
-
-	time    = (void *)(clint + 0xbff8);
-	timecmp = (void *)(clint + 0x4000);
-
-	if (!time)
-		die("Got timer interrupt but found no timer.");
-	if (!timecmp)
-		die("Got timer interrupt but found no timecmp.");
+	printk(BIOS_DEBUG, "Stored ra:          %p\n", (void *)tf->gpr[1]);
+	printk(BIOS_DEBUG, "Stored sp:          %p\n", (void *)tf->gpr[2]);
 }
 
 static void interrupt_handler(trapframe *tf)
 {
 	uint64_t cause = tf->cause & ~0x8000000000000000ULL;
-	uint32_t msip, ssie;
 
 	switch (cause) {
 	case IRQ_M_TIMER:
-		// The only way to reset the timer interrupt is to
-		// write mtimecmp. But we also have to ensure the
-		// comparison fails, for a long time, to let
-		// supervisor interrupt handler compute a new value
-		// and set it. Finally, it fires if mtimecmp is <=
-		// mtime, not =, so setting mtimecmp to 0 won't work
-		// to clear the interrupt and disable a new one. We
-		// have to set the mtimecmp far into the future.
-		// Akward!
-		//
-		// Further, maybe the platform doesn't have the
-		// hardware or the payload never uses it. We hold off
-		// querying some things until we are sure we need
-		// them. What to do if we can not find them? There are
-		// no good options.
+		/*
+		 * Set interrupt pending for supervisor mode and disable timer
+		 * interrupt in machine mode.
+		 * To receive another timer interrupt just set timecmp and
+		 * enable machine mode timer interrupt again.
+		 */
 
-		// This hart may have disabled timer interrupts.  If
-		// so, just return. Kernels should only enable timer
-		// interrupts on one hart, and that should be hart 0
-		// at present, as we only search for
-		// "core{0{0{timecmp" above.
-		ssie = read_csr(sie);
-		if (!(ssie & SIP_STIP))
-			break;
+		clear_csr(mie, MIP_MTIP);
+		set_csr(mip, MIP_STIP);
 
-		if (!timecmp)
-			gettimer();
-		//printk(BIOS_SPEW, "timer interrupt\n");
-		*timecmp = (uint64_t) -1;
-		msip = read_csr(mip);
-		msip |= SIP_STIP;
-		write_csr(mip, msip);
 		break;
 	default:
 		printk(BIOS_EMERG, "======================================\n");
@@ -152,30 +113,30 @@
 		return;
 	}
 
-	switch(tf->cause) {
-		case CAUSE_MISALIGNED_FETCH:
-		case CAUSE_FETCH_ACCESS:
-		case CAUSE_ILLEGAL_INSTRUCTION:
-		case CAUSE_BREAKPOINT:
-		case CAUSE_LOAD_ACCESS:
-		case CAUSE_STORE_ACCESS:
-		case CAUSE_USER_ECALL:
-		case CAUSE_SUPERVISOR_ECALL:
-		case CAUSE_HYPERVISOR_ECALL:
-		case CAUSE_MACHINE_ECALL:
-			print_trap_information(tf);
-			break;
-		case CAUSE_MISALIGNED_LOAD:
-		case CAUSE_MISALIGNED_STORE:
-			print_trap_information(tf);
-			handle_misaligned(tf);
-			return;
-		default:
-			printk(BIOS_EMERG, "================================\n");
-			printk(BIOS_EMERG, "coreboot: can not handle a trap:\n");
-			printk(BIOS_EMERG, "================================\n");
-			print_trap_information(tf);
-			break;
+	switch (tf->cause) {
+	case CAUSE_MISALIGNED_FETCH:
+	case CAUSE_FETCH_ACCESS:
+	case CAUSE_ILLEGAL_INSTRUCTION:
+	case CAUSE_BREAKPOINT:
+	case CAUSE_LOAD_ACCESS:
+	case CAUSE_STORE_ACCESS:
+	case CAUSE_USER_ECALL:
+	case CAUSE_SUPERVISOR_ECALL:
+	case CAUSE_HYPERVISOR_ECALL:
+	case CAUSE_MACHINE_ECALL:
+		print_trap_information(tf);
+		break;
+	case CAUSE_MISALIGNED_LOAD:
+	case CAUSE_MISALIGNED_STORE:
+		print_trap_information(tf);
+		handle_misaligned(tf);
+		return;
+	default:
+		printk(BIOS_EMERG, "================================\n");
+		printk(BIOS_EMERG, "coreboot: can not handle a trap:\n");
+		printk(BIOS_EMERG, "================================\n");
+		print_trap_information(tf);
+		break;
 	}
 
 	die("Can't recover from trap. Halting.\n");

-- 
To view, visit https://review.coreboot.org/29340
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5d693f872bd492c9d0017b514882a4cebd5ccadd
Gerrit-Change-Number: 29340
Gerrit-PatchSet: 1
Gerrit-Owner: Philipp Hug <philipp at hug.cx>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20181029/126689e4/attachment-0001.html>


More information about the coreboot-gerrit mailing list