diff --git a/.gitignore b/.gitignore index 7af67f87..aceeab82 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ rust_payload/target rust_payload/Cargo.lock fw_payload.* *.dtb +*.bmp +*.bin +*.elf +*.img diff --git a/bare_metal_test/Makefile b/bare_metal_test/Makefile new file mode 100644 index 00000000..0b316554 --- /dev/null +++ b/bare_metal_test/Makefile @@ -0,0 +1,34 @@ +TARGET ?= bare +SRC_DIRS ?= . + +PREFIX ?= ../buildroot-2021.05/output/host/bin/riscv32-buildroot-linux-gnu- +CC := $(PREFIX)cc +AS := $(PREFIX)as +LD := $(PREFIX)ld +OBJDUMP := $(PREFIX)objcopy + +SRCS := $(wildcard *.S) +SRCS += $(wildcard *.c) +OBJS := $(addsuffix .o,$(basename $(SRCS))) +DEPS := $(OBJS:.o=.d) + +INC_DIRS := $(shell find $(SRC_DIRS) -type d) +INC_FLAGS := $(addprefix -I,$(INC_DIRS)) + +CFLAGS += -O3 -march=rv32ima -mabi=ilp32 -fno-stack-protector -fno-pie +ASFLAGS += -march=rv32ima -mabi=ilp32 +LDFLAGS += -static -nostdlib -nostartfiles -nodefaultlibs -Triscv32.ld -Wl,--no-as-needed + +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $@ $(LOADLIBES) $(LDLIBS) + +$(TARGET).img: $(TARGET) + riscv32-elf-objcopy -O binary $< $@ + +.PHONY: clean +clean: + $(RM) $(TARGET) $(OBJS) $(DEPS) + +.PHONY: run +run: $(TARGET).img + ../rvc -d ../dts.dtb -b $(TARGET).img diff --git a/bare_metal_test/bare b/bare_metal_test/bare new file mode 100755 index 00000000..45102ac3 Binary files /dev/null and b/bare_metal_test/bare differ diff --git a/bare_metal_test/bare.c b/bare_metal_test/bare.c new file mode 100644 index 00000000..79c66384 --- /dev/null +++ b/bare_metal_test/bare.c @@ -0,0 +1,52 @@ +#include + +#define UART_THR (*(volatile unsigned char*)0x10000000) +#define UART_LSR (*(volatile unsigned char*)0x10000005) +#define UART_LSR_THRE 0x20 + +// wait for Transfer Hold Register to clear, then write character to print it +void uart_putc(unsigned char c) { + while (UART_THR || !(UART_LSR & UART_LSR_THRE)) {} + UART_THR = c; +} + +void print(const char* str) { + while (*str) { + uart_putc(*str++); + } +} + +static bool got_ssip = false; +volatile static long long a = 0xaaaaffffffff; + +// runs in supervisor mode via mideleg (machine-mode trap delegation) +void handle_trap(void) { + print("[bare/trap] got SSIP!\n"); + got_ssip = true; +} + +// called from assembly, runs in supervisor mode (via sret) +int main(void) { + print("[bare] in main()\n"); + + print("[bare] testing arithmetic...\n"); + + long long b = a * 400LLU * -1; + if (b != -0x10AAB2FFFFFFE70LL) { + print("[bare] got wrong result :(\n"); + } else { + print("[bare] got correct result!\n"); + } + + print("[bare] testing trap handler...\n"); + __asm volatile("csrw sip, 0x2"); + + while (!got_ssip) {} + + print("[bare] selftest done!\n"); + print("[bare] now go run something more exciting...\n"); + + while (true) {} + + return 0; +} diff --git a/bare_metal_test/init.S b/bare_metal_test/init.S new file mode 100644 index 00000000..16d2a6b8 --- /dev/null +++ b/bare_metal_test/init.S @@ -0,0 +1,137 @@ +#define SLL32 sll +#define STORE sw +#define LOAD lw +#define LWU lw +#define LOG_REGBYTES 2 +#define REGBYTES (1 << LOG_REGBYTES) + + .section .entry, "ax", %progbits + .align 4 + .globl _start +_start: + csrw mie, zero + csrw mip, zero + lla a3, _start_hang + csrw mtvec, a3 + lla a3, _s_trap_entry + csrw stvec, a3 + + # enable supervisor software interrupt + li a3, 0x2 + csrw sie, a3 + csrw mie, a3 + csrw mideleg, a3 + li a3, 0x00b + csrs mstatus, a3 + + lla sp, _estack + lla a3, main + csrw mepc, a3 + li a3, 0x800 + csrs mstatus, a3 + mret + j _start_hang + + .section .entry, "ax", %progbits + .align 4 + .globl _start_hang +_start_hang: + j _start_hang + + .section .entry, "ax", %progbits + .align 4 + .globl _trap_entry +_s_trap_entry: + + addi sp,sp,-320 + + # save gprs + STORE x1,1*REGBYTES(x2) + STORE x3,3*REGBYTES(x2) + STORE x4,4*REGBYTES(x2) + STORE x5,5*REGBYTES(x2) + STORE x6,6*REGBYTES(x2) + STORE x7,7*REGBYTES(x2) + STORE x8,8*REGBYTES(x2) + STORE x9,9*REGBYTES(x2) + STORE x10,10*REGBYTES(x2) + STORE x11,11*REGBYTES(x2) + STORE x12,12*REGBYTES(x2) + STORE x13,13*REGBYTES(x2) + STORE x14,14*REGBYTES(x2) + STORE x15,15*REGBYTES(x2) + STORE x16,16*REGBYTES(x2) + STORE x17,17*REGBYTES(x2) + STORE x18,18*REGBYTES(x2) + STORE x19,19*REGBYTES(x2) + STORE x20,20*REGBYTES(x2) + STORE x21,21*REGBYTES(x2) + STORE x22,22*REGBYTES(x2) + STORE x23,23*REGBYTES(x2) + STORE x24,24*REGBYTES(x2) + STORE x25,25*REGBYTES(x2) + STORE x26,26*REGBYTES(x2) + STORE x27,27*REGBYTES(x2) + STORE x28,28*REGBYTES(x2) + STORE x29,29*REGBYTES(x2) + STORE x30,30*REGBYTES(x2) + STORE x31,31*REGBYTES(x2) + + # get sr, epc, badvaddr, cause + csrr s0, sstatus + csrr t1, sepc + csrr t2, stval + csrr t3, scause + STORE t0, 2*REGBYTES(x2) + STORE s0, 32*REGBYTES(x2) + STORE t1, 33*REGBYTES(x2) + STORE t2, 34*REGBYTES(x2) + STORE t3, 35*REGBYTES(x2) + + move a0, sp + jal handle_trap + + mv a0, sp + addi sp, sp, 320 + + LOAD t0, 32*REGBYTES(a0) + LOAD t1, 33*REGBYTES(a0) + csrw sstatus, t0 + csrw sepc, t1 + + # restore x registers + LOAD x1,1*REGBYTES(a0) + LOAD x2,2*REGBYTES(a0) + LOAD x3,3*REGBYTES(a0) + LOAD x4,4*REGBYTES(a0) + LOAD x5,5*REGBYTES(a0) + LOAD x6,6*REGBYTES(a0) + LOAD x7,7*REGBYTES(a0) + LOAD x8,8*REGBYTES(a0) + LOAD x9,9*REGBYTES(a0) + LOAD x11,11*REGBYTES(a0) + LOAD x12,12*REGBYTES(a0) + LOAD x13,13*REGBYTES(a0) + LOAD x14,14*REGBYTES(a0) + LOAD x15,15*REGBYTES(a0) + LOAD x16,16*REGBYTES(a0) + LOAD x17,17*REGBYTES(a0) + LOAD x18,18*REGBYTES(a0) + LOAD x19,19*REGBYTES(a0) + LOAD x20,20*REGBYTES(a0) + LOAD x21,21*REGBYTES(a0) + LOAD x22,22*REGBYTES(a0) + LOAD x23,23*REGBYTES(a0) + LOAD x24,24*REGBYTES(a0) + LOAD x25,25*REGBYTES(a0) + LOAD x26,26*REGBYTES(a0) + LOAD x27,27*REGBYTES(a0) + LOAD x28,28*REGBYTES(a0) + LOAD x29,29*REGBYTES(a0) + LOAD x30,30*REGBYTES(a0) + LOAD x31,31*REGBYTES(a0) + # restore a0 last + LOAD x10,10*REGBYTES(a0) + + # gtfo + sret diff --git a/bare_metal_test/riscv32.ld b/bare_metal_test/riscv32.ld new file mode 100644 index 00000000..f609fa32 --- /dev/null +++ b/bare_metal_test/riscv32.ld @@ -0,0 +1,34 @@ +MEMORY +{ + RAM : ORIGIN = 0x80000000, LENGTH = 31M +} + +_estack = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .text : + { + . = ALIGN(4); + *(.entry) + *(.text) + *(.text*) + *(.rodata) + *(.rodata*) + } >RAM + + .data : + { + . = ALIGN(4); + *(.data) + *(.data*) + } >RAM + + .bss : + { + . = ALIGN(4); + *(.bss) + *(.bss*) + *(COMMON) + } >RAM +}