123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- //! Chapter 4. Base Extension (EID #0x10).
- /// Extension ID for RISC-V SBI Base extension.
- pub const EID_BASE: usize = 0x10;
- pub use fid::*;
- /// Default probe value for the target SBI extension is unavailable.
- pub const UNAVAILABLE_EXTENSION: usize = 0;
- /// SBI specification version.
- ///
- /// In RISC-V SBI specification, the bit 31 must be 0 and is reserved for future expansion.
- ///
- /// Not to be confused with 'implementation version'.
- ///
- /// Declared in §4.1.
- #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, Hash)]
- #[repr(transparent)]
- pub struct Version {
- raw: usize,
- }
- impl Version {
- /// Converts raw extension value into Version structure.
- #[inline]
- pub const fn from_raw(raw: usize) -> Self {
- Self { raw }
- }
- /// Reads the major version of RISC-V SBI specification.
- #[inline]
- pub const fn major(self) -> usize {
- (self.raw >> 24) & ((1 << 7) - 1)
- }
- /// Reads the minor version of RISC-V SBI specification.
- #[inline]
- pub const fn minor(self) -> usize {
- self.raw & ((1 << 24) - 1)
- }
- }
- impl core::fmt::Display for Version {
- #[inline]
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- write!(f, "{}.{}", self.major(), self.minor())
- }
- }
- impl core::cmp::PartialOrd for Version {
- #[inline]
- fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
- self.major()
- .partial_cmp(&other.major())
- .map(|ordering| ordering.then_with(|| self.minor().cmp(&other.minor())))
- }
- }
- /// Declared in §4.8
- mod fid {
- /// Function ID to get the current SBI specification version.
- ///
- /// Declared in §4.1.
- pub const GET_SBI_SPEC_VERSION: usize = 0x0;
- /// Function ID to get the current SBI implementation ID.
- ///
- /// Declared in §4.2.
- pub const GET_SBI_IMPL_ID: usize = 0x1;
- /// Function ID to get the current SBI implementation version.
- ///
- /// Declared in §4.3.
- pub const GET_SBI_IMPL_VERSION: usize = 0x2;
- /// Function ID to probe information about one SBI extension from the current environment.
- ///
- /// Declared in §4.4.
- pub const PROBE_EXTENSION: usize = 0x3;
- /// Function ID to get the value of `mvendorid` register in the current environment.
- ///
- /// Declared in §4.5.
- pub const GET_MVENDORID: usize = 0x4;
- /// Function ID to get the value of `marchid` register in the current environment.
- ///
- /// Declared in §4.6.
- pub const GET_MARCHID: usize = 0x5;
- /// Function ID to get the value of `mimpid` register in the current environment.
- ///
- /// Declared in §4.7.
- pub const GET_MIMPID: usize = 0x6;
- }
- /// SBI Implementation IDs.
- ///
- /// Declared in §4.9.
- pub mod impl_id {
- /// Berkley Bootloader.
- pub const BBL: usize = 0;
- /// OpenSBI.
- pub const OPEN_SBI: usize = 1;
- /// Xvisor.
- pub const XVISOR: usize = 2;
- /// KVM.
- pub const KVM: usize = 3;
- /// RustSBI.
- pub const RUST_SBI: usize = 4;
- /// Diosix.
- pub const DIOSIX: usize = 5;
- /// Coffer.
- pub const COFFER: usize = 6;
- /// Xen Project.
- pub const XEN: usize = 7;
- /// PolarFire Hart Software Services.
- pub const POLARFIRE_HSS: usize = 8;
- /// Coreboot.
- pub const COREBOOT: usize = 9;
- /// Oreboot.
- pub const OREBOOT: usize = 10;
- }
- #[cfg(test)]
- mod tests {
- use super::Version;
- #[test]
- fn version_parse() {
- let v1_0 = Version::from_raw(0x100_0000);
- assert_eq!(v1_0.major(), 1);
- assert_eq!(v1_0.minor(), 0);
- let v2_0 = Version::from_raw(0x200_0000);
- assert_eq!(v2_0.major(), 2);
- assert_eq!(v2_0.minor(), 0);
- let v2_1 = Version::from_raw(0x200_0001);
- assert_eq!(v2_1.major(), 2);
- assert_eq!(v2_1.minor(), 1);
- let v2_max = Version::from_raw(0x2ff_ffff);
- assert_eq!(v2_max.major(), 2);
- assert_eq!(v2_max.minor(), 16777215);
- let vmax_3 = Version::from_raw(0x7f00_0003);
- assert_eq!(vmax_3.major(), 127);
- assert_eq!(vmax_3.minor(), 3);
- let vmax_max = Version::from_raw(0x7fff_ffff);
- assert_eq!(vmax_max.major(), 127);
- assert_eq!(vmax_max.minor(), 16777215);
- }
- #[test]
- fn version_display() {
- extern crate alloc;
- use alloc::string::ToString;
- assert_eq!("0.0", &Version::from_raw(0).to_string());
- assert_eq!("0.1", &Version::from_raw(0x1).to_string());
- assert_eq!("1.0", &Version::from_raw(0x100_0000).to_string());
- assert_eq!("1.1", &Version::from_raw(0x100_0001).to_string());
- assert_eq!("2.0", &Version::from_raw(0x200_0000).to_string());
- assert_eq!("127.0", &Version::from_raw(0x7f00_0000).to_string());
- assert_eq!("2.16777215", &Version::from_raw(0x2ff_ffff).to_string());
- assert_eq!("127.16777215", &Version::from_raw(0x7fff_ffff).to_string());
- }
- #[test]
- fn version_ordering() {
- use core::cmp::Ordering;
- let v0_0 = Version::from_raw(0x0);
- let v0_3 = Version::from_raw(0x3);
- let v1_0 = Version::from_raw(0x100_0000);
- let v2_0 = Version::from_raw(0x200_0000);
- let v2_1 = Version::from_raw(0x200_0001);
- let v2_max = Version::from_raw(0x2ff_ffff);
- let vmax_3 = Version::from_raw(0x7f00_0003);
- let vmax_max = Version::from_raw(0x7fff_ffff);
- assert!(v0_3 != v0_0);
- assert!(!(v0_3 == v0_0));
- assert!(v0_0 == v0_0);
- assert!(vmax_max == vmax_max);
- assert!(v0_3 > v0_0);
- assert!(v0_3 >= v0_0);
- assert!(v0_0 < v0_3);
- assert!(v0_0 <= v0_3);
- assert!(v0_0 >= v0_0);
- assert!(v0_0 <= v0_0);
- assert!(v0_3 > v0_0);
- assert!(v1_0 > v0_3);
- assert!(v2_0 > v1_0);
- assert!(v2_1 > v2_0);
- assert!(v2_max > v2_1);
- assert!(vmax_3 > v2_max);
- assert!(vmax_max > vmax_3);
- assert_eq!(Version::partial_cmp(&v1_0, &v0_0), Some(Ordering::Greater));
- assert_eq!(Version::partial_cmp(&v0_0, &v1_0), Some(Ordering::Less));
- assert_eq!(Version::partial_cmp(&v0_0, &v0_0), Some(Ordering::Equal));
- assert_eq!(Version::max(v0_0, v0_0), v0_0);
- assert_eq!(Version::max(v1_0, v0_0), v1_0);
- assert_eq!(Version::max(v0_0, v1_0), v1_0);
- assert_eq!(Version::min(v0_0, v0_0), v0_0);
- assert_eq!(Version::min(v1_0, v0_0), v0_0);
- assert_eq!(Version::min(v0_0, v1_0), v0_0);
- assert_eq!(v0_0.clamp(v0_3, v2_0), v0_3);
- assert_eq!(v0_3.clamp(v0_3, v2_0), v0_3);
- assert_eq!(v1_0.clamp(v0_3, v2_0), v1_0);
- assert_eq!(v2_0.clamp(v0_3, v2_0), v2_0);
- assert_eq!(v2_1.clamp(v0_3, v2_0), v2_0);
- }
- }
|