1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:58:11 +00:00
serenity/Kernel/Arch/riscv64/SBI.cpp

174 lines
4.3 KiB
C++

/*
* 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_ecall0(LegacyEID extension_id)
{
register unsigned long a0 asm("a0");
register unsigned long a7 asm("a7") = to_underlying(extension_id);
asm volatile("ecall"
: "=r"(a0)
: "r"(a7)
: "memory");
return static_cast<long>(a0);
}
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;
}
void shutdown()
{
sbi_legacy_ecall0(LegacyEID::SystemShutdown);
VERIFY_NOT_REACHED();
}
}
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()));
}
}
}