Initial Commit
Mostly stolen from https://github.com/avdgrinten/riscv-toy-os Changed load address to 0x45000000 so it would run on real hardware Played around with GPIO and the watchdog
This commit is contained in:
commit
e50fb2de2c
6 changed files with 734 additions and 0 deletions
117
.gitignore
vendored
Normal file
117
.gitignore
vendored
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
### C ###
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.ko
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
### C++ ###
|
||||||
|
# Prerequisites
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
|
||||||
|
### Meson ###
|
||||||
|
# subproject directories
|
||||||
|
/subprojects/*
|
||||||
|
!/subprojects/*.wrap
|
||||||
|
|
||||||
|
# Meson Directories
|
||||||
|
meson-logs
|
||||||
|
meson-private
|
||||||
|
|
||||||
|
# Meson Files
|
||||||
|
meson_benchmark_setup.dat
|
||||||
|
meson_test_setup.dat
|
||||||
|
sanitycheckcpp.cc # C++ specific
|
||||||
|
sanitycheckcpp.exe # C++ specific
|
||||||
|
|
||||||
|
# Ninja
|
||||||
|
build.ninja
|
||||||
|
.ninja_deps
|
||||||
|
.ninja_logs
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
!*.svg # comment out if you don't need vector files
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
Sessionx.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
### Build dir ###
|
||||||
|
build/
|
201
kernel/boot.S
Normal file
201
kernel/boot.S
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
# a0: HART ID
|
||||||
|
# a1: DTB
|
||||||
|
|
||||||
|
la sp, stack_top
|
||||||
|
mv s0, zero
|
||||||
|
|
||||||
|
jal kmain
|
||||||
|
unimp
|
||||||
|
|
||||||
|
# void save_stack(void (*f)(void *, continuation), void *ctx)
|
||||||
|
.global save_stack
|
||||||
|
save_stack:
|
||||||
|
addi sp, sp, -0x78
|
||||||
|
|
||||||
|
sd gp, 0x00(sp)
|
||||||
|
sd tp, 0x08(sp)
|
||||||
|
sd s0, 0x10(sp)
|
||||||
|
sd s1, 0x18(sp)
|
||||||
|
sd s2, 0x20(sp)
|
||||||
|
sd s3, 0x28(sp)
|
||||||
|
sd s4, 0x30(sp)
|
||||||
|
sd s5, 0x38(sp)
|
||||||
|
sd s6, 0x40(sp)
|
||||||
|
sd s7, 0x48(sp)
|
||||||
|
sd s8, 0x50(sp)
|
||||||
|
sd s9, 0x58(sp)
|
||||||
|
sd s10, 0x60(sp)
|
||||||
|
sd s11, 0x68(sp)
|
||||||
|
sd ra, 0x70(sp)
|
||||||
|
|
||||||
|
mv t0, a0
|
||||||
|
mv a0, a1
|
||||||
|
mv a1, sp
|
||||||
|
jr t0
|
||||||
|
|
||||||
|
.global restore_stack
|
||||||
|
restore_stack:
|
||||||
|
mv sp, a0
|
||||||
|
ld gp, 0x00(sp)
|
||||||
|
ld tp, 0x08(sp)
|
||||||
|
ld s0, 0x10(sp)
|
||||||
|
ld s1, 0x18(sp)
|
||||||
|
ld s2, 0x20(sp)
|
||||||
|
ld s3, 0x28(sp)
|
||||||
|
ld s4, 0x30(sp)
|
||||||
|
ld s5, 0x38(sp)
|
||||||
|
ld s6, 0x40(sp)
|
||||||
|
ld s7, 0x48(sp)
|
||||||
|
ld s8, 0x50(sp)
|
||||||
|
ld s9, 0x58(sp)
|
||||||
|
ld s10, 0x60(sp)
|
||||||
|
ld s11, 0x68(sp)
|
||||||
|
ld ra, 0x70(sp)
|
||||||
|
|
||||||
|
addi sp, sp, 0x78
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
# void enter_umode(void *entry);
|
||||||
|
.global enter_umode
|
||||||
|
enter_umode:
|
||||||
|
# Do not trash x10 (= a0)
|
||||||
|
mv x1, zero
|
||||||
|
#mv x2, zero # SP
|
||||||
|
mv x3, zero
|
||||||
|
mv x4, zero
|
||||||
|
mv x5, zero
|
||||||
|
mv x6, zero
|
||||||
|
mv x7, zero
|
||||||
|
mv x8, zero
|
||||||
|
mv x9, zero
|
||||||
|
mv x11, zero
|
||||||
|
mv x12, zero
|
||||||
|
mv x13, zero
|
||||||
|
mv x14, zero
|
||||||
|
mv x15, zero
|
||||||
|
mv x16, zero
|
||||||
|
mv x17, zero
|
||||||
|
mv x18, zero
|
||||||
|
mv x19, zero
|
||||||
|
mv x20, zero
|
||||||
|
mv x21, zero
|
||||||
|
mv x22, zero
|
||||||
|
mv x23, zero
|
||||||
|
mv x24, zero
|
||||||
|
mv x25, zero
|
||||||
|
mv x26, zero
|
||||||
|
mv x27, zero
|
||||||
|
mv x28, zero
|
||||||
|
mv x29, zero
|
||||||
|
mv x30, zero
|
||||||
|
mv x31, zero
|
||||||
|
|
||||||
|
csrw sepc, a0
|
||||||
|
|
||||||
|
csrr a0, sstatus
|
||||||
|
# Set SPIE.
|
||||||
|
ori a0, a0, 0x20
|
||||||
|
# Clear SPP.
|
||||||
|
andi a0, a0, -1 - 0x100
|
||||||
|
csrw sstatus, a0
|
||||||
|
|
||||||
|
sret
|
||||||
|
|
||||||
|
.global isr
|
||||||
|
.align 2
|
||||||
|
isr:
|
||||||
|
# Exchange s1 and sscratch.
|
||||||
|
csrrw s1, sscratch, s1
|
||||||
|
|
||||||
|
# Store all temporary registers.
|
||||||
|
sd ra, 0x10(s1)
|
||||||
|
sd a0, 0x18(s1)
|
||||||
|
sd a1, 0x20(s1)
|
||||||
|
sd a2, 0x28(s1)
|
||||||
|
sd a3, 0x30(s1)
|
||||||
|
sd a4, 0x38(s1)
|
||||||
|
sd a5, 0x40(s1)
|
||||||
|
sd a6, 0x48(s1)
|
||||||
|
sd a7, 0x50(s1)
|
||||||
|
sd t0, 0x58(s1)
|
||||||
|
sd t1, 0x60(s1)
|
||||||
|
sd t2, 0x68(s1)
|
||||||
|
sd t3, 0x70(s1)
|
||||||
|
sd t4, 0x78(s1)
|
||||||
|
sd t5, 0x80(s1)
|
||||||
|
sd t6, 0x88(s1)
|
||||||
|
|
||||||
|
# Save sstatus (contains interrupt state etc.)
|
||||||
|
csrr t0, sstatus
|
||||||
|
sd t0, 0x98(s1)
|
||||||
|
# Save sepc.
|
||||||
|
csrr t0, sepc
|
||||||
|
sd t0, 0xA0(s1)
|
||||||
|
|
||||||
|
# Check if we interrupted user mode or supervisor mode.
|
||||||
|
# csrr t0, scause
|
||||||
|
# andi t0, t0, 0x100
|
||||||
|
# bnez t0, 1f
|
||||||
|
|
||||||
|
# TODO: If we interrupted user mode: also store callee-saved registers.
|
||||||
|
# (For example, to implement signals.)
|
||||||
|
# TODO: If we interrupted user mode: load a kernel stack pointer.
|
||||||
|
|
||||||
|
1:
|
||||||
|
# Store the next isr_frame in sccratch and re-load the saved s1 (which is still in sccratch).
|
||||||
|
ld t0, 0x08(s1)
|
||||||
|
beqz t0, 2f
|
||||||
|
csrrw t1, sscratch, t0
|
||||||
|
# Store the saved s1 in the isr_frame.
|
||||||
|
sd t1, 0x90(s1)
|
||||||
|
|
||||||
|
mv a0, s1
|
||||||
|
jal handle_isr
|
||||||
|
|
||||||
|
# Load the saved s1 into sscratch.
|
||||||
|
ld t0, 0x90(s1)
|
||||||
|
csrw sscratch, t0
|
||||||
|
|
||||||
|
# Restore sstatus.
|
||||||
|
ld t0, 0x98(s1)
|
||||||
|
csrw sstatus, t0
|
||||||
|
# Restore sepc.
|
||||||
|
ld t0, 0xA0(s1)
|
||||||
|
csrw sepc, t0
|
||||||
|
|
||||||
|
# Store all temporary registers.
|
||||||
|
ld ra, 0x10(s1)
|
||||||
|
ld a0, 0x18(s1)
|
||||||
|
ld a1, 0x20(s1)
|
||||||
|
ld a2, 0x28(s1)
|
||||||
|
ld a3, 0x30(s1)
|
||||||
|
ld a4, 0x38(s1)
|
||||||
|
ld a5, 0x40(s1)
|
||||||
|
ld a6, 0x48(s1)
|
||||||
|
ld a7, 0x50(s1)
|
||||||
|
ld t0, 0x58(s1)
|
||||||
|
ld t1, 0x60(s1)
|
||||||
|
ld t2, 0x68(s1)
|
||||||
|
ld t3, 0x70(s1)
|
||||||
|
ld t4, 0x78(s1)
|
||||||
|
ld t5, 0x80(s1)
|
||||||
|
ld t6, 0x88(s1)
|
||||||
|
|
||||||
|
# Exchange s1 and sscratch.
|
||||||
|
csrrw s1, sscratch, s1
|
||||||
|
|
||||||
|
# Returns from the trap.
|
||||||
|
sret
|
||||||
|
|
||||||
|
2:
|
||||||
|
jal isr_frame_overflow
|
||||||
|
unimp
|
||||||
|
|
||||||
|
.section .bss
|
||||||
|
.space 0x10000
|
||||||
|
stack_top:
|
349
kernel/kernel.cpp
Normal file
349
kernel/kernel.cpp
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#define read_csr(csr) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v; \
|
||||||
|
asm volatile ("csrr %0, " csr : "=r"(__v) : : "memory");\
|
||||||
|
__v;\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define write_csr(csr, v) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (v); \
|
||||||
|
asm volatile ("csrw " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define set_csr_bits(csr, bits) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (bits); \
|
||||||
|
asm volatile ("csrs " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
#define clear_csr_bits(csr, bits) \
|
||||||
|
({ \
|
||||||
|
unsigned long __v = (bits); \
|
||||||
|
asm volatile ("csrc " csr ", %0" : : "r"(__v) : "memory");\
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef unsigned long sbi_word;
|
||||||
|
|
||||||
|
void sbi_call1(int ext, int func, sbi_word arg0) {
|
||||||
|
register sbi_word rExt asm("a7") = ext;
|
||||||
|
register sbi_word rFunc asm("a6") = func;
|
||||||
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
|
register sbi_word rArg1 asm("a1");
|
||||||
|
asm volatile("ecall" : "+r"(rArg0), "=r"(rArg1) : "r"(rExt), "r"(rFunc));
|
||||||
|
if(rArg0)
|
||||||
|
__builtin_trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_call2(int ext, int func, sbi_word arg0, sbi_word arg1) {
|
||||||
|
register sbi_word rExt asm("a7") = ext;
|
||||||
|
register sbi_word rFunc asm("a6") = func;
|
||||||
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
|
register sbi_word rArg1 asm("a1") = arg1;
|
||||||
|
asm volatile("ecall" : "+r"(rArg0), "+r"(rArg1) : "r"(rExt), "r"(rFunc));
|
||||||
|
if(rArg0)
|
||||||
|
__builtin_trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void fmt(const char *f, ...) {
|
||||||
|
va_list va;
|
||||||
|
va_start(va, f);
|
||||||
|
while(*f) {
|
||||||
|
if(*f != '{') {
|
||||||
|
sbi_call1(1, 0, *(f++));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
f++;
|
||||||
|
|
||||||
|
while(*f != '}') {
|
||||||
|
if(!(*f))
|
||||||
|
return;
|
||||||
|
f++;
|
||||||
|
}
|
||||||
|
f++;
|
||||||
|
|
||||||
|
unsigned long v = va_arg(va, unsigned long);
|
||||||
|
for(int i = 0; i < 16; ++i) {
|
||||||
|
const char *digits = "0123456789abcdef";
|
||||||
|
int d = (v >> (60 - i * 4)) & 0xF;
|
||||||
|
sbi_call1(1, 0, digits[d]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
pte_valid = 1 << 0,
|
||||||
|
pte_r = 1 << 1,
|
||||||
|
pte_w = 1 << 2,
|
||||||
|
pte_x = 1 << 3,
|
||||||
|
pte_user = 1 << 4,
|
||||||
|
pte_access = 1 << 6,
|
||||||
|
pte_dirty = 1 << 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
pte_ppn_shift = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pt_t {
|
||||||
|
unsigned long ptes[512];
|
||||||
|
} __attribute__((aligned(4096)));
|
||||||
|
|
||||||
|
enum {
|
||||||
|
satp_sv48 = 9UL << 60
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *exception_strings[] = {
|
||||||
|
"instruction misaligned",
|
||||||
|
"instruction access fault",
|
||||||
|
"illegal instruction",
|
||||||
|
"breakpoint",
|
||||||
|
"load misaligned",
|
||||||
|
"load access fault",
|
||||||
|
"store misaligned",
|
||||||
|
"store access fault",
|
||||||
|
"u-mode ecall",
|
||||||
|
"s-mode ecall",
|
||||||
|
"reserved (10)",
|
||||||
|
"reserved (11)",
|
||||||
|
"instruction page fault",
|
||||||
|
"load page fault",
|
||||||
|
"reserved (14)",
|
||||||
|
"store page fault",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sie_s_software = (1 << 1),
|
||||||
|
sie_s_timer = (1 << 5)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sstatus_sie = (1 << 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
void cli() {
|
||||||
|
clear_csr_bits("sstatus", sstatus_sie);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sti() {
|
||||||
|
set_csr_bits("sstatus", sstatus_sie);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *sp;
|
||||||
|
} continuation_t;
|
||||||
|
|
||||||
|
struct task_t;
|
||||||
|
|
||||||
|
struct isr_frame_t {
|
||||||
|
task_t *task;
|
||||||
|
isr_frame_t *next;
|
||||||
|
unsigned long ra; // Offset 0x10.
|
||||||
|
unsigned long a[8]; // Offset 0x18.
|
||||||
|
unsigned long t[7]; // Offset 0x58.
|
||||||
|
unsigned long s1; // Offset 0x90.
|
||||||
|
unsigned long sstatus; // Offset 0x98.
|
||||||
|
unsigned long sepc; // Offset 0xA0.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kernel_stack_size = 0x10000
|
||||||
|
};
|
||||||
|
|
||||||
|
struct task_t {
|
||||||
|
continuation_t cont;
|
||||||
|
isr_frame_t isr_frames[2];
|
||||||
|
isr_frame_t *next_isr;
|
||||||
|
char kernel_stack[kernel_stack_size];
|
||||||
|
};
|
||||||
|
|
||||||
|
task_t task1;
|
||||||
|
task_t task2;
|
||||||
|
task_t *current_task;
|
||||||
|
|
||||||
|
continuation_t prepare_stack(void *s_top, void (*mainfn)(continuation_t)) {
|
||||||
|
void *sp = (void *)((uintptr_t)s_top - 0x78);
|
||||||
|
*((uint64_t *)((uintptr_t)sp + 0x70)) = (uint64_t)mainfn;
|
||||||
|
return (continuation_t){.sp = sp};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void save_stack(void (*f)(void *, continuation_t), void *ctx);
|
||||||
|
extern "C" void restore_stack(continuation_t c);
|
||||||
|
|
||||||
|
void create_task(task_t *task, void (*mainfn)(continuation_t)) {
|
||||||
|
task->isr_frames[0].task = task;
|
||||||
|
task->isr_frames[1].task = task;
|
||||||
|
task->isr_frames[0].next = &task->isr_frames[1];
|
||||||
|
task->isr_frames[1].next = 0;
|
||||||
|
task->next_isr = &task->isr_frames[0];
|
||||||
|
|
||||||
|
task->cont = prepare_stack((void *)(task->kernel_stack + kernel_stack_size), mainfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_task(void *ctx, continuation_t c) {
|
||||||
|
task_t *task = (task_t *)ctx;
|
||||||
|
if(task) {
|
||||||
|
task->next_isr = (isr_frame_t *)read_csr("sscratch");
|
||||||
|
task->cont = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
task_t *next;
|
||||||
|
if(task == &task1) {
|
||||||
|
next = &task2;
|
||||||
|
}else{
|
||||||
|
next = &task1;
|
||||||
|
}
|
||||||
|
current_task = next;
|
||||||
|
|
||||||
|
write_csr("sscratch", (unsigned long)next->next_isr);
|
||||||
|
|
||||||
|
restore_stack(next->cont);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void isr();
|
||||||
|
|
||||||
|
extern "C" void handle_isr(isr_frame_t *frame) {
|
||||||
|
unsigned long cause = read_csr("scause");
|
||||||
|
unsigned long code = cause & ~(1UL << 63);
|
||||||
|
if(cause & (1UL << 63)) {
|
||||||
|
if(code == 1) {
|
||||||
|
fmt("it's an IPI\n");
|
||||||
|
clear_csr_bits("sip", sie_s_software);
|
||||||
|
}else if(code == 5) { // Timer interrupt.
|
||||||
|
//clear_csr_bits("sie", sie_s_timer);
|
||||||
|
unsigned long time = read_csr("time");
|
||||||
|
sbi_call1(0x54494D45, 0, time + 100000);
|
||||||
|
save_stack(switch_task, current_task);
|
||||||
|
}else{
|
||||||
|
fmt("it's an unhandled interrupt, code: {}\n", code);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(code == 8) { // Syscall.
|
||||||
|
sbi_call1(1, 0, frame->a[0]);
|
||||||
|
}else{
|
||||||
|
unsigned long sepc = read_csr("sepc");
|
||||||
|
fmt("it's an exception at {}\n", sepc);
|
||||||
|
const char *s = exception_strings[cause];
|
||||||
|
while(*s)
|
||||||
|
sbi_call1(1, 0, *(s++));
|
||||||
|
while(1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void isr_frame_overflow() {
|
||||||
|
fmt("isr frame overflow\n");
|
||||||
|
while(1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
pt_t pml4;
|
||||||
|
|
||||||
|
extern "C" void enter_umode(void *entry);
|
||||||
|
|
||||||
|
void syscall(int n, unsigned long arg0) {
|
||||||
|
register sbi_word rArg0 asm("a0") = arg0;
|
||||||
|
register sbi_word rN asm("a7") = n;
|
||||||
|
asm volatile("ecall" : "+r"(rArg0) : "r"(rN) : "memory");
|
||||||
|
if(rArg0)
|
||||||
|
__builtin_trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void task1_umode() {
|
||||||
|
while(1)
|
||||||
|
syscall(0, '!');
|
||||||
|
}
|
||||||
|
|
||||||
|
void task1_main(continuation_t c) {
|
||||||
|
fmt("hello from task1\n");
|
||||||
|
sti();
|
||||||
|
//syscall(0, '!');
|
||||||
|
//enter_umode((void *)task1_umode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task2_main(continuation_t c) {
|
||||||
|
fmt("hello from task2\n");
|
||||||
|
sti();
|
||||||
|
//while(1)
|
||||||
|
//fmt(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
isr_frame_t global_isr_frames[2];
|
||||||
|
|
||||||
|
extern "C" void kmain(unsigned long hart, void *dtb) {
|
||||||
|
(void)hart;
|
||||||
|
(void)dtb;
|
||||||
|
|
||||||
|
//fmt("test\n");
|
||||||
|
|
||||||
|
volatile uint32_t *cfg = (uint32_t *)0x2000060;
|
||||||
|
volatile uint32_t *dat = (uint32_t *)0x2000070;
|
||||||
|
|
||||||
|
*cfg = 0x10;
|
||||||
|
*dat = 0xFF;
|
||||||
|
|
||||||
|
fmt("y");
|
||||||
|
|
||||||
|
cli();
|
||||||
|
|
||||||
|
global_isr_frames[0].next = &global_isr_frames[1];
|
||||||
|
write_csr("sscratch", (unsigned long)&global_isr_frames[0]);
|
||||||
|
write_csr("stvec", ((unsigned long)&isr));
|
||||||
|
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
set_csr_bits("sie", sie_s_software | sie_s_timer);
|
||||||
|
|
||||||
|
// Self-IPI.
|
||||||
|
sbi_call2(0x735049, 0, 1 << hart, 0);
|
||||||
|
|
||||||
|
sti();
|
||||||
|
cli();
|
||||||
|
|
||||||
|
unsigned long time;
|
||||||
|
volatile uint32_t *meme = (uint32_t *)0x6011010;
|
||||||
|
//while(true) {
|
||||||
|
time = read_csr("time");
|
||||||
|
fmt("hello world {}\n", time);
|
||||||
|
*meme = *meme | (0xA57 << 1) | (1 << 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Identity map the first 512GiB.
|
||||||
|
pml4.ptes[0] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
|
// Map 512GiB -> 0.
|
||||||
|
pml4.ptes[1] = ((0UL >> 12) << pte_ppn_shift) | pte_valid
|
||||||
|
| pte_r | pte_w | pte_x | pte_access | pte_dirty | pte_user;
|
||||||
|
|
||||||
|
fmt("Writing paging memes\n");
|
||||||
|
unsigned long pml4p = (unsigned long)&pml4;
|
||||||
|
fmt("pml4p @ {}\n", pml4p);
|
||||||
|
fmt("Setting SStatus\n");
|
||||||
|
set_csr_bits("sstatus", 1 << 18);
|
||||||
|
fmt("Setting Satp\n");
|
||||||
|
write_csr("satp", (pml4p >> 12) | satp_sv48);
|
||||||
|
|
||||||
|
fmt("Paging might work?...\n");
|
||||||
|
|
||||||
|
s = "paging works!\n";
|
||||||
|
s += 512UL * 1024 * 1024 * 1024;
|
||||||
|
while(*s)
|
||||||
|
sbi_call1(1, 0, *(s++));
|
||||||
|
|
||||||
|
create_task(&task1, task1_main);
|
||||||
|
create_task(&task2, task2_main);
|
||||||
|
|
||||||
|
time = read_csr("time");
|
||||||
|
//sbi_call1(0x54494D45, 0, time + 100000);
|
||||||
|
|
||||||
|
//save_stack(switch_task, 0);
|
||||||
|
|
||||||
|
sbi_call1(8, 0, 0);
|
||||||
|
|
||||||
|
while(1);
|
||||||
|
}
|
25
kernel/kernel.ld
Normal file
25
kernel/kernel.ld
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
OUTPUT_ARCH("riscv")
|
||||||
|
OUTPUT_FORMAT("elf64-littleriscv")
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS {
|
||||||
|
/* R-X segment. */
|
||||||
|
. = 0x45000000;
|
||||||
|
|
||||||
|
.text : { *(.text) *(.text.*) }
|
||||||
|
|
||||||
|
/* R-- segment. */
|
||||||
|
. = ALIGN(0x1000) + (. & (0xFFF));
|
||||||
|
/* For some reason, ld does not emit a read-only segment without an additional gap. */
|
||||||
|
. += 0x1000;
|
||||||
|
|
||||||
|
.rodata : { *(.rodata) *(.rodata.*) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
|
||||||
|
/* RW- segment. */
|
||||||
|
. = ALIGN(0x1000) + (. & (0xFFF));
|
||||||
|
|
||||||
|
.data : { *(.data) *(.data.*) }
|
||||||
|
.got : { *(.got) }
|
||||||
|
.got.plt : { *(.got.plt) }
|
||||||
|
.bss : { *(.bss) *(.bss.*) }
|
||||||
|
}
|
26
meson.build
Normal file
26
meson.build
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
project('riscv-qtech-os', ['c', 'cpp'])
|
||||||
|
|
||||||
|
kernel = executable('kernel',
|
||||||
|
'kernel/boot.S',
|
||||||
|
'kernel/kernel.cpp',
|
||||||
|
link_args: [
|
||||||
|
'-Wl,-T,' + (meson.current_source_dir() / 'kernel/kernel.ld'),
|
||||||
|
'-static'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
run_target('qemu',
|
||||||
|
command: [
|
||||||
|
find_program('qemu-system-riscv64'),
|
||||||
|
'-machine', 'virt',
|
||||||
|
'-cpu', 'rv64',
|
||||||
|
'-bios', 'opensbi-riscv64-generic-fw_dynamic.bin',
|
||||||
|
'-m', '256m',
|
||||||
|
'-serial', 'stdio',
|
||||||
|
'-s',
|
||||||
|
'-display', 'none',
|
||||||
|
# '-d', 'int',
|
||||||
|
'-kernel', kernel
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
16
riscv.cross
Normal file
16
riscv.cross
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[binaries]
|
||||||
|
c = 'riscv64-linux-gnu-gcc'
|
||||||
|
cpp = 'riscv64-linux-gnu-g++'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'riscv-qtech-os'
|
||||||
|
cpu_family = 'riscv'
|
||||||
|
cpu = 'rv64'
|
||||||
|
endian = 'little'
|
||||||
|
|
||||||
|
[built-in options]
|
||||||
|
|
||||||
|
c_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -ffreestanding'
|
||||||
|
c_link_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -nostdlib'
|
||||||
|
cpp_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -ffreestanding'
|
||||||
|
cpp_link_args = '-march=rv64gc -mabi=lp64d -mcmodel=medany -nostdlib'
|
Loading…
Reference in a new issue