OpenSBI memes

Added legacy extension

Fixed typing memes by just define a sbiword_t typedef

Renamed sbiret_t to SbiRet, I think i'll only use _t for typedefs

Added ecall() variant that takes no additional arguments

Moved opensbi includes to includes/opensbi/...

kernel.cpp uses the legacy extensions instead of raw ecalls

All legacy extension calls are marked as deprecated
This commit is contained in:
Thomas Muller 2022-01-23 20:15:53 -05:00
parent ea60891ef5
commit 464a61102e
Signed by: thomas
GPG key ID: AF006EB730564952
7 changed files with 285 additions and 122 deletions

View file

@ -0,0 +1,105 @@
#include "opensbi/extensions/legacy.h"
namespace drivers {
namespace opensbi::legacy {
namespace {
enum class ExtensionId {
SET_TIMER,
CONSOLE_PUTCHAR,
CONSOLE_GETCHAR,
CLEAR_IPI,
SEND_IPI,
REMOTE_FENCE_I,
REMOTE_SFENCE_VMA,
REMOTE_SFENCE_VMA_ASID,
SHUTDOWN
};
}
SbiRet set_timer(std::uint64_t stime_value) {
#if __riscv_xlen == 64
return ecall(
static_cast<sbiword_t>(ExtensionId::SET_TIMER),
0,
stime_value);
#else
return ecall(
static_cast<sbiword_t>(ExtensionId::SET_TIMER),
0,
static_cast<uint32_t>(stime_value),
static_cast<uint32_t>(stime_value >> 32));
#endif
}
SbiRet console_putchar(int ch) {
return ecall(
static_cast<sbiword_t>(ExtensionId::CONSOLE_PUTCHAR),
0,
ch);
}
SbiRet console_getchar() {
return ecall(
static_cast<sbiword_t>(ExtensionId::CONSOLE_GETCHAR),
0);
}
SbiRet clear_ipmi() {
return ecall(
static_cast<sbiword_t>(ExtensionId::CLEAR_IPI),
0);
}
SbiRet send_ipmi(hart_mask_t hart_mask) {
return ecall(
static_cast<sbiword_t>(ExtensionId::SEND_IPI),
0,
reinterpret_cast<sbiword_t>(hart_mask));
}
SbiRet remote_fence_i(hart_mask_t hart_mask) {
return ecall(
static_cast<sbiword_t>(ExtensionId::REMOTE_FENCE_I),
0,
reinterpret_cast<sbiword_t>(hart_mask));
}
SbiRet remote_sfence_vma(
hart_mask_t hart_mask,
sbiword_t start,
sbiword_t size) {
return ecall(
static_cast<sbiword_t>(ExtensionId::REMOTE_SFENCE_VMA),
0,
reinterpret_cast<sbiword_t>(hart_mask),
start,
size);
}
SbiRet remote_sfence_vma_asid(
hart_mask_t hart_mask,
sbiword_t start,
sbiword_t size,
sbiword_t asid) {
return ecall(
static_cast<sbiword_t>(ExtensionId::REMOTE_SFENCE_VMA_ASID),
0,
reinterpret_cast<sbiword_t>(hart_mask),
start,
size,
asid);
}
void shutdown() {
ecall(
static_cast<sbiword_t>(ExtensionId::SHUTDOWN),
0);
// This should never be reached, explode if it is
__builtin_trap();
while(1);
}
} // End namespace opensbi::legacy
} // End namespace drivers

View file

@ -1,62 +0,0 @@
#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

View file

@ -0,0 +1,42 @@
#pragma once
#include "opensbi/opensbi.h"
namespace drivers {
namespace opensbi::legacy {
[[deprecated("Use the time extension instead")]]
SbiRet set_timer(uint64_t stime_value);
[[deprecated("No alternative, git gud git real driver")]]
SbiRet console_putchar(int ch);
[[deprecated("No alternative, git gud git real driver")]]
SbiRet console_getchar();
[[deprecated("No alternative")]]
SbiRet clear_ipmi();
[[deprecated("Use the sPI extension instead")]]
SbiRet send_ipmi(hart_mask_t hart_mask);
[[deprecated("Use the RFNC extension instead")]]
SbiRet remote_fence_i(hart_mask_t hart_mask);
[[deprecated("Use the RFNC extension instead")]]
SbiRet remote_sfence_vma(
hart_mask_t hart_mask,
sbiword_t start,
sbiword_t size);
[[deprecated("Use the RFNC extension instead")]]
SbiRet remote_sfence_vma_asid(
hart_mask_t hart_mask,
sbiword_t start,
sbiword_t size,
sbiword_t asid);
[[deprecated("Use the SRST extension instead")]]
[[noreturn]] void shutdown();
} // End namespace opensbi::legacy
} // End namespace drivers

View file

@ -0,0 +1,65 @@
#pragma once
#include <cstdint>
namespace drivers {
namespace opensbi {
typedef unsigned long sbiword_t;
typedef const unsigned long * hart_mask_t;
struct SbiRet {
sbiword_t error;
sbiword_t value;
};
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0,
sbiword_t a1,
sbiword_t a2,
sbiword_t a3,
sbiword_t a4,
sbiword_t a5);
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0,
sbiword_t a1,
sbiword_t a2,
sbiword_t a3,
sbiword_t a4);
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0,
sbiword_t a1,
sbiword_t a2,
sbiword_t a3);
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0,
sbiword_t a1,
sbiword_t a2);
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0,
sbiword_t a1);
SbiRet ecall(
sbiword_t extension,
sbiword_t function,
sbiword_t a0);
SbiRet ecall(
sbiword_t extension,
sbiword_t function);
} // End namespace opensbi
} // End namespace drivers

View file

@ -1,6 +1,7 @@
kernel_sources += [ kernel_sources += [
files( files(
'opensbi.cpp' 'opensbi.cpp',
'extensions/legacy.cpp'
), ),
] ]

View file

@ -1,26 +1,25 @@
#include <cstdint> #include "opensbi/opensbi.h"
#include <opensbi.h>
namespace drivers { namespace drivers {
namespace opensbi { namespace opensbi {
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0, sbiword_t a0,
uintptr_t a1, sbiword_t a1,
uintptr_t a2, sbiword_t a2,
uintptr_t a3, sbiword_t a3,
uintptr_t a4, sbiword_t a4,
uintptr_t a5) { sbiword_t a5) {
register uintptr_t r_a7 asm("a7") = extension; register sbiword_t r_a7 asm("a7") = extension;
register uintptr_t r_a6 asm("a6") = function; register sbiword_t r_a6 asm("a6") = function;
register uintptr_t r_a0 asm("a0") = a0; register sbiword_t r_a0 asm("a0") = a0;
register uintptr_t r_a1 asm("a1") = a1; register sbiword_t r_a1 asm("a1") = a1;
register uintptr_t r_a2 asm("a2") = a2; register sbiword_t r_a2 asm("a2") = a2;
register uintptr_t r_a3 asm("a3") = a3; register sbiword_t r_a3 asm("a3") = a3;
register uintptr_t r_a4 asm("a4") = a4; register sbiword_t r_a4 asm("a4") = a4;
register uintptr_t r_a5 asm("a5") = a5; register sbiword_t r_a5 asm("a5") = a5;
asm volatile("ecall" : // Instruction asm volatile("ecall" : // Instruction
"=r"(r_a0), "=r"(r_a1) : // Inputs "=r"(r_a0), "=r"(r_a1) : // Inputs
"r"(r_a7), "r"(r_a6), // Outputs "r"(r_a7), "r"(r_a6), // Outputs
@ -29,50 +28,56 @@ namespace opensbi {
return {.error = a0, .value = a1}; return {.error = a0, .value = a1};
} }
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0, sbiword_t a0,
uintptr_t a1, sbiword_t a1,
uintptr_t a2, sbiword_t a2,
uintptr_t a3, sbiword_t a3,
uintptr_t a4) { sbiword_t a4) {
return ecall(extension, function, a0, a1, a2, a3, a4, 0); return ecall(extension, function, a0, a1, a2, a3, a4, 0);
} }
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0, sbiword_t a0,
uintptr_t a1, sbiword_t a1,
uintptr_t a2, sbiword_t a2,
uintptr_t a3) { sbiword_t a3) {
return ecall(extension, function, a0, a1, a2, a3, 0, 0); return ecall(extension, function, a0, a1, a2, a3, 0, 0);
} }
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0, sbiword_t a0,
uintptr_t a1, sbiword_t a1,
uintptr_t a2) { sbiword_t a2) {
return ecall(extension, function, a0, a1, a2, 0, 0, 0); return ecall(extension, function, a0, a1, a2, 0, 0, 0);
} }
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0, sbiword_t a0,
uintptr_t a1) { sbiword_t a1) {
return ecall(extension, function, a0, a1, 0, 0, 0, 0); return ecall(extension, function, a0, a1, 0, 0, 0, 0);
} }
sbiret_t ecall( SbiRet ecall(
uintptr_t extension, sbiword_t extension,
uintptr_t function, sbiword_t function,
uintptr_t a0) { sbiword_t a0) {
return ecall(extension, function, a0, 0, 0, 0, 0, 0); return ecall(extension, function, a0, 0, 0, 0, 0, 0);
} }
SbiRet ecall(
sbiword_t extension,
sbiword_t function) {
return ecall(extension, function, 0, 0, 0, 0, 0, 0);
}
} // End namespace opensbi } // End namespace opensbi
} // End namespace drivers } // End namespace drivers

View file

@ -1,7 +1,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <inttypes.h> #include <inttypes.h>
#include <opensbi.h> #include <opensbi/opensbi.h>
#include <opensbi/extensions/legacy.h>
#define read_csr(csr) \ #define read_csr(csr) \
({ \ ({ \
@ -31,11 +32,13 @@
typedef unsigned long sbi_word; typedef unsigned long sbi_word;
void fmt(const char *f, ...) { void fmt(const char *f, ...) {
using drivers::opensbi::legacy::console_putchar;
va_list va; va_list va;
va_start(va, f); va_start(va, f);
while(*f) { while(*f) {
if(*f != '{') { if(*f != '{') {
drivers::opensbi::call(1, 0, *(f++)); console_putchar(*(f++));
continue; continue;
} }
f++; f++;
@ -51,7 +54,7 @@ void fmt(const char *f, ...) {
for(int i = 0; i < 16; ++i) { for(int i = 0; i < 16; ++i) {
const char *digits = "0123456789abcdef"; const char *digits = "0123456789abcdef";
int d = (v >> (60 - i * 4)) & 0xF; int d = (v >> (60 - i * 4)) & 0xF;
drivers::opensbi::call(1, 0, digits[d]); console_putchar(digits[d]);
} }
} }
va_end(va); va_end(va);
@ -189,6 +192,8 @@ void switch_task(void *ctx, continuation_t c) {
extern "C" void isr(); extern "C" void isr();
extern "C" void handle_isr(isr_frame_t *frame) { extern "C" void handle_isr(isr_frame_t *frame) {
using drivers::opensbi::legacy::console_putchar;
unsigned long cause = read_csr("scause"); unsigned long cause = read_csr("scause");
unsigned long code = cause & ~(1UL << 63); unsigned long code = cause & ~(1UL << 63);
if(cause & (1UL << 63)) { if(cause & (1UL << 63)) {
@ -198,20 +203,20 @@ extern "C" void handle_isr(isr_frame_t *frame) {
}else if(code == 5) { // Timer interrupt. }else if(code == 5) { // Timer interrupt.
//clear_csr_bits("sie", sie_s_timer); //clear_csr_bits("sie", sie_s_timer);
unsigned long time = read_csr("time"); unsigned long time = read_csr("time");
drivers::opensbi::call(0x54494D45, 0, time + 100000); drivers::opensbi::ecall(0x54494D45, 0, time + 100000);
save_stack(switch_task, current_task); save_stack(switch_task, current_task);
}else{ }else{
fmt("it's an unhandled interrupt, code: {}\n", code); fmt("it's an unhandled interrupt, code: {}\n", code);
} }
}else{ }else{
if(code == 8) { // Syscall. if(code == 8) { // Syscall.
drivers::opensbi::call(1, 0, frame->a[0]); console_putchar(frame->a[0]);
}else{ }else{
unsigned long sepc = read_csr("sepc"); unsigned long sepc = read_csr("sepc");
fmt("it's an exception at {}\n", sepc); fmt("it's an exception at {}\n", sepc);
const char *s = exception_strings[cause]; const char *s = exception_strings[cause];
while(*s) while(*s)
drivers::opensbi::call(1, 0, *(s++)); console_putchar(*(s++));
while(1) while(1)
; ;
} }
@ -261,6 +266,8 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
(void)hart; (void)hart;
(void)dtb; (void)dtb;
using drivers::opensbi::legacy::console_putchar;
fmt("test\n"); fmt("test\n");
fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8); fmt("uintmax: {} bits\n", sizeof(uintmax_t) * 8);
@ -285,7 +292,7 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
set_csr_bits("sie", sie_s_software | sie_s_timer); set_csr_bits("sie", sie_s_software | sie_s_timer);
// Self-IPI. // Self-IPI.
drivers::opensbi::call(0x735049, 0, 1 << hart, 0); drivers::opensbi::ecall(0x735049, 0, 1 << hart, 0);
sti(); sti();
cli(); cli();
@ -318,17 +325,17 @@ extern "C" void kmain(unsigned long hart, void *dtb) {
s = "paging works!\n"; s = "paging works!\n";
s += 512UL * 1024 * 1024 * 1024; s += 512UL * 1024 * 1024 * 1024;
while(*s) while(*s)
drivers::opensbi::call(1, 0, *(s++)); console_putchar(*(s++));
create_task(&task1, task1_main); create_task(&task1, task1_main);
create_task(&task2, task2_main); create_task(&task2, task2_main);
time = read_csr("time"); time = read_csr("time");
drivers::opensbi::call(0x54494D45, 0, time + 100000); drivers::opensbi::ecall(0x54494D45, 0, time + 100000);
save_stack(switch_task, 0); save_stack(switch_task, 0);
drivers::opensbi::call(8, 0, 0); drivers::opensbi::ecall(8, 0, 0);
while(1); while(1);
} }