commit 8f4ca9f20812474b2a1ddad67296c89b920b1015
parent 2bd8d0d84f351f2935ff5accfd5417de8168f690
Author: Brian Swetland <swetland@frotz.net>
Date: Thu, 12 May 2022 15:57:49 -0700
shuffle stuff around
- nuke the old traps.c app
- context.h defines standard layouts for saving register state
- boot/entry/S and hw/src/trap-entry-single-stack.S and
hw/src/context-switch.S conform to these layouts
- update boot, utils, etc to also conform
Diffstat:
11 files changed, 391 insertions(+), 236 deletions(-)
diff --git a/boot/boot.c b/boot/boot.c
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0
#include <hw/riscv.h>
+#include <hw/context.h>
#include <hw/intrinsics.h>
#include <hw/debug.h>
@@ -13,26 +14,9 @@
// we expect the supervisor program to be in memory after the end of the bootloader
#define SVC_ENTRY (DRAM_BASE + BOOTLOADER_SIZE)
-void mach_exception_handler(uint32_t regs[32]) {
-#if EMULATE_MISSING_CSR_READS
- uint32_t mcause = csr_read(CSR_MCAUSE);
- uint32_t mtval = csr_read(CSR_MTVAL);
-
- // fragile: no mtval on qemu
- if (mcause == 2) mtval = *((uint32_t*) regs[0]);
-
- if ((mcause == 2) && ((mtval & (~0xFFF00F80)) == 0x00002073)) {
- uint32_t rd = (mtval >> 7) & 31;
- xprintf("BAD CSR READ @%08x (%08x) -> x%u\n", regs[0], mtval, rd);
- regs[rd] = 0xDEADBEEF;
- regs[0] += 4;
- return;
- }
-#endif
-
+void mach_exception_handler(eframe_t *ef) {
xprintf("\n** MACHINE EXCEPTION **\n");
- xprint_exception(regs);
-
+ xprint_m_exception(ef);
xprintf("\nHALT\n");
for (;;) ;
}
@@ -69,6 +53,7 @@ void start(uint32_t hartid, uint32_t fdt) {
xprintf("SVC ENTRY @0x%08x\n\n", SVC_ENTRY);
- enter_mode_s(hartid, fdt, SVC_ENTRY, 0);
+ exit_mode_m(hartid, fdt, SVC_ENTRY, 0);
+
}
diff --git a/boot/boot.h b/boot/boot.h
@@ -1,20 +1,10 @@
#pragma once
-// offsets into the interrupt workspace
-#define IWS_TIMECMP 0x00
-#define IWS_TICKINC 0x04
-#define IWS_SAVE0 0x08
-#define IWS_SAVE1 0x0C
-#define IWS_SAVE2 0x10
-#define IWS_SAVE3 0x14
-#define IWS_SAVE4 0x18
-#define IWS_SIZE 0x40
-
#ifndef __ASSEMBLY__
// entry.S
void mach_exception_entry(void);
-void enter_mode_s(uint32_t a0, uint32_t a1, uint32_t pc, uint32_t sp);
+void exit_mode_m(uint32_t a0, uint32_t a1, uint32_t pc, uint32_t sp);
#endif
diff --git a/boot/entry.S b/boot/entry.S
@@ -2,105 +2,119 @@
// Licensed under the Apache License, Version 2.0
#include <hw/riscv.h>
-#include "boot.h"
+
+// This exception handler is conservative and stores *all*
+// the general registers on the stack on exception entry.
+//
+// This allows the exception handler to easily inspect and
+// modify the previous register state.
+//
+// A more efficient handler could only store the callee-save
+// registers (that would otherwise be possibly clobbered by
+// the C code it calls into), and trust that the others would
+// be saved and restored as needed, further down the call chain.
.globl mach_exception_entry
mach_exception_entry:
// swap active sp with value in MSCRATCH (exception stack)
// interupts have been disabled on exception entry
- csrrw sp, CSR_MSCRATCH, sp
+ csrrw sp, mscratch, sp
- // save previous registers to stack
+ // allocate space for eframe_t
addi sp, sp, - (32 * 4)
- sw x1, 0x04(sp)
- sw x3, 0x0C(sp)
- sw x4, 0x10(sp)
- sw x5, 0x14(sp)
- sw x6, 0x18(sp)
- sw x7, 0x1C(sp)
- sw x8, 0x20(sp)
- sw x9, 0x24(sp)
- sw x10, 0x28(sp)
- sw x11, 0x2C(sp)
- sw x12, 0x30(sp)
- sw x13, 0x34(sp)
- sw x14, 0x38(sp)
- sw x15, 0x3C(sp)
- sw x16, 0x40(sp)
- sw x17, 0x44(sp)
- sw x18, 0x48(sp)
- sw x19, 0x4C(sp)
- sw x20, 0x50(sp)
- sw x21, 0x54(sp)
- sw x22, 0x58(sp)
- sw x23, 0x5C(sp)
- sw x24, 0x60(sp)
- sw x25, 0x64(sp)
- sw x26, 0x68(sp)
- sw x27, 0x6C(sp)
- sw x28, 0x70(sp)
- sw x29, 0x74(sp)
- sw x30, 0x78(sp)
- sw x31, 0x7C(sp)
- mv a0, sp
- // save previous pc (hw stashed it in MEPC)
- csrr t0, CSR_MEPC
- sw t0, 0x00(sp)
+ // save the tframe_t
+ sw ra, 0x00(sp)
+ sw t0, 0x04(sp)
+ sw t1, 0x08(sp)
+ sw t2, 0x0C(sp)
+ sw t3, 0x10(sp)
+ sw t4, 0x14(sp)
+ sw t5, 0x18(sp)
+ sw t6, 0x1C(sp)
+ sw a0, 0x20(sp)
+ sw a1, 0x24(sp)
+ sw a2, 0x28(sp)
+ sw a3, 0x2C(sp)
+ sw a4, 0x30(sp)
+ sw a5, 0x34(sp)
+ sw a6, 0x38(sp)
+ sw a7, 0x3C(sp)
- // save previous sp (we stashed it in MSCRATCH)
- csrr t0, CSR_MSCRATCH
- sw t0, 0x08(sp)
+ // save the cframe_t
+ csrr t0, mepc
+ csrr t1, mscratch
+ sw t0, 0x40(sp) // pc
+ sw t1, 0x44(sp) // sp
+ sw gp, 0x48(sp)
+ sw tp, 0x4C(sp)
+ sw s0, 0x50(sp)
+ sw s1, 0x54(sp)
+ sw s2, 0x58(sp)
+ sw s3, 0x5C(sp)
+ sw s4, 0x60(sp)
+ sw s5, 0x64(sp)
+ sw s6, 0x68(sp)
+ sw s7, 0x6C(sp)
+ sw s8, 0x70(sp)
+ sw s9, 0x74(sp)
+ sw s10, 0x78(sp)
+ sw s11, 0x7C(sp)
+ // call into C handler
+ mv a0, sp
jal mach_exception_handler
- // save machine sp back into SSCRATCH
+ // restore trap sp to mscratch
addi t0, sp, (32 * 4)
- csrw CSR_MSCRATCH, t0
+ csrw mscratch, t0
- // return pc goes into MEPC for mret
- lw t0, 0x00(sp)
- csrw CSR_MEPC, t0
+ // return pc goes into mepc for mret
+ lw t1, 0x40(sp) // pc
+ csrw mepc, t1
- // restore remaining registers
- lw x1, 0x04(sp)
- lw x3, 0x0C(sp)
- lw x4, 0x10(sp)
- lw x5, 0x14(sp)
- lw x6, 0x18(sp)
- lw x7, 0x1C(sp)
- lw x8, 0x20(sp)
- lw x9, 0x24(sp)
- lw x10, 0x28(sp)
- lw x11, 0x2C(sp)
- lw x12, 0x30(sp)
- lw x13, 0x34(sp)
- lw x14, 0x38(sp)
- lw x15, 0x3C(sp)
- lw x16, 0x40(sp)
- lw x17, 0x44(sp)
- lw x18, 0x48(sp)
- lw x19, 0x4C(sp)
- lw x20, 0x50(sp)
- lw x21, 0x54(sp)
- lw x22, 0x58(sp)
- lw x23, 0x5C(sp)
- lw x24, 0x60(sp)
- lw x25, 0x64(sp)
- lw x26, 0x68(sp)
- lw x27, 0x6C(sp)
- lw x28, 0x70(sp)
- lw x29, 0x74(sp)
- lw x30, 0x78(sp)
- lw x31, 0x7C(sp)
+ // restore registers from cframe_t
+ lw gp, 0x48(sp)
+ lw tp, 0x4C(sp)
+ lw s0, 0x50(sp)
+ lw s1, 0x54(sp)
+ lw s2, 0x58(sp)
+ lw s3, 0x5C(sp)
+ lw s4, 0x60(sp)
+ lw s5, 0x64(sp)
+ lw s6, 0x68(sp)
+ lw s7, 0x6C(sp)
+ lw s8, 0x70(sp)
+ lw s9, 0x74(sp)
+ lw s10, 0x78(sp)
+ lw s11, 0x7C(sp)
- lw sp, 0x08(sp)
+ // restore registers from tframe_t
+ lw ra, 0x00(sp)
+ lw t0, 0x04(sp)
+ lw t1, 0x08(sp)
+ lw t2, 0x0C(sp)
+ lw t3, 0x10(sp)
+ lw t4, 0x14(sp)
+ lw t5, 0x18(sp)
+ lw t6, 0x1C(sp)
+ lw a0, 0x20(sp)
+ lw a1, 0x24(sp)
+ lw a2, 0x28(sp)
+ lw a3, 0x2C(sp)
+ lw a4, 0x30(sp)
+ lw a5, 0x34(sp)
+ lw a6, 0x38(sp)
+ lw a7, 0x3C(sp)
+ // restore previous sp last
+ lw sp, 0x44(sp)
+
+ // return from exception
mret
-.globl enter_mode_s
-enter_mode_s: // (a0, a1, svc_pc, svc_sp)
- csrw CSR_MEPC, a2
+.globl exit_mode_m // a0, a1, pc, sp
+exit_mode_m:
+ csrw mepc, a2
mv sp, a3
mret
-
diff --git a/hw/inc/hw/context-switch.h b/hw/inc/hw/context-switch.h
@@ -1,35 +0,0 @@
-// Copyright 2022, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0
-
-#pragma once
-
-#include <stdint.h>
-
-// this layout must match the assembly in context-switch.S
-typedef struct {
- uint32_t pc;
- uint32_t sp;
- uint32_t gp;
- uint32_t tp;
- uint32_t s0;
- uint32_t s1;
- uint32_t s2;
- uint32_t s3;
- uint32_t s4;
- uint32_t s5;
- uint32_t s6;
- uint32_t s7;
- uint32_t s8;
- uint32_t s9;
- uint32_t s10;
- uint32_t s11;
-} rv32_ctxt_t;
-
-// store the current state into prev
-// restore the new state from next
-void context_switch(rv32_ctxt_t* prev, rv32_ctxt_t* next);
-
-// bootstrap for a new context
-// will call s2(s0, s1)
-// and call context_exit() should it return
-void context_entry(void);
diff --git a/hw/inc/hw/context.h b/hw/inc/hw/context.h
@@ -0,0 +1,118 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#pragma once
+
+#include <stdint.h>
+
+// cframe - Context Frame
+// contains the 16 callee-save and global registers
+typedef struct cframe {
+ uint32_t pc;
+ uint32_t sp;
+ uint32_t gp;
+ uint32_t tp;
+ uint32_t s0;
+ uint32_t s1;
+ uint32_t s2;
+ uint32_t s3;
+ uint32_t s4;
+ uint32_t s5;
+ uint32_t s6;
+ uint32_t s7;
+ uint32_t s8;
+ uint32_t s9;
+ uint32_t s10;
+ uint32_t s11;
+} cframe_t;
+
+// tframe - Trap Frame
+// contains the 16 caller-save and temporary registers
+// as well as the pc
+typedef struct tframe {
+ uint32_t ra;
+ uint32_t t0;
+ uint32_t t1;
+ uint32_t t2;
+ uint32_t t3;
+ uint32_t t4;
+ uint32_t t5;
+ uint32_t t6;
+ uint32_t a0;
+ uint32_t a1;
+ uint32_t a2;
+ uint32_t a3;
+ uint32_t a4;
+ uint32_t a5;
+ uint32_t a6;
+ uint32_t a7;
+
+ uint32_t pc;
+ uint32_t _0;
+ uint32_t _1;
+ uint32_t _2;
+} tframe_t;
+
+// eframe - Exception Frame
+// contains all general registers
+// It stacks a cframe on an iframe
+typedef struct eframe {
+ uint32_t ra;
+ uint32_t t0;
+ uint32_t t1;
+ uint32_t t2;
+ uint32_t t3;
+ uint32_t t4;
+ uint32_t t5;
+ uint32_t t6;
+ uint32_t a0;
+ uint32_t a1;
+ uint32_t a2;
+ uint32_t a3;
+ uint32_t a4;
+ uint32_t a5;
+ uint32_t a6;
+ uint32_t a7;
+
+ uint32_t pc;
+ uint32_t sp;
+ uint32_t gp;
+ uint32_t tp;
+ uint32_t s0;
+ uint32_t s1;
+ uint32_t s2;
+ uint32_t s3;
+ uint32_t s4;
+ uint32_t s5;
+ uint32_t s6;
+ uint32_t s7;
+ uint32_t s8;
+ uint32_t s9;
+ uint32_t s10;
+ uint32_t s11;
+} eframe_t;
+
+// save register state into from and restore it from to
+void context_switch(cframe_t* from, cframe_t* to);
+
+// helper function which calls s2(s0, s1)
+void context_entry(void);
+
+// trap vector
+// saves register on stack in tframe_t or eframe_t
+// calls interrupt_handler() or exception_handler()
+void trap_entry(void);
+
+// restores tframe_t from stack and return from interrupt
+void trap_exit(void);
+
+// restores eframe_t from stack and return from exception
+void exception_exit(void);
+
+// debug helpers
+void xprint_m_exception(eframe_t* ef);
+void xprint_s_exception(eframe_t* ef);
+
+// called from trap_entry() to handle interrupts or exceptions
+void interrupt_handler(void);
+void exception_handler(eframe_t* ef);
diff --git a/hw/inc/hw/debug.h b/hw/inc/hw/debug.h
@@ -13,6 +13,3 @@ int xgetc(void);
// debug-printf.c -- calls xputs()
void xprintf(const char* fmt, ...);
-// print-exception.c -- calls xprintf()
-void xprint_exception(uint32_t regs[32]);
-
diff --git a/hw/src/context-switch.S b/hw/src/context-switch.S
@@ -23,6 +23,7 @@ context_switch:
sw s9, 0x34(a0)
sw s10, 0x38(a0)
sw s11, 0x3C(a0)
+
// load new context from next
lw ra, 0x00(a1)
lw sp, 0x04(a1)
@@ -40,13 +41,17 @@ context_switch:
lw s9, 0x34(a1)
lw s10, 0x38(a1)
lw s11, 0x3C(a1)
+
// return to new context
ret
+// startup helper
+// calls routine in s2 with s0, s1 as arguments
+// then calls thread_exit() if that routine returns
.globl context_entry
context_entry:
mv a0, s0
mv a1, s1
jalr s2
- j context_exit
+ j thread_exit
diff --git a/hw/src/print-exception.c b/hw/src/print-exception.c
@@ -3,6 +3,7 @@
#include <hw/debug.h>
#include <hw/riscv.h>
+#include <hw/context.h>
#include <hw/intrinsics.h>
static const char* cause_name(uint32_t n) {
@@ -38,20 +39,40 @@ static const char* mode_name(uint32_t n) {
}
}
-void xprint_exception(uint32_t regs[32]) {
- uint32_t mcause = csr_read(CSR_MCAUSE);
+static void xprint_regs(eframe_t* ef, uint32_t xstatus, uint32_t xcause, uint32_t xtval) {
+ xprintf("pc %08x ra %08x sp %08x gp %08x xstatus %08x\n",
+ ef->pc, ef->ra, ef->sp, ef->gp, xstatus);
+ xprintf("tp %08x t0 %08x t1 %08x t2 %08x xcause %08x\n",
+ ef->tp, ef->t0, ef->t1, ef->t2, xcause);
+ xprintf("fp %08x s1 %08x a0 %08x a1 %08x xtval %08x\n",
+ ef->s0, ef->s1, ef->a0, ef->a1, xtval);
+ xprintf("a2 %08x a3 %08x a4 %08x a5 %08x\n",
+ ef->a2, ef->a3, ef->a4, ef->a5);
+ xprintf("a6 %08x a7 %08x s2 %08x s3 %08x\n",
+ ef->a6, ef->a7, ef->s2, ef->s3);
+ xprintf("s4 %08x s5 %08x s6 %08x s7 %08x\n",
+ ef->s4, ef->s5, ef->s6, ef->s7);
+ xprintf("s8 %08x s9 %08x 10 %08x 11 %08x\n",
+ ef->s8, ef->s9, ef->s10, ef->s11);
+ xprintf("t3 %08x t4 %08x t5 %08x t6 %08x\n",
+ ef->t3, ef->t4, ef->t5, ef->t6);
+}
+
+void xprint_m_exception(eframe_t* ef) {
uint32_t mstatus = csr_read(CSR_MSTATUS);
+ uint32_t mcause = csr_read(CSR_MCAUSE);
uint32_t mtval = csr_read(CSR_MTVAL);
-
xprintf("** %s (in %s mode)\n\n", cause_name(mcause),
mode_name((mstatus >> MSTATUS_MPP_SHIFT) & 3));
+ xprint_regs(ef, mstatus, mcause, mtval);
- xprintf("pc %08x ra %08x sp %08x gp %08x MSTATUS %08x\n",
- regs[0], regs[1], regs[2], regs[3], mstatus);
- xprintf("tp %08x t0 %08x t1 %08x t2 %08x MCAUSE %08x\n",
- regs[4], regs[5], regs[6], regs[7], mcause);
- xprintf("fp %08x s1 %08x a0 %08x a1 %08x MTVAL %08x\n",
- regs[8], regs[9], regs[10], regs[11], mtval);
- xprintf("a2 %08x a3 %08x a4 %08x a5 %08x\n",
- regs[12], regs[13], regs[14], regs[15]);
}
+void xprint_s_exception(eframe_t* ef) {
+ uint32_t sstatus = csr_read(CSR_SSTATUS);
+ uint32_t scause = csr_read(CSR_SCAUSE);
+ uint32_t stval = csr_read(CSR_STVAL);
+ xprintf("** %s (in %s mode)\n\n", cause_name(scause),
+ mode_name((sstatus >> SSTATUS_SPP_SHIFT) & 1));
+ xprint_regs(ef, sstatus, scause, stval);
+}
+
diff --git a/hw/src/trap-entry-single-stack.S b/hw/src/trap-entry-single-stack.S
@@ -0,0 +1,134 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+// This file provides assembly glue for handling traps
+// (interrupts or exceptions) and safely saving and
+// restoring the processor state of the code running
+// when the trap happened.
+
+// It assume a single stack setup -- when an interrupt
+// or exception occurs, the state will be saved on the
+// active stack that sp is pointing to.
+
+// It will call into interrupt_handler() or exception_handler()
+// to process the interrupt or exception.
+
+// For interrupts, only the registers that must be saved
+// are saved (the others are callee-save so the C code
+// called into will save them if necessary).
+
+// For exceptions, ALL registers are saved so that the
+// exception handler my inspect, display, or modify them
+// as necesary.
+
+// hw/context.h defines structures tframe_t and eframe_t
+// that correspond to how the registers are saved on the
+// stack
+
+.global trap_entry
+trap_entry:
+ // reserve stack space for a full eframe_t
+ addi sp, sp, - (32 * 4)
+
+ // save caller-save registers (tframe_t)
+ sw ra, 0x00(sp)
+ sw t0, 0x04(sp)
+ sw t1, 0x08(sp)
+ sw t2, 0x0C(sp)
+ sw t3, 0x10(sp)
+ sw t4, 0x14(sp)
+ sw t5, 0x18(sp)
+ sw t6, 0x1C(sp)
+ sw a0, 0x20(sp)
+ sw a1, 0x24(sp)
+ sw a2, 0x28(sp)
+ sw a3, 0x2C(sp)
+ sw a4, 0x30(sp)
+ sw a5, 0x34(sp)
+ sw a6, 0x38(sp)
+ sw a7, 0x3C(sp)
+
+ // save pc which hw stashed in SEPC
+ csrr t0, sepc
+ sw t0, 0x40(sp)
+
+ // if the scause high bit is clear, it is an exception
+ csrr t1, scause
+ bge t1, zero, exception_entry
+
+ // otherwise it is an interrupt, call interrupt_handler()
+ jal interrupt_handler
+
+.globl trap_exit
+trap_exit:
+ // return pc goes into sepc for sret
+ lw t0, 0x40(sp)
+ csrw sepc, t0
+
+ // restore the caller-save registers
+ lw ra, 0x00(sp)
+ lw t0, 0x04(sp)
+ lw t1, 0x08(sp)
+ lw t2, 0x0C(sp)
+ lw t3, 0x10(sp)
+ lw t4, 0x14(sp)
+ lw t5, 0x18(sp)
+ lw t6, 0x1C(sp)
+ lw a0, 0x20(sp)
+ lw a1, 0x24(sp)
+ lw a2, 0x28(sp)
+ lw a3, 0x2C(sp)
+ lw a4, 0x30(sp)
+ lw a5, 0x34(sp)
+ lw a6, 0x38(sp)
+ lw a7, 0x3C(sp)
+
+ // release the stack space
+ addi sp, sp, (32 * 4)
+
+ // return from trap
+ sret
+
+exception_entry:
+ // save the callee-save registers (cframe_t)
+ // pc already stored at 0x40(sp)
+ addi t0, sp, (32 * 4)
+ sw t0, 0x44(sp)
+ sw gp, 0x48(sp)
+ sw tp, 0x4C(sp)
+ sw s0, 0x50(sp)
+ sw s1, 0x54(sp)
+ sw s2, 0x58(sp)
+ sw s3, 0x5C(sp)
+ sw s4, 0x60(sp)
+ sw s5, 0x64(sp)
+ sw s6, 0x68(sp)
+ sw s7, 0x6C(sp)
+ sw s8, 0x70(sp)
+ sw s9, 0x74(sp)
+ sw s10, 0x78(sp)
+ sw s11, 0x7C(sp)
+
+ // call exception_handler() passing eframe_t*
+ // as the first argument
+ mv a0, sp
+ jal exception_handler
+
+.globl exception_exit
+exception_exit:
+ lw gp, 0x48(sp)
+ lw tp, 0x4C(sp)
+ lw s0, 0x50(sp)
+ lw s1, 0x54(sp)
+ lw s2, 0x58(sp)
+ lw s3, 0x5C(sp)
+ lw s4, 0x60(sp)
+ lw s5, 0x64(sp)
+ lw s6, 0x68(sp)
+ lw s7, 0x6C(sp)
+ lw s8, 0x70(sp)
+ lw s9, 0x74(sp)
+ lw s10, 0x78(sp)
+ lw s11, 0x7C(sp)
+
+ j trap_exit
diff --git a/misc/traps.c b/misc/traps.c
@@ -1,68 +0,0 @@
-// Copyright 2022, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0
-
-#include <hw/riscv.h>
-#include <hw/debug.h>
-#include <hw/platform.h>
-
-#define MEMORY_TOP (DRAM_BASE + DRAM_SIZE)
-
-#define SVC_SP (MEMORY_TOP - 8*1024)
-#define USER_SP (MEMORY_TOP - 16*1024)
-
-extern void svc_exception_entry(void);
-void enter_mode_u(uint32_t a0, uint32_t a1, uint32_t user_pc, uint32_t user_sp);
-
-void svc_exception_handler(uint32_t regs[32]) {
- uint32_t cause = csr_read(CSR_SCAUSE);
- uint32_t val = csr_read(CSR_STVAL);
- xprintf("\nSUPERVISOR EXCEPTION %08x %08x %08x\n",
- cause, val, (unsigned) regs);
-
- xprintf("pc %08x ra %08x sp %08x gp %08x\n",
- regs[0], regs[1], regs[2], regs[3]);
- xprintf("tp %08x t0 %08x t1 %08x t2 %08x\n",
- regs[4], regs[5], regs[6], regs[7]);
- xprintf("fp %08x s1 %08x a0 %08x a1 %08x\n",
- regs[8], regs[9], regs[10], regs[11]);
- xprintf("a2 %08x a3 %08x a4 %08x a5 %08x\n\n",
- regs[12], regs[13], regs[14], regs[15]);
-
- if (cause == EXCn_ECALL_UMODE) {
- // advance return address to next instr
- regs[0] += 4;
- xprintf("RETURNING FROM ECALL\n");
- return;
- }
-
- xprintf("HALTED\n");
- for (;;) ;
-}
-
-void user_start(uint32_t hartid, uint32_t fdt) {
- xprintf("Hello, User Mode hartid=%08x fdt=%08x\n", hartid, fdt);
-
- // syscall
- asm volatile ("ecall");
-
- // illegal write from user mode
- csr_write(CSR_MEPC, 0x42);
-
- xprintf("\nSTOP\n");
- for (;;) ;
-}
-
-void start(uint32_t hartid, uint32_t fdt) {
- xprintf("Hello, Trap Test %08x %08x\n", hartid, fdt);
-
- // set svc exception vector and stack pointer
- csr_write(CSR_STVEC, (uintptr_t) svc_exception_entry);
- csr_write(CSR_SSCRATCH, SVC_SP);
-
- //csr_set(CSR_SIE, INTb_SVC_SW);
-
- enter_mode_u(hartid, fdt, (uintptr_t)user_start, USER_SP);
-
- for (;;) ;
-}
-
diff --git a/project/traps.app.mk b/project/traps.app.mk
@@ -1,6 +0,0 @@
-
-MOD_NAME := traps
-MOD_SRC := hw/src/start.S misc/traps-entry.S misc/traps.c
-MOD_SRC += hw/src/debug-printf.c hw/src/debug-io.c
-MOD_LIB := c
-include make/app.mk