sbi_spec/
lib.rs

1//! RISC-V SBI Specification structure and constant definitions.
2//!
3//! This crate adapts to RISC-V SBI Specification version 2.0 ratified.
4//! It provides structures in Rust semantics and best practices to simplify
5//! designs of RISC-V SBI ecosystem, both implementation and applications.
6//!
7//! You may find it convenient to use this library in a vast range of packages,
8//! from operating system kernels, hypervisors, to SBI bare metal implementations.
9//! This crate is `no_std` compatible and does not need dynamic memory allocation,
10//! which makes it suitable for embedded development.
11//!
12//! Although this library is dedicated to RISC-V architecture, it does not limit
13//! which build target the dependents should compile into.
14//! For example, when developing a RISC-V emulator on platforms other than RISC-V,
15//! the emulator designed on other platforms can still make use of `sbi-spec` structures,
16//! to provide the necessary features where the emulated RISC-V environment would make use of.
17#![no_std]
18#![deny(missing_docs, unsafe_code, unstable_features)]
19
20// §3
21pub mod binary;
22// §4
23pub mod base;
24// §5
25#[cfg(feature = "legacy")]
26pub mod legacy;
27// §6
28pub mod time;
29// §7
30pub mod spi;
31// §8
32pub mod rfnc;
33// §9
34pub mod hsm;
35// §10
36pub mod srst;
37// §11
38pub mod pmu;
39// §12
40pub mod dbcn;
41// §13
42pub mod susp;
43// §14
44pub mod cppc;
45// §15
46pub mod nacl;
47// §16
48pub mod sta;
49
50/// Converts SBI EID from str.
51const fn eid_from_str(name: &str) -> i32 {
52    match *name.as_bytes() {
53        [a] => i32::from_be_bytes([0, 0, 0, a]),
54        [a, b] => i32::from_be_bytes([0, 0, a, b]),
55        [a, b, c] => i32::from_be_bytes([0, a, b, c]),
56        [a, b, c, d] => i32::from_be_bytes([a, b, c, d]),
57        _ => unreachable!(),
58    }
59}
60
61/// Checks during compilation, and provides an item list for developers.
62#[cfg(test)]
63mod tests {
64    use static_assertions::{
65        assert_eq_align, assert_eq_size, assert_fields, assert_impl_all, const_assert_eq,
66    };
67    // §3
68    #[test]
69    fn test_binary() {
70        use crate::binary::*;
71        assert_eq_align!(SbiRet, usize);
72        assert_eq_size!(SbiRet, [usize; 2]);
73        assert_fields!(SbiRet: error);
74        assert_fields!(SbiRet: value);
75        assert_impl_all!(SbiRet: Copy, Clone, PartialEq, Eq, core::fmt::Debug);
76
77        const_assert_eq!(0, RET_SUCCESS as isize);
78        const_assert_eq!(-1, RET_ERR_FAILED as isize);
79        const_assert_eq!(-2, RET_ERR_NOT_SUPPORTED as isize);
80        const_assert_eq!(-3, RET_ERR_INVALID_PARAM as isize);
81        const_assert_eq!(-4, RET_ERR_DENIED as isize);
82        const_assert_eq!(-5, RET_ERR_INVALID_ADDRESS as isize);
83        const_assert_eq!(-6, RET_ERR_ALREADY_AVAILABLE as isize);
84        const_assert_eq!(-7, RET_ERR_ALREADY_STARTED as isize);
85        const_assert_eq!(-8, RET_ERR_ALREADY_STOPPED as isize);
86        const_assert_eq!(-9, RET_ERR_NO_SHMEM as isize);
87    }
88    // §4
89    #[test]
90    fn test_base() {
91        use crate::base::*;
92        const_assert_eq!(0x10, EID_BASE);
93        const_assert_eq!(0, GET_SBI_SPEC_VERSION);
94        const_assert_eq!(1, GET_SBI_IMPL_ID);
95        const_assert_eq!(2, GET_SBI_IMPL_VERSION);
96        const_assert_eq!(3, PROBE_EXTENSION);
97        const_assert_eq!(4, GET_MVENDORID);
98        const_assert_eq!(5, GET_MARCHID);
99        const_assert_eq!(6, GET_MIMPID);
100        const_assert_eq!(0, impl_id::BBL);
101        const_assert_eq!(1, impl_id::OPEN_SBI);
102        const_assert_eq!(2, impl_id::XVISOR);
103        const_assert_eq!(3, impl_id::KVM);
104        const_assert_eq!(4, impl_id::RUST_SBI);
105        const_assert_eq!(5, impl_id::DIOSIX);
106        const_assert_eq!(6, impl_id::COFFER);
107        const_assert_eq!(7, impl_id::XEN);
108        const_assert_eq!(8, impl_id::POLARFIRE_HSS);
109        const_assert_eq!(9, impl_id::COREBOOT);
110        const_assert_eq!(10, impl_id::OREBOOT);
111    }
112    // §5
113    #[cfg(feature = "legacy")]
114    #[test]
115    fn test_legacy() {
116        use crate::legacy::*;
117        const_assert_eq!(0, LEGACY_SET_TIMER);
118        const_assert_eq!(1, LEGACY_CONSOLE_PUTCHAR);
119        const_assert_eq!(2, LEGACY_CONSOLE_GETCHAR);
120        const_assert_eq!(3, LEGACY_CLEAR_IPI);
121        const_assert_eq!(4, LEGACY_SEND_IPI);
122        const_assert_eq!(5, LEGACY_REMOTE_FENCE_I);
123        const_assert_eq!(6, LEGACY_REMOTE_SFENCE_VMA);
124        const_assert_eq!(7, LEGACY_REMOTE_SFENCE_VMA_ASID);
125        const_assert_eq!(8, LEGACY_SHUTDOWN);
126    }
127    // §6
128    #[test]
129    fn test_time() {
130        use crate::time::*;
131        const_assert_eq!(0x54494D45, EID_TIME);
132        const_assert_eq!(0, SET_TIMER);
133    }
134    // §7
135    #[test]
136    fn test_spi() {
137        use crate::spi::*;
138        const_assert_eq!(0x735049, EID_SPI);
139        const_assert_eq!(0, SEND_IPI);
140    }
141    // §8
142    #[test]
143    fn test_rfnc() {
144        use crate::rfnc::*;
145        const_assert_eq!(0x52464E43, EID_RFNC);
146        const_assert_eq!(0, REMOTE_FENCE_I);
147        const_assert_eq!(1, REMOTE_SFENCE_VMA);
148        const_assert_eq!(2, REMOTE_SFENCE_VMA_ASID);
149        const_assert_eq!(3, REMOTE_HFENCE_GVMA_VMID);
150        const_assert_eq!(4, REMOTE_HFENCE_GVMA);
151        const_assert_eq!(5, REMOTE_HFENCE_VVMA_ASID);
152        const_assert_eq!(6, REMOTE_HFENCE_VVMA);
153    }
154    // §9
155    #[test]
156    fn test_hsm() {
157        use crate::hsm::*;
158        const_assert_eq!(0x48534D, EID_HSM);
159        const_assert_eq!(0, hart_state::STARTED);
160        const_assert_eq!(1, hart_state::STOPPED);
161        const_assert_eq!(2, hart_state::START_PENDING);
162        const_assert_eq!(3, hart_state::STOP_PENDING);
163        const_assert_eq!(4, hart_state::SUSPENDED);
164        const_assert_eq!(5, hart_state::SUSPEND_PENDING);
165        const_assert_eq!(6, hart_state::RESUME_PENDING);
166        const_assert_eq!(0x0000_0000, suspend_type::RETENTIVE);
167        const_assert_eq!(0x8000_0000, suspend_type::NON_RETENTIVE);
168        const_assert_eq!(0, HART_START);
169        const_assert_eq!(1, HART_STOP);
170        const_assert_eq!(2, HART_GET_STATUS);
171        const_assert_eq!(3, HART_SUSPEND);
172    }
173    // §10
174    #[test]
175    fn test_srst() {
176        use crate::srst::*;
177        const_assert_eq!(0x53525354, EID_SRST);
178        const_assert_eq!(0, RESET_TYPE_SHUTDOWN);
179        const_assert_eq!(1, RESET_TYPE_COLD_REBOOT);
180        const_assert_eq!(2, RESET_TYPE_WARM_REBOOT);
181        const_assert_eq!(0, RESET_REASON_NO_REASON);
182        const_assert_eq!(1, RESET_REASON_SYSTEM_FAILURE);
183        const_assert_eq!(0, SYSTEM_RESET);
184    }
185    // §11
186    #[test]
187    fn test_pmu() {
188        use crate::pmu::*;
189        const_assert_eq!(0x504D55, EID_PMU);
190        const_assert_eq!(0, NUM_COUNTERS);
191        const_assert_eq!(1, COUNTER_GET_INFO);
192        const_assert_eq!(2, COUNTER_CONFIG_MATCHING);
193        const_assert_eq!(3, COUNTER_START);
194        const_assert_eq!(4, COUNTER_STOP);
195        const_assert_eq!(5, COUNTER_FW_READ);
196        const_assert_eq!(6, COUNTER_FW_READ_HI);
197        const_assert_eq!(7, SNAPSHOT_SET_SHMEM);
198
199        const_assert_eq!(0, event_type::HARDWARE_GENERAL);
200        const_assert_eq!(1, event_type::HARDWARE_CACHE);
201        const_assert_eq!(2, event_type::HARDWARE_RAW);
202        const_assert_eq!(15, event_type::FIRMWARE);
203
204        const_assert_eq!(0, hardware_event::NO_EVENT);
205        const_assert_eq!(1, hardware_event::CPU_CYCLES);
206        const_assert_eq!(2, hardware_event::INSTRUCTIONS);
207        const_assert_eq!(3, hardware_event::CACHE_REFERENCES);
208        const_assert_eq!(4, hardware_event::CACHE_MISSES);
209        const_assert_eq!(5, hardware_event::BRANCH_INSTRUCTIONS);
210        const_assert_eq!(6, hardware_event::BRANCH_MISSES);
211        const_assert_eq!(7, hardware_event::BUS_CYCLES);
212        const_assert_eq!(8, hardware_event::STALLED_CYCLES_FRONTEND);
213        const_assert_eq!(9, hardware_event::STALLED_CYCLES_BACKEND);
214        const_assert_eq!(10, hardware_event::REF_CPU_CYCLES);
215
216        const_assert_eq!(0, cache_event::L1D);
217        const_assert_eq!(1, cache_event::L1I);
218        const_assert_eq!(2, cache_event::LL);
219        const_assert_eq!(3, cache_event::DTLB);
220        const_assert_eq!(4, cache_event::ITLB);
221        const_assert_eq!(5, cache_event::BPU);
222        const_assert_eq!(6, cache_event::NODE);
223
224        const_assert_eq!(0, cache_operation::READ);
225        const_assert_eq!(1, cache_operation::WRITE);
226        const_assert_eq!(2, cache_operation::PREFETCH);
227
228        const_assert_eq!(0, cache_result::ACCESS);
229        const_assert_eq!(1, cache_result::MISS);
230
231        const_assert_eq!(0, firmware_event::MISALIGNED_LOAD);
232        const_assert_eq!(1, firmware_event::MISALIGNED_STORE);
233        const_assert_eq!(2, firmware_event::ACCESS_LOAD);
234        const_assert_eq!(3, firmware_event::ACCESS_STORE);
235        const_assert_eq!(4, firmware_event::ILLEGAL_INSN);
236        const_assert_eq!(5, firmware_event::SET_TIMER);
237        const_assert_eq!(6, firmware_event::IPI_SENT);
238        const_assert_eq!(7, firmware_event::IPI_RECEIVED);
239        const_assert_eq!(8, firmware_event::FENCE_I_SENT);
240        const_assert_eq!(9, firmware_event::FENCE_I_RECEIVED);
241        const_assert_eq!(10, firmware_event::SFENCE_VMA_SENT);
242        const_assert_eq!(11, firmware_event::SFENCE_VMA_RECEIVED);
243        const_assert_eq!(12, firmware_event::SFENCE_VMA_ASID_SENT);
244        const_assert_eq!(13, firmware_event::SFENCE_VMA_ASID_RECEIVED);
245        const_assert_eq!(14, firmware_event::HFENCE_GVMA_SENT);
246        const_assert_eq!(15, firmware_event::HFENCE_GVMA_RECEIVED);
247        const_assert_eq!(16, firmware_event::HFENCE_GVMA_VMID_SENT);
248        const_assert_eq!(17, firmware_event::HFENCE_GVMA_VMID_RECEIVED);
249        const_assert_eq!(18, firmware_event::HFENCE_VVMA_SENT);
250        const_assert_eq!(19, firmware_event::HFENCE_VVMA_RECEIVED);
251        const_assert_eq!(20, firmware_event::HFENCE_VVMA_ASID_SENT);
252        const_assert_eq!(21, firmware_event::HFENCE_VVMA_ASID_RECEIVED);
253        const_assert_eq!(65535, firmware_event::PLATFORM);
254
255        const_assert_eq!(4096, shmem_size::SIZE);
256    }
257    // §12
258    #[test]
259    fn test_dbcn() {
260        use crate::dbcn::*;
261        const_assert_eq!(0x4442434E, EID_DBCN);
262        const_assert_eq!(0, CONSOLE_WRITE);
263        const_assert_eq!(1, CONSOLE_READ);
264        const_assert_eq!(2, CONSOLE_WRITE_BYTE);
265    }
266    // §13
267    #[test]
268    fn test_susp() {
269        use crate::susp::*;
270        const_assert_eq!(0x53555350, EID_SUSP);
271        const_assert_eq!(0, SUSPEND);
272    }
273    // §14
274    #[test]
275    fn test_cppc() {
276        use crate::cppc::*;
277        const_assert_eq!(0x43505043, EID_CPPC);
278        const_assert_eq!(0, PROBE);
279        const_assert_eq!(1, READ);
280        const_assert_eq!(2, READ_HI);
281        const_assert_eq!(3, WRITE);
282    }
283    // §15
284    #[test]
285    fn test_nacl() {
286        use crate::nacl::*;
287        const_assert_eq!(0x4E41434C, EID_NACL);
288        const_assert_eq!(0, PROBE_FEATURE);
289        const_assert_eq!(1, SET_SHMEM);
290        const_assert_eq!(2, SYNC_CSR);
291        const_assert_eq!(3, SYNC_HFENCE);
292        const_assert_eq!(4, SYNC_SRET);
293
294        const_assert_eq!(0, feature_id::SYNC_CSR);
295        const_assert_eq!(1, feature_id::SYNC_HFENCE);
296        const_assert_eq!(2, feature_id::SYNC_SRET);
297        const_assert_eq!(3, feature_id::AUTOSWAP_CSR);
298
299        const_assert_eq!(8192, shmem_size::RV32);
300        const_assert_eq!(12288, shmem_size::RV64);
301        const_assert_eq!(20480, shmem_size::RV128);
302        match () {
303            #[cfg(target_pointer_width = "32")]
304            () => {
305                const_assert_eq!(shmem_size::NATIVE, shmem_size::RV32);
306            }
307            #[cfg(target_pointer_width = "64")]
308            () => {
309                const_assert_eq!(shmem_size::NATIVE, shmem_size::RV64);
310            }
311        }
312        // FIXME(2024-08-03): gate target pointer width at 128
313        // Currently, values for `target_pointer_width` expected by Rustc compiler are only `16`, `32`, and `64`.
314        // #[cfg(target_pointer_width = "128")]
315        // () => {
316        //     const_assert_eq!(shmem_size::NATIVE, shmem_size::RV128);
317        // }
318    }
319    // §16
320    #[test]
321    fn test_sta() {
322        use crate::sta::*;
323        const_assert_eq!(0x535441, EID_STA);
324        const_assert_eq!(0, SET_SHMEM);
325    }
326}