commit 5114163ca82270239d131ba66f6d3cd07f6ba356
parent 5a586737ea493d0e3de55b44fb063e6adee5eaf3
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 7 May 2022 10:17:39 -0700
bios; tidy up a bunch
- remove dead code and test code
- detect qemu and only program PMP in that case
- general cleanup
Diffstat:
M | bios/bios.c | | | 159 | ++++++++++++------------------------------------------------------------------- |
M | bios/bios.h | | | 10 | +++++++++- |
M | bios/entry.S | | | 60 | ------------------------------------------------------------ |
3 files changed, 33 insertions(+), 196 deletions(-)
diff --git a/bios/bios.c b/bios/bios.c
@@ -9,15 +9,10 @@
#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)
-
+// we expect the supervisor program to be in memory after the end of the BIOS
#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);
-
-static const char* _cause(uint32_t n) {
+static const char* cause_name(uint32_t n) {
if (n & 0x80000000U) {
return "Interrupt";
} else {
@@ -41,7 +36,7 @@ static const char* _cause(uint32_t n) {
return "Unknown";
}
-static const char* _mode(uint32_t n) {
+static const char* mode_name(uint32_t n) {
switch (n) {
case 0: return "User";
case 1: return "Supervisor";
@@ -54,27 +49,9 @@ void mach_exception_handler(uint32_t regs[32]) {
uint32_t mcause = csr_read(CSR_MCAUSE);
uint32_t mstatus = csr_read(CSR_MSTATUS);
uint32_t mtval = csr_read(CSR_MTVAL);
+ uint32_t mtinst = 0; //csr_read(CSR_MTINST); // not supported
-#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
+#if EMULATE_MISSING_CSR_READS
// fragile: no mtval on qemu
if (mcause == 2) mtval = *((uint32_t*) regs[0]);
@@ -88,9 +65,8 @@ void mach_exception_handler(uint32_t regs[32]) {
#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("** %s (in %s mode)\n\n", cause_name(mcause),
+ mode_name((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);
@@ -104,36 +80,35 @@ void mach_exception_handler(uint32_t regs[32]) {
for (;;) ;
}
+// interrupts and exceptions to delegate to supervisor mode
#define INT_LIST (INTb_SVC_SW|INTb_SVC_TIMER|INTb_SVC_EXTERN)
#define EXC_LIST (EXCb_ECALL_UMODE)
-#define CLINT_BASE 0x2000000
-#define TIME_TICK 10000000
-
void start(uint32_t hartid, uint32_t fdt) {
- xprintf("** Frobozz Magic BIOS v0.1 **\n");
+ xprintf("\n** Frobozz Magic BIOS v0.1 **\n\n");
+
+ int qemu = (csr_read(CSR_MVENDORID) == 0);
// delegate interrupts and exceptions
- //xprintf("MIDELEG %08x MEDELEG %08x\n",
- // csr_read(CSR_MIDELEG), csr_read(CSR_MEDELEG));
csr_set(CSR_MIDELEG, INT_LIST);
csr_set(CSR_MEDELEG, EXC_LIST);
- //xprintf("MIDELEG %08x MEDELEG %08x\n\n",
- // csr_read(CSR_MIDELEG), csr_read(CSR_MEDELEG));
// 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));
// set mach exception vector and stack pointer
csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) );
+ // use the free ram below the supervisor entry as our exception stack
+ csr_write(CSR_MSCRATCH, SVC_ENTRY);
+
+#if USE_CLINT_TIMER
+#define CLINT_BASE 0x2000000
+#define TIME_TICK 10000000
+
// 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;
@@ -146,102 +121,16 @@ void start(uint32_t hartid, uint32_t fdt) {
*((uint64_t*) mtimecmp) = next;
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);
-
-#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);
+ // QEMU currently emulates memory protection, which we must appease
+ if (qemu) {
+ // 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);
}
-#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
+ xprintf("SVC ENTRY @0x%08x\n\n", SVC_ENTRY);
enter_mode_s(hartid, fdt, SVC_ENTRY, 0);
}
diff --git a/bios/bios.h b/bios/bios.h
@@ -1,6 +1,6 @@
+#pragma once
// offsets into the interrupt workspace
-
#define IWS_TIMECMP 0x00
#define IWS_TICKINC 0x04
#define IWS_SAVE0 0x08
@@ -10,3 +10,11 @@
#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);
+
+#endif
+
diff --git a/bios/entry.S b/bios/entry.S
@@ -6,66 +6,6 @@
.globl mach_exception_entry
mach_exception_entry:
- j mach_exception
- j .
- j .
- j .
- j .
- j .
- j .
-mach_timer_entry:
- // swap active sp with value in MSCRATCH (exception stack)
- // interupts have been disabled on exception entry
- csrrw sp, CSR_MSCRATCH, sp
-
- // use the workspace above the exception stack to save
- // registers and get necessary data
- sw t0, IWS_SAVE0(sp)
- sw t1, IWS_SAVE1(sp)
- sw t2, IWS_SAVE2(sp)
- sw t3, IWS_SAVE3(sp)
- sw t4, IWS_SAVE4(sp)
-
- lw t0, IWS_TIMECMP(sp)
- lw t1, IWS_TICKINC(sp)
-
- // read last match lo/hi
- lw t2, 0(t0)
- lw t3, 4(t0)
-
- add t1, t2, t1
- // t4 is carry bit
- sltu t4, t1, t2
- add t3, t4, t3
-
- // avoid spurious irq by ensuring we can't roll back
- li t4, -1
- sw t4, 0(t0)
-
- sw t3, 4(t0)
- sw t1, 0(t0)
-
- // set S MODE SW INT pending
- csrsi CSR_SIP, INTb_SVC_SW
-
-#if 0
- li t0, 0x10000000
- li t1, '!'
- sb t1, 0(t0)
-#endif
-
- // restore registers
- lw t0, IWS_SAVE0(sp)
- lw t1, IWS_SAVE1(sp)
- lw t2, IWS_SAVE2(sp)
- lw t3, IWS_SAVE3(sp)
- lw t4, IWS_SAVE4(sp)
-
- // swap back to previous sp
- csrrw sp, CSR_MSCRATCH, sp
- mret
-
-mach_exception:
// swap active sp with value in MSCRATCH (exception stack)
// interupts have been disabled on exception entry
csrrw sp, CSR_MSCRATCH, sp