first commit

This commit is contained in:
sam 2025-04-26 18:24:51 +12:00
commit 61e8950b2e
11 changed files with 252 additions and 0 deletions

Binary file not shown.

Binary file not shown.

25
.clang-format Normal file
View file

@ -0,0 +1,25 @@
BasedOnStyle: WebKit
IndentWidth: 4
TabWidth: 4
UseTab: Never
AlignConsecutiveDeclarations: false
AlignConsecutiveAssignments: false
AlignTrailingComments: true
ColumnLimit: 105
BreakBeforeBraces: Attach
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: false
PointerAlignment: Left
SpaceBeforeParens: Never
SpacesInParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpaceAfterCStyleCast: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeSquareBrackets: false
SpacesBeforeTrailingComments: 2
PenaltyBreakAssignment: 1000
NamespaceIndentation: All

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
compile_commands.json
kernel.elf
*.o

34
Makefile Normal file
View file

@ -0,0 +1,34 @@
TOOLCHAIN = riscv64-linux-gnu-
QEMU=qemu-system-riscv64
KERNEL = kernel.elf
CFLAGS=-march=rv64i_zicsr_d -mabi=lp64d -Wall -Wextra -Werror -O2 -g -Iinclude
LDFLAGS=-T linker.ld --no-dynamic-linker -m elf64lriscv -static -nostdlib
QEMUFLAGS=-nographic -serial mon:stdio --no-reboot
CFILES = $(shell find -L -type f -name "*.c")
SFILES = $(shell find -L -type f -iname "*.s")
OBJ := $(addsuffix .o,$(CFILES)) $(addsuffix .o,$(SFILES))
$(KERNEL): $(OBJ) linker.ld
${TOOLCHAIN}ld $(LDFLAGS) -o $(KERNEL) $(OBJ)
%.c.o: %.c
$(TOOLCHAIN)gcc $(CFLAGS) -o $@ -c $<
%.s.o: %.s
$(TOOLCHAIN)gcc $(CFLAGS) -o $@ -c $<
%.S.o: %.S
$(TOOLCHAIN)gcc $(CFLAGS) -o $@ -c $<
run: $(KERNEL)
qemu-system-riscv64 $(QEMUFLAGS) -kernel $(KERNEL)
run-debug: $(KERNEL)
$(QEMU) -monitor none -s -S -kernel $(KERNEL) &
$(TOOLCHAIN)gdb $(KERNEL) -q -ex "target remote :1234" -ex "b *_start" -ex "c" -tui
killall $(QEMU)
clean:
@rm $(OBJ) $(KERNEL)

17
include/atomic_helpers.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef ATOMIC_HELPERS_H
#define ATOMIC_HELPERS_H
#define csrr(reg) \
({ \
uintptr_t temp; \
__asm__ volatile("csrr %0, " #reg : "=r"(temp)); \
temp; \
})
#define csrw(reg, val) \
({ \
uintptr_t temp = (uintptr_t)val; \
__asm__ volatile("csrw " #reg ", %0" ::"r"(temp)); \
})
#endif

9
linker.ld Normal file
View file

@ -0,0 +1,9 @@
MEMORY {
rom (rwx) : ORIGIN = 0x80200000, LENGTH = 512K
}
SECTIONS {
.init : {
*(.init)
} > rom
}

17
src/entry.s Normal file
View file

@ -0,0 +1,17 @@
.global _start
.global sret_wrapper
.extern main
.section .bss
stack: .space 4096
stack_top:
.section .init
_start:
la sp, stack_top
mv s0, sp
call main
sret
.loop:
wfi
j .loop

147
src/kernel.c Normal file
View file

@ -0,0 +1,147 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "atomic_helpers.h"
#define DEBUG_ECALL 0x4442434E
typedef struct {
long error;
long value;
} sbiret;
void trap_handler();
void trap_handler_wrapper() __attribute__((naked));
void user_entry();
unsigned long strlen(const char* str) {
unsigned long len = 0;
while(str[len] != '\0') {
len++;
}
return len;
}
int main() {
csrw(stvec, trap_handler_wrapper);
csrw(sepc, user_entry);
unsigned long sstatus = csrr(sstatus);
sstatus |= (1 << 5);
csrw(sstatus, sstatus);
// _start in entry.s will do the sret
}
void user_entry(void) {
while(1) {
__asm__ volatile("ecall");
__asm__ volatile("unimp");
}
}
__attribute__((always_inline))
inline sbiret sbi_ecall6(unsigned long number, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
sbiret ret;
__asm__ volatile("mv a7, %[number]\n"
"li a6, 0\n"
"mv a0, %[arg0]\n"
"mv a1, %[arg1]\n"
"mv a2, %[arg2]\n"
"mv a3, %[arg3]\n"
"mv a4, %[arg4]\n"
"mv a5, %[arg5]\n"
"ecall\n"
"mv %[err], a0\n"
"mv %[val], a1\n"
: [err] "=r"(ret.error), [val] "=r"(ret.value)
: [number] "r"(number), [arg0] "r"(arg0), [arg1] "r"(arg1),
[arg2] "r"(arg2),[arg3] "r"(arg3), [arg4] "r"(arg4),[arg5] "r"(arg5)
: "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7");
return ret;
}
__attribute__((always_inline))
inline sbiret sbi_ecall5(unsigned long number, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) {
return sbi_ecall6(number, arg0, arg1, arg2, arg3, arg4, 0);
}
__attribute__((always_inline))
inline sbiret sbi_ecall4(unsigned long number, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3) {
return sbi_ecall5(number, arg0, arg1, arg2, arg3, 0);
}
__attribute__((always_inline))
inline sbiret sbi_ecall3(unsigned long number, unsigned long arg0, unsigned long arg1, unsigned long arg2) {
return sbi_ecall4(number, arg0, arg1, arg2, 0);
}
__attribute__((always_inline))
inline sbiret sbi_ecall2(unsigned long number, unsigned long arg0, unsigned long arg1) {
return sbi_ecall3(number, arg0, arg1, 0);
}
__attribute__((always_inline))
inline sbiret sbi_ecall1(unsigned long number, unsigned long arg0) {
return sbi_ecall2(number, arg0, 0);
}
__attribute__((always_inline))
inline sbiret sbi_ecall0(unsigned long number) {
return sbi_ecall1(number, 0);
}
sbiret console_debug_write(const char* str, unsigned long len) {
return sbi_ecall2(DEBUG_ECALL, len, (unsigned long)str);
}
int puts(const char* str) {
sbiret ret;
if((ret = console_debug_write(str, strlen(str))).error != 0) {
return -1;
}
if((ret = console_debug_write("\n", 1)).error != 0) {
return -1;
}
return 0;
}
void trap_handler_wrapper() {
__asm__ volatile("call trap_handler\n"
"sret");
}
void trap_handler(void) {
unsigned long sepc = csrr(sepc);
unsigned long scause = csrr(scause);
unsigned long sstatus = csrr(sstatus);
if(scause == 8) {
puts("hello world");
sepc += 4;
csrw(sepc, sepc);
goto exit;
}
if(((sstatus >> 8) & 1) == 0) {
sepc += 4;
puts("exception occured in usermode, skipping past");
csrw(sepc, sepc);
goto exit;
} else {
puts("exception occured in supervisor mode, panic");
while(1) {
__asm__ volatile("wfi");
}
}
exit:
return;
}