kernel/arch/riscv64/instruction/
sbi.rs1use core::arch::asm;
2
3pub enum Extension {
4 Base = 0x10,
5 SetTimer = 0x00,
6 ConsolePutChar = 0x01,
7 ConsoleGetChar = 0x02,
8 Timer = 0x54494d45,
9 Ipi = 0x735049,
10 Rfence = 0x52464e43,
11 Hsm = 0x48534d,
12 Srst = 0x53525354,
13 Pmu = 0x504d55,
14}
15
16pub struct SbiRet {
17 pub error: usize,
18 pub value: usize,
19}
20
21pub enum SbiError {
22 Failed = -1,
23 NotSupported = -2,
24 InvalidParam = -3,
25 Denied = -4,
26 InvalidAddress = -5,
27 AlreadyAvailable = -6,
28 AlreadyStarted = -7,
29 AlreadyStopped = -8,
30}
31
32impl SbiError {
33 pub fn from_error(error: usize) -> SbiError {
34 let error = error as isize;
35 match error {
36 -1 => SbiError::Failed,
37 -2 => SbiError::NotSupported,
38 -3 => SbiError::InvalidParam,
39 -4 => SbiError::Denied,
40 -5 => SbiError::InvalidAddress,
41 -6 => SbiError::AlreadyAvailable,
42 -7 => SbiError::AlreadyStarted,
43 -8 => SbiError::AlreadyStopped,
44 _ => panic!("Invalid SBI error code"),
45 }
46 }
47}
48
49pub fn sbi_call(extension: Extension, function: usize, arg0: usize, arg1: usize) -> Result<usize, SbiError> {
50 let error: usize;
51 let ret: usize;
52
53 unsafe {
54 asm!(
55 "ecall",
56 inout("a0") arg0 => error,
57 inout("a1") arg1 => ret,
58 in("a2") 0,
59 in("a3") 0,
60 in("a4") 0,
61 in("a5") 0,
62 in("a6") function,
63 in("a7") extension as usize,
64 options(nostack),
65 );
66 }
67
68 match error {
69 0 => Ok(ret),
70 _ => Err(SbiError::from_error(error)),
71 }
72}
73
74pub fn sbi_console_putchar(c: char) {
75 let _ = sbi_call(Extension::ConsolePutChar, 0, c as usize, 0);
76}
77
78pub fn sbi_console_getchar() -> char {
79 let ret = sbi_call(Extension::ConsoleGetChar, 0, 0, 0);
80 match ret {
81 Ok(c) => c as u8 as char,
82 Err(_) => '\0',
83 }
84}
85
86pub fn sbi_set_timer(stime_value: u64) {
87 let _ = sbi_call(Extension::Timer, 0, stime_value as usize, 0);
88}
89
90pub fn sbi_system_reset(reset_type: u32, reset_reason: u32) -> ! {
91 let _ = sbi_call(Extension::Srst, 0, reset_type as usize, reset_reason as usize);
92 loop {}
93}