os-workshop

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Mbios/bios.c | 159++++++++++++-------------------------------------------------------------------
Mbios/bios.h | 10+++++++++-
Mbios/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