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:
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