base.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //! Chapter 4. Base Extension (EID #0x10).
  2. /// Extension ID for RISC-V SBI Base extension.
  3. pub const EID_BASE: usize = 0x10;
  4. pub use fid::*;
  5. /// Default probe value for the target SBI extension is unavailable.
  6. pub const UNAVAILABLE_EXTENSION: usize = 0;
  7. /// SBI specification version.
  8. ///
  9. /// In RISC-V SBI specification, the bit 31 must be 0 and is reserved for future expansion.
  10. ///
  11. /// Not to be confused with 'implementation version'.
  12. ///
  13. /// Declared in §4.1.
  14. #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, Hash)]
  15. #[repr(transparent)]
  16. pub struct Version {
  17. raw: usize,
  18. }
  19. impl Version {
  20. /// Converts raw extension value into Version structure.
  21. #[inline]
  22. pub const fn from_raw(raw: usize) -> Self {
  23. Self { raw }
  24. }
  25. /// Reads the major version of RISC-V SBI specification.
  26. #[inline]
  27. pub const fn major(self) -> usize {
  28. (self.raw >> 24) & ((1 << 7) - 1)
  29. }
  30. /// Reads the minor version of RISC-V SBI specification.
  31. #[inline]
  32. pub const fn minor(self) -> usize {
  33. self.raw & ((1 << 24) - 1)
  34. }
  35. }
  36. impl core::fmt::Display for Version {
  37. #[inline]
  38. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  39. write!(f, "{}.{}", self.major(), self.minor())
  40. }
  41. }
  42. impl core::cmp::PartialOrd for Version {
  43. #[inline]
  44. fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
  45. self.major()
  46. .partial_cmp(&other.major())
  47. .map(|ordering| ordering.then_with(|| self.minor().cmp(&other.minor())))
  48. }
  49. }
  50. /// Declared in §4.8
  51. mod fid {
  52. /// Function ID to get the current SBI specification version.
  53. ///
  54. /// Declared in §4.1.
  55. pub const GET_SBI_SPEC_VERSION: usize = 0x0;
  56. /// Function ID to get the current SBI implementation ID.
  57. ///
  58. /// Declared in §4.2.
  59. pub const GET_SBI_IMPL_ID: usize = 0x1;
  60. /// Function ID to get the current SBI implementation version.
  61. ///
  62. /// Declared in §4.3.
  63. pub const GET_SBI_IMPL_VERSION: usize = 0x2;
  64. /// Function ID to probe information about one SBI extension from the current environment.
  65. ///
  66. /// Declared in §4.4.
  67. pub const PROBE_EXTENSION: usize = 0x3;
  68. /// Function ID to get the value of `mvendorid` register in the current environment.
  69. ///
  70. /// Declared in §4.5.
  71. pub const GET_MVENDORID: usize = 0x4;
  72. /// Function ID to get the value of `marchid` register in the current environment.
  73. ///
  74. /// Declared in §4.6.
  75. pub const GET_MARCHID: usize = 0x5;
  76. /// Function ID to get the value of `mimpid` register in the current environment.
  77. ///
  78. /// Declared in §4.7.
  79. pub const GET_MIMPID: usize = 0x6;
  80. }
  81. /// SBI Implementation IDs.
  82. ///
  83. /// Declared in §4.9.
  84. pub mod impl_id {
  85. /// Berkley Bootloader.
  86. pub const BBL: usize = 0;
  87. /// OpenSBI.
  88. pub const OPEN_SBI: usize = 1;
  89. /// Xvisor.
  90. pub const XVISOR: usize = 2;
  91. /// KVM.
  92. pub const KVM: usize = 3;
  93. /// RustSBI.
  94. pub const RUST_SBI: usize = 4;
  95. /// Diosix.
  96. pub const DIOSIX: usize = 5;
  97. /// Coffer.
  98. pub const COFFER: usize = 6;
  99. /// Xen Project.
  100. pub const XEN: usize = 7;
  101. /// PolarFire Hart Software Services.
  102. pub const POLARFIRE_HSS: usize = 8;
  103. /// Coreboot.
  104. pub const COREBOOT: usize = 9;
  105. /// Oreboot.
  106. pub const OREBOOT: usize = 10;
  107. }
  108. #[cfg(test)]
  109. mod tests {
  110. use super::Version;
  111. #[test]
  112. fn version_parse() {
  113. let v1_0 = Version::from_raw(0x100_0000);
  114. assert_eq!(v1_0.major(), 1);
  115. assert_eq!(v1_0.minor(), 0);
  116. let v2_0 = Version::from_raw(0x200_0000);
  117. assert_eq!(v2_0.major(), 2);
  118. assert_eq!(v2_0.minor(), 0);
  119. let v2_1 = Version::from_raw(0x200_0001);
  120. assert_eq!(v2_1.major(), 2);
  121. assert_eq!(v2_1.minor(), 1);
  122. let v2_max = Version::from_raw(0x2ff_ffff);
  123. assert_eq!(v2_max.major(), 2);
  124. assert_eq!(v2_max.minor(), 16777215);
  125. let vmax_3 = Version::from_raw(0x7f00_0003);
  126. assert_eq!(vmax_3.major(), 127);
  127. assert_eq!(vmax_3.minor(), 3);
  128. let vmax_max = Version::from_raw(0x7fff_ffff);
  129. assert_eq!(vmax_max.major(), 127);
  130. assert_eq!(vmax_max.minor(), 16777215);
  131. }
  132. #[test]
  133. fn version_display() {
  134. extern crate alloc;
  135. use alloc::string::ToString;
  136. assert_eq!("0.0", &Version::from_raw(0).to_string());
  137. assert_eq!("0.1", &Version::from_raw(0x1).to_string());
  138. assert_eq!("1.0", &Version::from_raw(0x100_0000).to_string());
  139. assert_eq!("1.1", &Version::from_raw(0x100_0001).to_string());
  140. assert_eq!("2.0", &Version::from_raw(0x200_0000).to_string());
  141. assert_eq!("127.0", &Version::from_raw(0x7f00_0000).to_string());
  142. assert_eq!("2.16777215", &Version::from_raw(0x2ff_ffff).to_string());
  143. assert_eq!("127.16777215", &Version::from_raw(0x7fff_ffff).to_string());
  144. }
  145. #[test]
  146. fn version_ordering() {
  147. use core::cmp::Ordering;
  148. let v0_0 = Version::from_raw(0x0);
  149. let v0_3 = Version::from_raw(0x3);
  150. let v1_0 = Version::from_raw(0x100_0000);
  151. let v2_0 = Version::from_raw(0x200_0000);
  152. let v2_1 = Version::from_raw(0x200_0001);
  153. let v2_max = Version::from_raw(0x2ff_ffff);
  154. let vmax_3 = Version::from_raw(0x7f00_0003);
  155. let vmax_max = Version::from_raw(0x7fff_ffff);
  156. assert!(v0_3 != v0_0);
  157. assert!(!(v0_3 == v0_0));
  158. assert!(v0_0 == v0_0);
  159. assert!(vmax_max == vmax_max);
  160. assert!(v0_3 > v0_0);
  161. assert!(v0_3 >= v0_0);
  162. assert!(v0_0 < v0_3);
  163. assert!(v0_0 <= v0_3);
  164. assert!(v0_0 >= v0_0);
  165. assert!(v0_0 <= v0_0);
  166. assert!(v0_3 > v0_0);
  167. assert!(v1_0 > v0_3);
  168. assert!(v2_0 > v1_0);
  169. assert!(v2_1 > v2_0);
  170. assert!(v2_max > v2_1);
  171. assert!(vmax_3 > v2_max);
  172. assert!(vmax_max > vmax_3);
  173. assert_eq!(Version::partial_cmp(&v1_0, &v0_0), Some(Ordering::Greater));
  174. assert_eq!(Version::partial_cmp(&v0_0, &v1_0), Some(Ordering::Less));
  175. assert_eq!(Version::partial_cmp(&v0_0, &v0_0), Some(Ordering::Equal));
  176. assert_eq!(Version::max(v0_0, v0_0), v0_0);
  177. assert_eq!(Version::max(v1_0, v0_0), v1_0);
  178. assert_eq!(Version::max(v0_0, v1_0), v1_0);
  179. assert_eq!(Version::min(v0_0, v0_0), v0_0);
  180. assert_eq!(Version::min(v1_0, v0_0), v0_0);
  181. assert_eq!(Version::min(v0_0, v1_0), v0_0);
  182. assert_eq!(v0_0.clamp(v0_3, v2_0), v0_3);
  183. assert_eq!(v0_3.clamp(v0_3, v2_0), v0_3);
  184. assert_eq!(v1_0.clamp(v0_3, v2_0), v1_0);
  185. assert_eq!(v2_0.clamp(v0_3, v2_0), v2_0);
  186. assert_eq!(v2_1.clamp(v0_3, v2_0), v2_0);
  187. }
  188. }