os-workshop

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

commit df4564a47a27592d88146b40f70052f44037a3c0
parent 4a39106a77b65203f99ca97c29ad260c557efb14
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat,  7 May 2022 23:40:46 -0700

boot: rename 'bios' to 'boot'

- It's more of a second stage bootloader than a BIOS
- The FPGA SoC has a BIOS so things were getting confusing

Diffstat:
MMakefile | 2+-
Dbios/bios.c | 136-------------------------------------------------------------------------------
Dbios/entry.S | 106-------------------------------------------------------------------------------
Aboot/boot.c | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rbios/bios.h -> boot/boot.h | 0
Aboot/entry.S | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rhw/bios.ld -> hw/boot.ld | 0
Mhw/inc/hw/platform.h | 2+-
Dproject/bios.app.mk | 7-------
Aproject/boot.app.mk | 7+++++++
10 files changed, 251 insertions(+), 251 deletions(-)

diff --git a/Makefile b/Makefile @@ -10,7 +10,7 @@ V := @ # defaults for Ubuntu, can override with local.mk XTOOLCHAIN ?= /usr/bin/riscv64-unknown-elf- QEMU ?= /usr/bin/qemu-system-riscv32 -QEMUBIOS := out/bios.elf +QEMUBIOS := out/boot.elf QFLAGS := -machine micro -bios $(QEMUBIOS) QFLAGS.GDB := $(QFLAGS) -gdb tcp::7777 -S diff --git a/bios/bios.c b/bios/bios.c @@ -1,136 +0,0 @@ -// Copyright 2022, Brian Swetland <swetland@frotz.net> -// Licensed under the Apache License, Version 2.0 - -#include <hw/riscv.h> -#include <hw/riscv-clint.h> -#include <hw/debug.h> -#include "bios.h" - -#include <hw/platform.h> -#include <hw/litex.h> - -// we expect the supervisor program to be in memory after the end of the BIOS -#define SVC_ENTRY (DRAM_BASE + BIOS_SIZE) - -static const char* cause_name(uint32_t n) { - if (n & 0x80000000U) { - return "Interrupt"; - } else { - switch(n & 0x7FFFFFFFU) { - case 0: return "Instruction Address Misaligned"; - case 1: return "Instruction Address Fault"; - case 2: return "Illegal Instruction"; - case 3: return "Breakpoint"; - case 4: return "Load Address Misaligned"; - case 5: return "Load Address Fault"; - case 6: return "Store Address Misaligned"; - case 7: return "Store Address Fault"; - case 8: return "User Mode ECALL"; - case 9: return "Supervisor Mode ECALL"; - case 10: return "Machine Mode ECALL"; - case 12: return "Instruction Page Fault"; - case 13: return "Load Page Fault"; - case 14: return "Store Page Fault"; - } - } - return "Unknown"; -} - -static const char* mode_name(uint32_t n) { - switch (n) { - case 0: return "User"; - case 1: return "Supervisor"; - case 3: return "Machine Mode"; - default: return "???"; - } -} - -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 EMULATE_MISSING_CSR_READS - // 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"); - 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); - 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 (;;) ; -} - -// 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) - -void start(uint32_t hartid, uint32_t fdt) { - xprintf("\n** Frobozz Magic BIOS v0.1 **\n\n"); - - int qemu = (csr_read(CSR_MVENDORID) == 0); - - // delegate interrupts and exceptions - csr_set(CSR_MIDELEG, INT_LIST); - csr_set(CSR_MEDELEG, EXC_LIST); - - // set previous status to S_MODE, previous interrupt status ENABLED - csr_write(CSR_MSTATUS, (PRIV_S << MSTATUS_MPP_SHIFT) | MSTATUS_MPIE); - - // 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); - - 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); -#endif - - // 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); - } - - xprintf("SVC ENTRY @0x%08x\n\n", SVC_ENTRY); - enter_mode_s(hartid, fdt, SVC_ENTRY, 0); -} - diff --git a/bios/entry.S b/bios/entry.S @@ -1,106 +0,0 @@ -// Copyright 2022, Brian Swetland <swetland@frotz.net> -// Licensed under the Apache License, Version 2.0 - -#include <hw/riscv.h> -#include "bios.h" - -.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 - - // save previous registers to stack - 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 previous sp (we stashed it in MSCRATCH) - csrr t0, CSR_MSCRATCH - sw t0, 0x08(sp) - - jal mach_exception_handler - - // save machine sp back into SSCRATCH - addi t0, sp, (32 * 4) - csrw CSR_MSCRATCH, t0 - - // return pc goes into MEPC for mret - lw t0, 0x00(sp) - csrw CSR_MEPC, t0 - - // 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) - - lw sp, 0x08(sp) - - mret - -.globl enter_mode_s -enter_mode_s: // (a0, a1, svc_pc, svc_sp) - csrw CSR_MEPC, a2 - mv sp, a3 - mret - diff --git a/boot/boot.c b/boot/boot.c @@ -0,0 +1,136 @@ +// Copyright 2022, Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0 + +#include <hw/riscv.h> +#include <hw/riscv-clint.h> +#include <hw/debug.h> +#include "boot.h" + +#include <hw/platform.h> +#include <hw/litex.h> + +// we expect the supervisor program to be in memory after the end of the bootloader +#define SVC_ENTRY (DRAM_BASE + BOOTLOADER_SIZE) + +static const char* cause_name(uint32_t n) { + if (n & 0x80000000U) { + return "Interrupt"; + } else { + switch(n & 0x7FFFFFFFU) { + case 0: return "Instruction Address Misaligned"; + case 1: return "Instruction Address Fault"; + case 2: return "Illegal Instruction"; + case 3: return "Breakpoint"; + case 4: return "Load Address Misaligned"; + case 5: return "Load Address Fault"; + case 6: return "Store Address Misaligned"; + case 7: return "Store Address Fault"; + case 8: return "User Mode ECALL"; + case 9: return "Supervisor Mode ECALL"; + case 10: return "Machine Mode ECALL"; + case 12: return "Instruction Page Fault"; + case 13: return "Load Page Fault"; + case 14: return "Store Page Fault"; + } + } + return "Unknown"; +} + +static const char* mode_name(uint32_t n) { + switch (n) { + case 0: return "User"; + case 1: return "Supervisor"; + case 3: return "Machine Mode"; + default: return "???"; + } +} + +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 EMULATE_MISSING_CSR_READS + // 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"); + 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); + 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 (;;) ; +} + +// 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) + +void start(uint32_t hartid, uint32_t fdt) { + xprintf("\n** Frobozz Magic Bootloader v0.2 **\n\n"); + + int qemu = (csr_read(CSR_MVENDORID) == 0); + + // delegate interrupts and exceptions + csr_set(CSR_MIDELEG, INT_LIST); + csr_set(CSR_MEDELEG, EXC_LIST); + + // set previous status to S_MODE, previous interrupt status ENABLED + csr_write(CSR_MSTATUS, (PRIV_S << MSTATUS_MPP_SHIFT) | MSTATUS_MPIE); + + // 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); + + 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); +#endif + + // 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); + } + + xprintf("SVC ENTRY @0x%08x\n\n", SVC_ENTRY); + enter_mode_s(hartid, fdt, SVC_ENTRY, 0); +} + diff --git a/bios/bios.h b/boot/boot.h diff --git a/boot/entry.S b/boot/entry.S @@ -0,0 +1,106 @@ +// Copyright 2022, Brian Swetland <swetland@frotz.net> +// Licensed under the Apache License, Version 2.0 + +#include <hw/riscv.h> +#include "boot.h" + +.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 + + // save previous registers to stack + 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 previous sp (we stashed it in MSCRATCH) + csrr t0, CSR_MSCRATCH + sw t0, 0x08(sp) + + jal mach_exception_handler + + // save machine sp back into SSCRATCH + addi t0, sp, (32 * 4) + csrw CSR_MSCRATCH, t0 + + // return pc goes into MEPC for mret + lw t0, 0x00(sp) + csrw CSR_MEPC, t0 + + // 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) + + lw sp, 0x08(sp) + + mret + +.globl enter_mode_s +enter_mode_s: // (a0, a1, svc_pc, svc_sp) + csrw CSR_MEPC, a2 + mv sp, a3 + mret + diff --git a/hw/bios.ld b/hw/boot.ld diff --git a/hw/inc/hw/platform.h b/hw/inc/hw/platform.h @@ -8,7 +8,7 @@ #define DRAM_BASE 0x40000000 #define FRAMEBUFFER_BASE 0x40C00000 // default fb dma base #define DRAM_SIZE (32*1024*1024) -#define BIOS_SIZE 0x00008000 +#define BOOTLOADER_SIZE 0x00008000 #define MMIO_BASE 0xF0000000 // MMIO Devices diff --git a/project/bios.app.mk b/project/bios.app.mk @@ -1,7 +0,0 @@ - -MOD_NAME := bios -MOD_SRC := hw/src/start.S bios/entry.S bios/bios.c -MOD_SRC += hw/src/debug.c -MOD_LIB := c -MOD_LDSCRIPT := hw/bios.ld -include make/app.mk diff --git a/project/boot.app.mk b/project/boot.app.mk @@ -0,0 +1,7 @@ + +MOD_NAME := boot +MOD_SRC := hw/src/start.S boot/entry.S boot/boot.c +MOD_SRC += hw/src/debug.c +MOD_LIB := c +MOD_LDSCRIPT := hw/boot.ld +include make/app.mk