os-workshop

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

commit 7c287998a02dd6c4033142c34776fdaa04a0fb3d
parent 377b132bd6f86892da7f077ce8eb1ba1ce95d200
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 25 Apr 2022 01:07:47 -0700

bios: more features

- setup periodic timer (m mode)
- kick the svc sw interrupt when the timer interval rolls
- use vectored interrupts to split timer irqs from the fault handler
- use space above the machine stack for timer irq state and storage
- add bios.mk project file

Diffstat:
Mbios/bios.c | 58+++++++++++++++++++++++++++++++++++-----------------------
Abios/bios.h | 12++++++++++++
Mbios/entry.S | 69++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Aproject/bios.mk | 6++++++
4 files changed, 115 insertions(+), 30 deletions(-)

diff --git a/bios/bios.c b/bios/bios.c @@ -2,11 +2,14 @@ // Licensed under the Apache License, Version 2.0 #include <hw/riscv.h> +#include <hw/riscv-clint.h> #include <hw/debug.h> +#include "bios.h" #define SVC_ENTRY 0x80004000 -extern void mach_exception_entry(void); +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) { if (n & 0x80000000U) { @@ -43,10 +46,9 @@ 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\n", cause(n)); - n = csr_read(CSR_MSTATUS); - xprintf("** in %s mode\n\n", mode((n >> MSTATUS_MPP_SHIFT) & 3)); + 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]); @@ -60,26 +62,13 @@ void mach_exception_handler(uint32_t regs[32]) { for (;;) ; } -void enter_mode_u(uint32_t a0, uint32_t a1, uint32_t pc, uint32_t sp); -void enter_mode_s(uint32_t a0, uint32_t a1, uint32_t pc, uint32_t sp); - -#if 0 -void user_start(uint32_t user_pc, uint32_t user_sp) { - xprintf("Hello, User Mode %08x %08x\n", user_pc, user_sp); - - // illegal write from user mode - // csr_write(CSR_MEPC, 0x42); - - // syscall - asm volatile ("ecall"); - - for (;;) ; -} -#endif - #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 +//#define TIME_TICK 0x10000000 + void start(uint32_t hartid, uint32_t fdt) { xprintf("** Frobozz Magic BIOS v0.1 **\n"); @@ -96,9 +85,32 @@ void start(uint32_t hartid, uint32_t fdt) { //xprintf("MSTATUS %08x\n", csr_read(CSR_MSTATUS)); // set mach exception vector and stack pointer - csr_write(CSR_MTVEC, (uintptr_t) mach_exception_entry); - csr_write(CSR_MSCRATCH, SVC_ENTRY); + csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) | 1); + + // leaving room for the timer interrupt workspace above the stack + csr_write(CSR_MSCRATCH, SVC_ENTRY - IWS_SIZE); + + xprintf("HARTID %08x\n", hartid); + + uint32_t* iws = (void*) (SVC_ENTRY - IWS_SIZE); + uint32_t mtimecmp = CLINT_BASE + CLINT_MTIMECMP(hartid); + uint32_t mtime = CLINT_BASE + CLINT_MTIME; + + iws[IWS_TIMECMP/4] = mtimecmp; + iws[IWS_TICKINC/4] = TIME_TICK; + + // set initial tick + uint64_t next = *((uint64_t*) mtime) + TIME_TICK; + *((uint64_t*) mtimecmp) = next; + + csr_set(CSR_MIE, INTb_MACH_TIMER); + xprintf("MIE %08x\n", csr_read(CSR_MIE)); + + // 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 (;;) ; enter_mode_s(hartid, fdt, SVC_ENTRY, 0); } diff --git a/bios/bios.h b/bios/bios.h @@ -0,0 +1,12 @@ + +// 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 + diff --git a/bios/entry.S b/bios/entry.S @@ -2,15 +2,76 @@ // Licensed under the Apache License, Version 2.0 #include <hw/riscv.h> +#include "bios.h" .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 // save previous registers to stack - addi sp, sp, - 32 * 4 + addi sp, sp, - (32 * 4) sw x1, 0x04(sp) sw x3, 0x0C(sp) sw x4, 0x10(sp) @@ -54,12 +115,6 @@ mach_exception_entry: j mach_exception_handler j . -.globl enter_mode_u -enter_mode_u: // (a0, a1, user_pc, user_sp) - csrw CSR_SEPC, a2 - mv sp, a3 - sret - .globl enter_mode_s enter_mode_s: // (a0, a1, svc_pc, svc_sp) csrw CSR_MEPC, a2 diff --git a/project/bios.mk b/project/bios.mk @@ -0,0 +1,6 @@ + +APP_NAME := bios +APP_SRC := hw/src/start.S bios/entry.S bios/bios.c +APP_SRC += hw/src/debug.c $(LIBC_SRC) +APP_LDSCRIPT := hw/bios.ld +include make/app.mk