commit fdcd2ad2e2af729897355b28944d5827db62e834
parent f2d7f133a43bd5fe6ea51b7ae3e0f9e2d2c142e4
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 4 May 2022 17:06:43 -0700
bios: mostly a lot of debug code that will be going away soon
Diffstat:
M | bios/bios.c | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
1 file changed, 151 insertions(+), 20 deletions(-)
diff --git a/bios/bios.c b/bios/bios.c
@@ -6,12 +6,18 @@
#include <hw/debug.h>
#include "bios.h"
-#define SVC_ENTRY 0x80004000
+#include <hw/platform.h>
+#include <hw/litex.h>
+
+#define uart_rd(a) io_rd32(UART0_BASE + LX_UART_ ## a)
+#define uart_wr(a,v) io_wr32(UART0_BASE + LX_UART_ ## a, v)
+
+#define SVC_ENTRY (DRAM_BASE + BIOS_SIZE)
void mach_exception_entry(void);
void enter_mode_s(uint32_t a0, uint32_t a1, uint32_t pc, uint32_t sp);
-const char* cause(uint32_t n) {
+static const char* _cause(uint32_t n) {
if (n & 0x80000000U) {
return "Interrupt";
} else {
@@ -35,7 +41,7 @@ const char* cause(uint32_t n) {
return "Unknown";
}
-const char* mode(uint32_t n) {
+static const char* _mode(uint32_t n) {
switch (n) {
case 0: return "User";
case 1: return "Supervisor";
@@ -45,19 +51,55 @@ const char* mode(uint32_t n) {
}
void mach_exception_handler(uint32_t regs[32]) {
- uint32_t n = csr_read(CSR_MCAUSE);
- uint32_t m = csr_read(CSR_MSTATUS);
- xprintf("\n** MACHINE EXCEPTION %08x %08x\n", n, csr_read(CSR_MTVAL));
- xprintf("** %s (in %s mode)\n\n", cause(n), mode((m >> MSTATUS_MPP_SHIFT) & 3));
-
- 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",
- regs[12], regs[13], regs[14], regs[15]);
+ uint32_t mcause = csr_read(CSR_MCAUSE);
+ uint32_t mstatus = csr_read(CSR_MSTATUS);
+ uint32_t mtval = csr_read(CSR_MTVAL);
+
+#if IRQ_TEST
+ if (mcause == 0x8000000b) {
+ xprintf("IP %x\n", csr_read(CSR_M_INTC_PENDING));
+ if (uart_rd(EV_PENDING) & LX_UART_EVb_RX) {
+ unsigned ch = uart_rd(RX);
+ uart_wr(EV_PENDING, LX_UART_EVb_RX);
+ //csr_clr(CSR_MIP, INTb_MACH_EXTERN);
+ xputc('.');
+ xputc(ch);
+ } else {
+ xputc('?');
+ //csr_clr(CSR_MIP, INTb_MACH_EXTERN);
+ }
+ csr_write(CSR_MIP, 0);
+ //csr_write(CSR_M_INTC_PENDING, 1);
+ return;
+ }
+#endif
+
+#if EMULATE_MISSING_CSRS
+ // 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 -> r%u\n", regs[0], rd);
+ regs[rd] = 0xDEADBEEF;
+ regs[0] += 4;
+ return;
+ }
+#endif
+
+ xprintf("\n** MACHINE EXCEPTION **\n");
+ uint32_t mtinst = 0; //csr_read(CSR_MTINST);
+ xprintf("** %s (in %s mode)\n\n", _cause(mcause),
+ _mode((mstatus >> MSTATUS_MPP_SHIFT) & 3));
+
+ 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 MTINST %08x\n",
+ regs[12], regs[13], regs[14], regs[15], mtinst);
xprintf("\n** HALT\n");
for (;;) ;
}
@@ -67,7 +109,6 @@ void mach_exception_handler(uint32_t regs[32]) {
#define CLINT_BASE 0x2000000
#define TIME_TICK 10000000
-//#define TIME_TICK 0x10000000
void start(uint32_t hartid, uint32_t fdt) {
xprintf("** Frobozz Magic BIOS v0.1 **\n");
@@ -82,16 +123,17 @@ void start(uint32_t hartid, uint32_t fdt) {
// set previous status to S_MODE, previous interrupt status ENABLED
csr_write(CSR_MSTATUS, (PRIV_S << MSTATUS_MPP_SHIFT) | MSTATUS_MPIE);
- //xprintf("MSTATUS %08x\n", csr_read(CSR_MSTATUS));
+ xprintf("MSTATUS %08x\n", csr_read(CSR_MSTATUS));
// set mach exception vector and stack pointer
- csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) | 1);
+ csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) );
// leaving room for the timer interrupt workspace above the stack
csr_write(CSR_MSCRATCH, SVC_ENTRY - IWS_SIZE);
xprintf("HARTID %08x\n", hartid);
+#if USE_CLINT_TIMER
uint32_t* iws = (void*) (SVC_ENTRY - IWS_SIZE);
uint32_t mtimecmp = CLINT_BASE + CLINT_MTIMECMP(hartid);
uint32_t mtime = CLINT_BASE + CLINT_MTIME;
@@ -105,12 +147,101 @@ void start(uint32_t hartid, uint32_t fdt) {
csr_set(CSR_MIE, INTb_MACH_TIMER);
xprintf("MIE %08x\n", csr_read(CSR_MIE));
+#endif
// U/S allow access to all memory
csr_write(CSR_PMPCFG(0), PMP_CFG_A_TOR | PMP_CFG_X | PMP_CFG_W | PMP_CFG_R);
csr_write(CSR_PMPADDR(0), 0xFFFFFFFF);
- //for (;;) ;
+#if UART_DEBUG_GOOP
+ uart_wr(EV_ENABLE, 3);
+ // enable machine mode external interrupts (cpu)
+ csr_set(CSR_MIE, INTb_MACH_EXTERN);
+ xprintf("MIE %08x\n", csr_read(CSR_MIE));
+
+ // enable machine mode interrupts (cpu)
+ csr_set(CSR_MSTATUS, MSTATUS_MIE);
+
+ uart_wr(EV_ENABLE, 0);
+
+ // clear any outstanding UART interrupts
+ uart_wr(EV_PENDING, LX_UART_EVb_RX);
+
+ //csr_set(CSR_M_INTC_PENDING, UART0_IRQb);
+
+ // enable UART0 interrupts (intc)
+ csr_set(CSR_M_INTC_ENABLE, UART0_IRQb);
+
+ // enable RX interrupts (uart0)
+ uart_wr(EV_ENABLE, LX_UART_EVb_RX);
+ xprintf("WHEE!!!\n");
+
+ for (;;) ;
+#endif
+#if MORE_UART_DEBUG
+ for (;;) {
+ while (uart_rd(RXEMPTY)) ;
+ //uart_wr(TX, '.');
+ xprintf("RX %02x %x %x EVP%x EVS%x\n", uart_rd(TX), uart_rd(RXEMPTY), uart_rd(RXFULL),
+uart_rd(EV_PENDING), uart_rd(EV_STATUS));
+// while(uart_rd(RXEMPTY) == 0) xputc('.');
+// uart_wr(TX, (*((volatile uint8_t*) (UART0_BASE + LX_UART_RX)))); //uart_rd(RX));
+// uart_wr(EV_PENDING, LX_UART_EVb_RX);
+ }
+#endif
+
+#if DUMP_CSRS
+#define X(csr) xprintf("%08x " #csr "\n", csr_read(csr))
+
+#define CSR_MTVEC_WO
+#define CSR_MIDELEG_WO
+#define CSR_MEDELEG_WO
+
+ csr_write(CSR_MIDELEG, 0);
+ csr_write(CSR_MEDELEG, 0);
+
+ X(CSR_MVENDORID);
+ X(CSR_MARCHID);
+ X(CSR_MIMPID);
+ X(CSR_MHARTID);
+ X(CSR_MCONFIGPTR);
+ X(CSR_MSTATUS);
+ X(CSR_MISA);
+ X(CSR_MEDELEG);
+ X(CSR_MIDELEG);
+ X(CSR_MIE);
+ X(CSR_MTVEC);
+ X(CSR_MCOUNTEREN);
+ X(CSR_MSTATUSH);
+ X(CSR_MSCRATCH);
+ X(CSR_MEPC);
+ X(CSR_MCAUSE);
+ X(CSR_MTVAL);
+ X(CSR_MIP);
+ X(CSR_MTINST);
+ X(CSR_MTVAL2);
+ X(CSR_MENVCFG);
+ X(CSR_MCYCLE);
+ X(CSR_MINSTRET);
+ X(CSR_SATP);
+ X(CSR_SIP);
+ X(CSR_STVAL);
+ X(CSR_SCAUSE);
+ X(CSR_SEPC);
+ X(CSR_SSCRATCH);
+ X(CSR_SENVCFG);
+ X(CSR_SCOUNTEREN);
+ X(CSR_STVEC);
+ X(CSR_SIE);
+ X(CSR_SSTATUS);
+
+ X(CSR_PMPCFG(0));
+ X(CSR_PMPADDR(0));
+ xprintf("DONE\n");
+
+ for (;;) ;
+#endif
+
enter_mode_s(hartid, fdt, SVC_ENTRY, 0);
}