base.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //! Chapter 4. Base Extension (EID #0x10)
  2. use crate::binary::{sbi_call_0, sbi_call_1};
  3. use sbi_spec::base::{
  4. Version, EID_BASE, GET_MARCHID, GET_MIMPID, GET_MVENDORID, GET_SBI_IMPL_ID,
  5. GET_SBI_IMPL_VERSION, GET_SBI_SPEC_VERSION, PROBE_EXTENSION,
  6. };
  7. /// Return the current SBI specification version.
  8. ///
  9. /// The minor number of the SBI specification is encoded in the low 24 bits,
  10. /// with the major number encoded in the next 7 bits.
  11. /// Bit 31 must be zero and is reserved for future expansion.
  12. ///
  13. /// This function is defined in RISC-V SBI Specification chapter 4.1.
  14. /// According to the introduction of chapter 4, all base extension functions
  15. /// must success and return no error code.
  16. #[inline]
  17. pub fn get_spec_version() -> Version {
  18. Version::from_raw(sbi_call_0(EID_BASE, GET_SBI_SPEC_VERSION).value)
  19. }
  20. /// Return the current SBI implementation ID.
  21. ///
  22. /// Implementation ID is different for every SBI implementation.
  23. /// It is intended that this implementation ID allows software to probe
  24. /// for SBI implementation quirks.
  25. ///
  26. /// This function is defined in RISC-V SBI Specification chapter 4.2.
  27. /// According to the introduction of chapter 4, all base extension functions
  28. /// must success and return no error code.
  29. #[inline]
  30. pub fn get_sbi_impl_id() -> usize {
  31. sbi_call_0(EID_BASE, GET_SBI_IMPL_ID).value
  32. }
  33. /// Return the current SBI implementation version.
  34. ///
  35. /// The encoding of this version number is specific to the SBI implementation.
  36. ///
  37. /// This function is defined in RISC-V SBI Specification chapter 4.3.
  38. /// According to the introduction of chapter 4, all base extension functions
  39. /// must success and return no error code.
  40. #[inline]
  41. pub fn get_sbi_impl_version() -> usize {
  42. sbi_call_0(EID_BASE, GET_SBI_IMPL_VERSION).value
  43. }
  44. /// Probe information about one SBI extension from the current environment.
  45. ///
  46. /// Returns 0 if given SBI `extension_id` is not available, or typically
  47. /// 1 if it's available. Implementation would define further non-zero
  48. /// return values for information about this extension if it is available.
  49. ///
  50. /// This function is defined in RISC-V SBI Specification chapter 4.4.
  51. /// According to the introduction of chapter 4, all base extension functions
  52. /// must success and return no error code.
  53. #[inline]
  54. pub fn probe_extension<E>(extension: E) -> ExtensionInfo
  55. where
  56. E: Extension,
  57. {
  58. let ans = sbi_call_1(EID_BASE, PROBE_EXTENSION, extension.extension_id());
  59. ExtensionInfo { raw: ans.value }
  60. }
  61. /// Return the value of `mvendorid` register in the current environment.
  62. ///
  63. /// This function returns a value that is legal for the `mvendorid` register,
  64. /// and 0 is always a legal value for this register.
  65. ///
  66. /// This function is defined in RISC-V SBI Specification chapter 4.5.
  67. /// According to the introduction of chapter 4, all base extension functions
  68. /// must success and return no error code.
  69. #[inline]
  70. pub fn get_mvendorid() -> usize {
  71. sbi_call_0(EID_BASE, GET_MVENDORID).value
  72. }
  73. /// Return value of `marchid` register in the current environment.
  74. ///
  75. /// This function returns a value that is legal for the `marchid` register,
  76. /// and 0 is always a legal value for this register.
  77. ///
  78. /// This function is defined in RISC-V SBI Specification chapter 4.6.
  79. /// According to the introduction of chapter 4, all base extension functions
  80. /// must success and return no error code.
  81. #[inline]
  82. pub fn get_marchid() -> usize {
  83. sbi_call_0(EID_BASE, GET_MARCHID).value
  84. }
  85. /// Return value of `mimpid` register in the current environment.
  86. ///
  87. /// This function returns a value that is legal for the `mimpid` register,
  88. /// and 0 is always a legal value for this register.
  89. ///
  90. /// This function is defined in RISC-V SBI Specification chapter 4.7.
  91. /// According to the introduction of chapter 4, all base extension functions
  92. /// must success and return no error code.
  93. #[inline]
  94. pub fn get_mimpid() -> usize {
  95. sbi_call_0(EID_BASE, GET_MIMPID).value
  96. }
  97. /// An SBI extension.
  98. pub trait Extension {
  99. /// Get a raw `extension_id` value to pass to SBI environment.
  100. fn extension_id(&self) -> usize;
  101. }
  102. macro_rules! define_extension {
  103. ($($struct:ident($value:expr) #[$doc:meta])*) => {
  104. $(
  105. #[derive(Clone, Copy, Debug)]
  106. #[$doc]
  107. pub struct $struct;
  108. impl Extension for $struct {
  109. #[inline]
  110. fn extension_id(&self) -> usize {
  111. $value
  112. }
  113. }
  114. )*
  115. };
  116. }
  117. define_extension! {
  118. Base(sbi_spec::base::EID_BASE) /// RISC-V SBI Base extension.
  119. Timer(sbi_spec::time::EID_TIME) /// Timer programmer extension.
  120. Ipi(sbi_spec::spi::EID_SPI) /// Inter-processor Interrupt extension.
  121. Fence(sbi_spec::rfnc::EID_RFNC) /// Remote Fence extension.
  122. Hsm(sbi_spec::hsm::EID_HSM) /// Hart State Monitor extension.
  123. Reset(sbi_spec::srst::EID_SRST) /// System Reset extension.
  124. Pmu(sbi_spec::pmu::EID_PMU) /// Performance Monitoring Unit extension.
  125. Console(sbi_spec::dbcn::EID_DBCN) /// Debug Console extension.
  126. Suspend(sbi_spec::susp::SUSPEND) /// System Suspend extension.
  127. Cppc(sbi_spec::cppc::EID_CPPC) /// SBI CPPC extension.
  128. Nacl(sbi_spec::nacl::EID_NACL) /// Nested Acceleration extension.
  129. Sta(sbi_spec::sta::EID_STA) /// Steal-time Accounting extension.
  130. }
  131. #[cfg(feature = "integer-impls")]
  132. impl Extension for usize {
  133. #[inline]
  134. fn extension_id(&self) -> usize {
  135. *self
  136. }
  137. }
  138. #[cfg(feature = "integer-impls")]
  139. impl Extension for isize {
  140. #[inline]
  141. fn extension_id(&self) -> usize {
  142. usize::from_ne_bytes(isize::to_ne_bytes(*self))
  143. }
  144. }
  145. /// Information about an SBI extension.
  146. #[derive(Clone, Copy, Debug)]
  147. pub struct ExtensionInfo {
  148. pub raw: usize,
  149. }
  150. impl ExtensionInfo {
  151. /// Is this extension available?
  152. #[inline]
  153. pub const fn is_available(&self) -> bool {
  154. self.raw != 0
  155. }
  156. /// Is this extension not available?
  157. #[inline]
  158. pub const fn is_unavailable(&self) -> bool {
  159. self.raw == 0
  160. }
  161. }
  162. #[cfg(test)]
  163. mod tests {
  164. #[test]
  165. fn extension_id_defined() {
  166. use crate::Extension;
  167. assert_eq!(crate::Base.extension_id(), 0x10);
  168. assert_eq!(crate::Timer.extension_id(), 0x54494D45);
  169. assert_eq!(crate::Ipi.extension_id(), 0x735049);
  170. assert_eq!(crate::Fence.extension_id(), 0x52464E43);
  171. assert_eq!(crate::Hsm.extension_id(), 0x48534D);
  172. assert_eq!(crate::Reset.extension_id(), 0x53525354);
  173. assert_eq!(crate::Pmu.extension_id(), 0x504D55);
  174. assert_eq!(crate::Console.extension_id(), 0x4442434E);
  175. assert_eq!(crate::Suspend.extension_id(), 0x53555350);
  176. assert_eq!(crate::Cppc.extension_id(), 0x43505043);
  177. assert_eq!(crate::Nacl.extension_id(), 0x4E41434C);
  178. assert_eq!(crate::Sta.extension_id(), 0x535441);
  179. }
  180. }