mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:48:10 +00:00
Kernel/riscv64: Add basic SBI support
This commit is contained in:
parent
84777fbe62
commit
9bd3c542b4
3 changed files with 339 additions and 1 deletions
156
Kernel/Arch/riscv64/SBI.cpp
Normal file
156
Kernel/Arch/riscv64/SBI.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Sönke Holz <sholz8530@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Format.h>
|
||||
|
||||
#include <Kernel/Arch/riscv64/SBI.h>
|
||||
|
||||
namespace Kernel::SBI {
|
||||
|
||||
static bool s_sbi_is_legacy = false;
|
||||
|
||||
static SBIErrorOr<long> sbi_ecall0(EID extension_id, u32 function_id)
|
||||
{
|
||||
register unsigned long a0 asm("a0");
|
||||
register unsigned long a1 asm("a1");
|
||||
register unsigned long a6 asm("a6") = function_id;
|
||||
register unsigned long a7 asm("a7") = to_underlying(extension_id);
|
||||
asm volatile("ecall"
|
||||
: "=r"(a0), "=r"(a1)
|
||||
: "r"(a6), "r"(a7)
|
||||
: "memory");
|
||||
if (a0 == to_underlying(SBIError::Success))
|
||||
return static_cast<long>(a1);
|
||||
|
||||
return static_cast<SBIError>(a0);
|
||||
}
|
||||
|
||||
static SBIErrorOr<long> sbi_ecall1(EID extension_id, u32 function_id, unsigned long arg0)
|
||||
{
|
||||
register unsigned long a0 asm("a0") = arg0;
|
||||
register unsigned long a1 asm("a1");
|
||||
register unsigned long a6 asm("a6") = function_id;
|
||||
register unsigned long a7 asm("a7") = to_underlying(extension_id);
|
||||
asm volatile("ecall"
|
||||
: "+r"(a0), "=r"(a1)
|
||||
: "r"(a0), "r"(a6), "r"(a7)
|
||||
: "memory");
|
||||
if (a0 == to_underlying(SBIError::Success))
|
||||
return static_cast<long>(a1);
|
||||
|
||||
return static_cast<SBIError>(a0);
|
||||
}
|
||||
|
||||
namespace Base {
|
||||
|
||||
SBIErrorOr<SpecificationVersion> get_spec_version()
|
||||
{
|
||||
auto version = TRY(SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetSpecVersion)));
|
||||
return bit_cast<SpecificationVersion>(static_cast<u32>(version));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> get_impl_id()
|
||||
{
|
||||
return SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetImplID));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> get_impl_version()
|
||||
{
|
||||
return SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetImplVersion));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> probe_extension(EID extension_id)
|
||||
{
|
||||
return SBI::sbi_ecall1(EID::Base, to_underlying(FID::ProbeExtension), to_underlying(extension_id));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> get_mvendorid()
|
||||
{
|
||||
return SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetMVENDORID));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> get_marchid()
|
||||
{
|
||||
return SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetMARCHID));
|
||||
}
|
||||
|
||||
SBIErrorOr<long> get_mimpid()
|
||||
{
|
||||
return SBI::sbi_ecall0(EID::Base, to_underlying(FID::GetMIMPID));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Legacy {
|
||||
|
||||
static long sbi_legacy_ecall1(LegacyEID extension_id, unsigned long arg0)
|
||||
{
|
||||
register unsigned long a0 asm("a0") = arg0;
|
||||
register unsigned long a7 asm("a7") = to_underlying(extension_id);
|
||||
asm volatile("ecall"
|
||||
: "+r"(a0)
|
||||
: "r"(a0), "r"(a7)
|
||||
: "memory");
|
||||
return static_cast<long>(a0);
|
||||
}
|
||||
|
||||
LegacySBIErrorOr<void> set_timer(u64 stime_value)
|
||||
{
|
||||
auto err = sbi_legacy_ecall1(LegacyEID::SetTimer, stime_value);
|
||||
if (err == 0)
|
||||
return {};
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
LegacySBIErrorOr<void> console_putchar(int ch)
|
||||
{
|
||||
auto err = sbi_legacy_ecall1(LegacyEID::ConsolePutchar, ch);
|
||||
if (err == 0)
|
||||
return {};
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Timer {
|
||||
|
||||
SBIErrorOr<void> set_timer(u64 stime_value)
|
||||
{
|
||||
TRY(SBI::sbi_ecall1(EID::Timer, to_underlying(FID::SetTimer), stime_value));
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace DBCN {
|
||||
|
||||
SBIErrorOr<void> debug_console_write_byte(u8 byte)
|
||||
{
|
||||
TRY(SBI::sbi_ecall1(EID::DebugConsole, to_underlying(FID::DebugConsoleWriteByte), byte));
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
auto spec_version = Base::get_spec_version();
|
||||
if (spec_version.is_error()) {
|
||||
s_sbi_is_legacy = true;
|
||||
dbgln("SBI: Specification version: 0.1");
|
||||
} else {
|
||||
dbgln("SBI: Specification version: {}", spec_version.value());
|
||||
dbgln("SBI: Implementation ID: {}", MUST(Base::get_impl_id()));
|
||||
dbgln("SBI: Implementation version: {:#x}", MUST(Base::get_impl_version()));
|
||||
dbgln("SBI: mvendorid: {:#x}", MUST(Base::get_mvendorid()));
|
||||
dbgln("SBI: marchid: {:#x}", MUST(Base::get_marchid()));
|
||||
dbgln("SBI: mimpid: {:#x}", MUST(Base::get_mimpid()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue