xref: /DragonOS/kernel/src/arch/riscv64/driver/sbi.rs (revision 2b7818e80e00fcfe4d03533f587cc125ea5e4bec)
1 use core::ptr::addr_of;
2 
3 /// 向控制台打印字符串。
4 ///
5 /// 该函数接受一个字节切片 `s` 作为输入,并迭代切片中的每个字节 `c`。
6 /// 然后调用 `sbi_rt::console_write_byte` 函数,将 `c` 的值作为参数传递给它。
7 ///
8 /// # 安全性
9 ///
10 /// 这个函数是安全的,因为对SBI环境的操作不涉及不安全内存的访问操作。
11 ///
12 /// # 参数
13 ///
14 /// * `s` - 表示要打印的字符串的字节切片。
15 ///
16 /// # 示例
17 ///
18 /// ```
19 /// let message = b"Hello, World!";
20 /// console_putstr(message);
21 /// ```
console_putstr(s: &[u8])22 pub fn console_putstr(s: &[u8]) {
23     if SbiDriver::extensions().contains(SBIExtensions::CONSOLE) {
24         for c in s {
25             sbi_rt::console_write_byte(*c);
26         }
27         return;
28     } else {
29         for c in s {
30             #[allow(deprecated)]
31             sbi_rt::legacy::console_putchar(*c as usize);
32         }
33     }
34 }
35 
36 bitflags! {
37     pub struct SBIExtensions: u64 {
38         /// RISC-V SBI Base extension.
39         const BASE = 1 << 0;
40         /// Timer programmer extension.
41         const TIME = 1 << 1;
42         /// Inter-processor Interrupt extension.
43         const SPI = 1 << 2;
44         /// Remote Fence extension.
45         const RFENCE = 1 << 3;
46         /// Hart State Monitor extension.
47         const HSM = 1 << 4;
48         /// System Reset extension.
49         const RESET = 1 << 5;
50         /// Performance Monitoring Unit extension.
51         const PMU = 1 << 6;
52         /// Debug Console extension.
53         const CONSOLE = 1 << 7;
54         /// System Suspend extension.
55         const SUSPEND = 1 << 8;
56         /// SBI CPPC extension.
57         const CPPC = 1 << 9;
58         /// Nested Acceleration extension.
59         const NACL = 1 << 10;
60         /// Steal-time Accounting extension.
61         const STA = 1 << 11;
62     }
63 }
64 
65 static mut EXTENSIONS: SBIExtensions = SBIExtensions::empty();
66 
67 #[derive(Debug)]
68 pub struct SbiDriver;
69 
70 impl SbiDriver {
71     #[inline(never)]
early_init()72     pub fn early_init() {
73         unsafe {
74             EXTENSIONS = Self::probe_extensions();
75         }
76     }
77 
78     /// 获取probe得到的SBI扩展信息。
extensions() -> &'static SBIExtensions79     pub fn extensions() -> &'static SBIExtensions {
80         unsafe { addr_of!(EXTENSIONS).as_ref().unwrap() }
81     }
82 
probe_extensions() -> SBIExtensions83     fn probe_extensions() -> SBIExtensions {
84         let mut extensions = SBIExtensions::empty();
85         if sbi_rt::probe_extension(sbi_rt::Base).is_available() {
86             extensions |= SBIExtensions::BASE;
87         }
88         if sbi_rt::probe_extension(sbi_rt::Timer).is_available() {
89             extensions |= SBIExtensions::TIME;
90         }
91 
92         if sbi_rt::probe_extension(sbi_rt::Ipi).is_available() {
93             extensions |= SBIExtensions::SPI;
94         }
95 
96         if sbi_rt::probe_extension(sbi_rt::Fence).is_available() {
97             extensions |= SBIExtensions::RFENCE;
98         }
99 
100         if sbi_rt::probe_extension(sbi_rt::Hsm).is_available() {
101             extensions |= SBIExtensions::HSM;
102         }
103 
104         if sbi_rt::probe_extension(sbi_rt::Reset).is_available() {
105             extensions |= SBIExtensions::RESET;
106         }
107 
108         if sbi_rt::probe_extension(sbi_rt::Pmu).is_available() {
109             extensions |= SBIExtensions::PMU;
110         }
111 
112         if sbi_rt::probe_extension(sbi_rt::Console).is_available() {
113             extensions |= SBIExtensions::CONSOLE;
114         }
115 
116         if sbi_rt::probe_extension(sbi_rt::Suspend).is_available() {
117             extensions |= SBIExtensions::SUSPEND;
118         }
119 
120         if sbi_rt::probe_extension(sbi_rt::Cppc).is_available() {
121             extensions |= SBIExtensions::CPPC;
122         }
123 
124         if sbi_rt::probe_extension(sbi_rt::Nacl).is_available() {
125             extensions |= SBIExtensions::NACL;
126         }
127 
128         if sbi_rt::probe_extension(sbi_rt::Sta).is_available() {
129             extensions |= SBIExtensions::STA;
130         }
131 
132         return extensions;
133     }
134 }
135