From d5d92555ae94d0b1265822f0ecf7f025a1c9dab7 Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 5 Jan 2022 02:47:30 -0500 Subject: [PATCH] Drivers: Started OpenSBI driver Just ecall wrapper for now TODO: Build system changes are lazy and need to be figured out TODO: Looks like kernel.cpp was indented with tabs, fix --- .../riscv/platform/allwinner-d1/meson.build | 1 + kernel/drivers/opensbi/include/opensbi.h | 62 +++++++++++++++ kernel/drivers/opensbi/meson.build | 9 +++ kernel/drivers/opensbi/opensbi.cpp | 78 +++++++++++++++++++ kernel/kernel.cpp | 31 ++++---- kernel/meson.build | 11 +++ 6 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 kernel/drivers/opensbi/include/opensbi.h create mode 100644 kernel/drivers/opensbi/meson.build create mode 100644 kernel/drivers/opensbi/opensbi.cpp diff --git a/kernel/arch/riscv/platform/allwinner-d1/meson.build b/kernel/arch/riscv/platform/allwinner-d1/meson.build index 867b244..2713137 100644 --- a/kernel/arch/riscv/platform/allwinner-d1/meson.build +++ b/kernel/arch/riscv/platform/allwinner-d1/meson.build @@ -8,6 +8,7 @@ arch_sources += [ elf = executable( 'kernel.elf', arch_sources, + include_directories: includes, link_args: [ '-Wl,-T,' + meson.current_source_dir() + '/platform.ld', '-static' diff --git a/kernel/drivers/opensbi/include/opensbi.h b/kernel/drivers/opensbi/include/opensbi.h new file mode 100644 index 0000000..d3083b5 --- /dev/null +++ b/kernel/drivers/opensbi/include/opensbi.h @@ -0,0 +1,62 @@ +#pragma once + +typedef unsigned long uintmax_t; + +namespace drivers { +namespace opensbi { + + // We use uintmax_t to make sure this works on 32 and 64 bit + // At least thats how I hope this works.. + // TODO: Add assert() to make sure this is the case + struct sbiret_t { + uintmax_t error; + uintmax_t value; + }; + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3, + uintmax_t a4, + uintmax_t a5); + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3, + uintmax_t a4); + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3); + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2); + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1); + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0); + +} // End namespace opensbi +} // End namespace drivers diff --git a/kernel/drivers/opensbi/meson.build b/kernel/drivers/opensbi/meson.build new file mode 100644 index 0000000..dfbc8de --- /dev/null +++ b/kernel/drivers/opensbi/meson.build @@ -0,0 +1,9 @@ +kernel_sources += [ + files( + 'opensbi.cpp' + ), +] + +kernel_includes += include_directories( + 'include' +) diff --git a/kernel/drivers/opensbi/opensbi.cpp b/kernel/drivers/opensbi/opensbi.cpp new file mode 100644 index 0000000..1456be3 --- /dev/null +++ b/kernel/drivers/opensbi/opensbi.cpp @@ -0,0 +1,78 @@ +#include +#include + +namespace drivers { +namespace opensbi { + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3, + uintmax_t a4, + uintmax_t a5) { + register uintmax_t r_a7 asm("a7") = extension; + register uintmax_t r_a6 asm("a6") = function; + register uintmax_t r_a0 asm("a0") = a0; + register uintmax_t r_a1 asm("a1") = a1; + register uintmax_t r_a2 asm("a2") = a2; + register uintmax_t r_a3 asm("a3") = a3; + register uintmax_t r_a4 asm("a4") = a4; + register uintmax_t r_a5 asm("a5") = a5; + asm volatile("ecall" : // Instruction + "=r"(r_a0), "=r"(r_a1) : // Inputs + "r"(r_a7), "r"(r_a6), // Outputs + "r"(r_a0), "r"(r_a1), "r"(r_a2), + "r"(r_a3), "r"(r_a4), "r"(r_a5)); + return {.error = a0, .value = a1}; + } + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3, + uintmax_t a4) { + return call(extension, function, a0, a1, a2, a3, a4, 0); + } + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2, + uintmax_t a3) { + return call(extension, function, a0, a1, a2, a3, 0, 0); + } + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1, + uintmax_t a2) { + return call(extension, function, a0, a1, a2, 0, 0, 0); + } + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0, + uintmax_t a1) { + return call(extension, function, a0, a1, 0, 0, 0, 0); + } + + sbiret_t call( + uintmax_t extension, + uintmax_t function, + uintmax_t a0) { + return call(extension, function, a0, 0, 0, 0, 0, 0); + } + +} // End namespace opensbi +} // End namespace drivers diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index 0b98da4..2a85a1e 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -1,6 +1,8 @@ #include #include +#include + #define read_csr(csr) \ ({ \ unsigned long __v; \ @@ -28,6 +30,7 @@ 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; @@ -47,13 +50,14 @@ void sbi_call2(int ext, int func, sbi_word arg0, sbi_word arg1) { 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++)); + drivers::opensbi::call(1, 0, *(f++)); continue; } f++; @@ -69,7 +73,7 @@ void fmt(const char *f, ...) { for(int i = 0; i < 16; ++i) { const char *digits = "0123456789abcdef"; int d = (v >> (60 - i * 4)) & 0xF; - sbi_call1(1, 0, digits[d]); + drivers::opensbi::call(1, 0, digits[d]); } } va_end(va); @@ -216,20 +220,20 @@ extern "C" void handle_isr(isr_frame_t *frame) { }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); + drivers::opensbi::call(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]); + drivers::opensbi::call(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++)); + drivers::opensbi::call(1, 0, *(s++)); while(1) ; } @@ -279,17 +283,18 @@ extern "C" void kmain(unsigned long hart, void *dtb) { (void)hart; (void)dtb; - //fmt("test\n"); + fmt("test\n"); + + fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8); + fmt("HART: {}, DTB: {}\n", hart, dtb); - /* volatile uint32_t *cfg = (uint32_t *)0x2000060; volatile uint32_t *dat = (uint32_t *)0x2000070; *cfg = 0x10; *dat = 0xFF; - */ - fmt("y"); + while(1); cli(); @@ -302,7 +307,7 @@ extern "C" void kmain(unsigned long hart, void *dtb) { set_csr_bits("sie", sie_s_software | sie_s_timer); // Self-IPI. - sbi_call2(0x735049, 0, 1 << hart, 0); + drivers::opensbi::call(0x735049, 0, 1 << hart, 0); sti(); cli(); @@ -335,17 +340,17 @@ extern "C" void kmain(unsigned long hart, void *dtb) { s = "paging works!\n"; s += 512UL * 1024 * 1024 * 1024; while(*s) - sbi_call1(1, 0, *(s++)); + drivers::opensbi::call(1, 0, *(s++)); create_task(&task1, task1_main); create_task(&task2, task2_main); time = read_csr("time"); - sbi_call1(0x54494D45, 0, time + 100000); + drivers::opensbi::call(0x54494D45, 0, time + 100000); save_stack(switch_task, 0); - sbi_call1(8, 0, 0); + drivers::opensbi::call(8, 0, 0); while(1); } diff --git a/kernel/meson.build b/kernel/meson.build index 5cf1571..6cb5212 100644 --- a/kernel/meson.build +++ b/kernel/meson.build @@ -4,5 +4,16 @@ kernel_sources = [ ) ] +kernel_includes = [ + include_directories('include') +] + +subdir('drivers/opensbi') + +includes = [ +# arch_includes, + kernel_includes +] + subdir('arch/' + arch)