binary.rs 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895
  1. //! Chapter 3. Binary Encoding.
  2. use core::marker::PhantomData;
  3. /// SBI functions return type.
  4. ///
  5. /// > SBI functions must return a pair of values in a0 and a1,
  6. /// > with a0 returning an error code.
  7. /// > This is analogous to returning the C structure `SbiRet`.
  8. ///
  9. /// Note: if this structure is used in function return on conventional
  10. /// Rust code, it would not require pinning memory representation as
  11. /// extern C. The `repr(C)` is set in case that some users want to use
  12. /// this structure in FFI code.
  13. #[derive(Clone, Copy, PartialEq, Eq)]
  14. #[repr(C)]
  15. pub struct SbiRet<T = usize> {
  16. /// Error number.
  17. pub error: T,
  18. /// Result value.
  19. pub value: T,
  20. }
  21. /// SBI success state return value.
  22. pub const RET_SUCCESS: usize = <usize as SbiRegister>::RET_SUCCESS;
  23. /// Error for SBI call failed for unknown reasons.
  24. pub const RET_ERR_FAILED: usize = <usize as SbiRegister>::RET_ERR_FAILED;
  25. /// Error for target operation not supported.
  26. pub const RET_ERR_NOT_SUPPORTED: usize = <usize as SbiRegister>::RET_ERR_NOT_SUPPORTED;
  27. /// Error for invalid parameter.
  28. pub const RET_ERR_INVALID_PARAM: usize = <usize as SbiRegister>::RET_ERR_INVALID_PARAM;
  29. /// Error for denied.
  30. pub const RET_ERR_DENIED: usize = <usize as SbiRegister>::RET_ERR_DENIED;
  31. /// Error for invalid address.
  32. pub const RET_ERR_INVALID_ADDRESS: usize = <usize as SbiRegister>::RET_ERR_INVALID_ADDRESS;
  33. /// Error for resource already available.
  34. pub const RET_ERR_ALREADY_AVAILABLE: usize = <usize as SbiRegister>::RET_ERR_ALREADY_AVAILABLE;
  35. /// Error for resource already started.
  36. pub const RET_ERR_ALREADY_STARTED: usize = <usize as SbiRegister>::RET_ERR_ALREADY_STARTED;
  37. /// Error for resource already stopped.
  38. pub const RET_ERR_ALREADY_STOPPED: usize = <usize as SbiRegister>::RET_ERR_ALREADY_STOPPED;
  39. /// Error for shared memory not available.
  40. pub const RET_ERR_NO_SHMEM: usize = <usize as SbiRegister>::RET_ERR_NO_SHMEM;
  41. /// Error for invalid state.
  42. pub const RET_ERR_INVALID_STATE: usize = <usize as SbiRegister>::RET_ERR_INVALID_STATE;
  43. /// Error for bad or invalid range.
  44. pub const RET_ERR_BAD_RANGE: usize = <usize as SbiRegister>::RET_ERR_BAD_RANGE;
  45. /// Error for failed due to timeout.
  46. pub const RET_ERR_TIMEOUT: usize = <usize as SbiRegister>::RET_ERR_TIMEOUT;
  47. /// Error for input or output error.
  48. pub const RET_ERR_IO: usize = <usize as SbiRegister>::RET_ERR_IO;
  49. /// Data type of register that can be passed to the RISC-V SBI ABI.
  50. ///
  51. /// This trait defines the requirements for types that are used as the underlying
  52. /// representation for both the `value` and `error` fields in the `SbiRet` structure.
  53. /// In most cases, this trait is implemented for primitive integer types (e.g., `usize`),
  54. /// but it can also be implemented for other types that satisfy the constraints.
  55. ///
  56. /// # Examples
  57. ///
  58. /// Implemented automatically for all types that satisfy `Copy`, `Eq`, and `Debug`.
  59. pub trait SbiRegister: Copy + Eq + Ord + core::fmt::Debug {
  60. /// SBI success state return value.
  61. const RET_SUCCESS: Self;
  62. /// Error for SBI call failed for unknown reasons.
  63. const RET_ERR_FAILED: Self;
  64. /// Error for target operation not supported.
  65. const RET_ERR_NOT_SUPPORTED: Self;
  66. /// Error for invalid parameter.
  67. const RET_ERR_INVALID_PARAM: Self;
  68. /// Error for denied.
  69. const RET_ERR_DENIED: Self;
  70. /// Error for invalid address.
  71. const RET_ERR_INVALID_ADDRESS: Self;
  72. /// Error for resource already available.
  73. const RET_ERR_ALREADY_AVAILABLE: Self;
  74. /// Error for resource already started.
  75. const RET_ERR_ALREADY_STARTED: Self;
  76. /// Error for resource already stopped.
  77. const RET_ERR_ALREADY_STOPPED: Self;
  78. /// Error for shared memory not available.
  79. const RET_ERR_NO_SHMEM: Self;
  80. /// Error for invalid state.
  81. const RET_ERR_INVALID_STATE: Self;
  82. /// Error for bad or invalid range.
  83. const RET_ERR_BAD_RANGE: Self;
  84. /// Error for failed due to timeout.
  85. const RET_ERR_TIMEOUT: Self;
  86. /// Error for input or output error.
  87. const RET_ERR_IO: Self;
  88. /// Zero value for this type; this is used on `value` fields once `SbiRet` returns an error.
  89. const ZERO: Self;
  90. /// Full-ones value for this type; this is used on SBI mask structures like `CounterMask`
  91. /// and `HartMask`.
  92. const FULL_MASK: Self;
  93. /// Converts an `SbiRet` of this type to a `Result` of self and `Error`.
  94. fn into_result(ret: SbiRet<Self>) -> Result<Self, Error<Self>>;
  95. }
  96. macro_rules! impl_sbi_register {
  97. ($ty:ty, $signed:ty) => {
  98. impl SbiRegister for $ty {
  99. const RET_SUCCESS: Self = 0;
  100. const RET_ERR_FAILED: Self = -1 as $signed as $ty;
  101. const RET_ERR_NOT_SUPPORTED: Self = -2 as $signed as $ty;
  102. const RET_ERR_INVALID_PARAM: Self = -3 as $signed as $ty;
  103. const RET_ERR_DENIED: Self = -4 as $signed as $ty;
  104. const RET_ERR_INVALID_ADDRESS: Self = -5 as $signed as $ty;
  105. const RET_ERR_ALREADY_AVAILABLE: Self = -6 as $signed as $ty;
  106. const RET_ERR_ALREADY_STARTED: Self = -7 as $signed as $ty;
  107. const RET_ERR_ALREADY_STOPPED: Self = -8 as $signed as $ty;
  108. const RET_ERR_NO_SHMEM: Self = -9 as $signed as $ty;
  109. const RET_ERR_INVALID_STATE: Self = -10 as $signed as $ty;
  110. const RET_ERR_BAD_RANGE: Self = -11 as $signed as $ty;
  111. const RET_ERR_TIMEOUT: Self = -12 as $signed as $ty;
  112. const RET_ERR_IO: Self = -13 as $signed as $ty;
  113. const ZERO: Self = 0;
  114. const FULL_MASK: Self = !0;
  115. fn into_result(ret: SbiRet<Self>) -> Result<Self, Error<Self>> {
  116. match ret.error {
  117. Self::RET_SUCCESS => Ok(ret.value),
  118. Self::RET_ERR_FAILED => Err(Error::Failed),
  119. Self::RET_ERR_NOT_SUPPORTED => Err(Error::NotSupported),
  120. Self::RET_ERR_INVALID_PARAM => Err(Error::InvalidParam),
  121. Self::RET_ERR_DENIED => Err(Error::Denied),
  122. Self::RET_ERR_INVALID_ADDRESS => Err(Error::InvalidAddress),
  123. Self::RET_ERR_ALREADY_AVAILABLE => Err(Error::AlreadyAvailable),
  124. Self::RET_ERR_ALREADY_STARTED => Err(Error::AlreadyStarted),
  125. Self::RET_ERR_ALREADY_STOPPED => Err(Error::AlreadyStopped),
  126. Self::RET_ERR_NO_SHMEM => Err(Error::NoShmem),
  127. Self::RET_ERR_INVALID_STATE => Err(Error::InvalidState),
  128. Self::RET_ERR_BAD_RANGE => Err(Error::BadRange),
  129. Self::RET_ERR_TIMEOUT => Err(Error::Timeout),
  130. Self::RET_ERR_IO => Err(Error::Io),
  131. unknown => Err(Error::Custom(unknown as _)),
  132. }
  133. }
  134. }
  135. };
  136. }
  137. impl_sbi_register!(usize, isize);
  138. impl_sbi_register!(isize, isize);
  139. impl_sbi_register!(u32, i32);
  140. impl_sbi_register!(i32, i32);
  141. impl_sbi_register!(u64, i64);
  142. impl_sbi_register!(i64, i64);
  143. impl_sbi_register!(u128, i128);
  144. impl_sbi_register!(i128, i128);
  145. impl<T: SbiRegister + core::fmt::LowerHex> core::fmt::Debug for SbiRet<T> {
  146. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  147. match T::into_result(*self) {
  148. Ok(value) => write!(f, "{:?}", value),
  149. Err(err) => match err {
  150. Error::Failed => write!(f, "<SBI call failed>"),
  151. Error::NotSupported => write!(f, "<SBI feature not supported>"),
  152. Error::InvalidParam => write!(f, "<SBI invalid parameter>"),
  153. Error::Denied => write!(f, "<SBI denied>"),
  154. Error::InvalidAddress => write!(f, "<SBI invalid address>"),
  155. Error::AlreadyAvailable => write!(f, "<SBI already available>"),
  156. Error::AlreadyStarted => write!(f, "<SBI already started>"),
  157. Error::AlreadyStopped => write!(f, "<SBI already stopped>"),
  158. Error::NoShmem => write!(f, "<SBI shared memory not available>"),
  159. Error::InvalidState => write!(f, "<SBI invalid state>"),
  160. Error::BadRange => write!(f, "<SBI bad range>"),
  161. Error::Timeout => write!(f, "<SBI timeout>"),
  162. Error::Io => write!(f, "<SBI input/output error>"),
  163. Error::Custom(unknown) => write!(f, "[SBI Unknown error: {:#x}]", unknown),
  164. },
  165. }
  166. }
  167. }
  168. /// RISC-V SBI error in enumeration.
  169. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  170. pub enum Error<T = usize> {
  171. /// Error for SBI call failed for unknown reasons.
  172. Failed,
  173. /// Error for target operation not supported.
  174. NotSupported,
  175. /// Error for invalid parameter.
  176. InvalidParam,
  177. /// Error for denied.
  178. Denied,
  179. /// Error for invalid address.
  180. InvalidAddress,
  181. /// Error for resource already available.
  182. AlreadyAvailable,
  183. /// Error for resource already started.
  184. AlreadyStarted,
  185. /// Error for resource already stopped.
  186. AlreadyStopped,
  187. /// Error for shared memory not available.
  188. NoShmem,
  189. /// Error for invalid state.
  190. InvalidState,
  191. /// Error for bad or invalid range.
  192. BadRange,
  193. /// Error for failed due to timeout.
  194. Timeout,
  195. /// Error for input or output error.
  196. Io,
  197. /// Custom error code.
  198. Custom(T),
  199. }
  200. impl<T: SbiRegister> SbiRet<T> {
  201. /// Returns success SBI state with given `value`.
  202. #[inline]
  203. pub const fn success(value: T) -> Self {
  204. Self {
  205. error: T::RET_SUCCESS,
  206. value,
  207. }
  208. }
  209. /// The SBI call request failed for unknown reasons.
  210. #[inline]
  211. pub const fn failed() -> Self {
  212. Self {
  213. error: T::RET_ERR_FAILED,
  214. value: T::ZERO,
  215. }
  216. }
  217. /// SBI call failed due to not supported by target ISA,
  218. /// operation type not supported,
  219. /// or target operation type not implemented on purpose.
  220. #[inline]
  221. pub const fn not_supported() -> Self {
  222. Self {
  223. error: T::RET_ERR_NOT_SUPPORTED,
  224. value: T::ZERO,
  225. }
  226. }
  227. /// SBI call failed due to invalid hart mask parameter,
  228. /// invalid target hart id,
  229. /// invalid operation type,
  230. /// or invalid resource index.
  231. #[inline]
  232. pub const fn invalid_param() -> Self {
  233. Self {
  234. error: T::RET_ERR_INVALID_PARAM,
  235. value: T::ZERO,
  236. }
  237. }
  238. /// SBI call denied for unsatisfied entry criteria, or insufficient access
  239. /// permission to debug console or CPPC register.
  240. #[inline]
  241. pub const fn denied() -> Self {
  242. Self {
  243. error: T::RET_ERR_DENIED,
  244. value: T::ZERO,
  245. }
  246. }
  247. /// SBI call failed for invalid mask start address,
  248. /// not a valid physical address parameter,
  249. /// or the target address is prohibited by PMP to run in supervisor mode.
  250. #[inline]
  251. pub const fn invalid_address() -> Self {
  252. Self {
  253. error: T::RET_ERR_INVALID_ADDRESS,
  254. value: T::ZERO,
  255. }
  256. }
  257. /// SBI call failed for the target resource is already available,
  258. /// e.g., the target hart is already started when caller still requests it to start.
  259. #[inline]
  260. pub const fn already_available() -> Self {
  261. Self {
  262. error: T::RET_ERR_ALREADY_AVAILABLE,
  263. value: T::ZERO,
  264. }
  265. }
  266. /// SBI call failed for the target resource is already started,
  267. /// e.g., target performance counter is started.
  268. #[inline]
  269. pub const fn already_started() -> Self {
  270. Self {
  271. error: T::RET_ERR_ALREADY_STARTED,
  272. value: T::ZERO,
  273. }
  274. }
  275. /// SBI call failed for the target resource is already stopped,
  276. /// e.g., target performance counter is stopped.
  277. #[inline]
  278. pub const fn already_stopped() -> Self {
  279. Self {
  280. error: T::RET_ERR_ALREADY_STOPPED,
  281. value: T::ZERO,
  282. }
  283. }
  284. /// SBI call failed for shared memory is not available,
  285. /// e.g. nested acceleration shared memory is not available.
  286. #[inline]
  287. pub const fn no_shmem() -> Self {
  288. Self {
  289. error: T::RET_ERR_NO_SHMEM,
  290. value: T::ZERO,
  291. }
  292. }
  293. /// SBI call failed for invalid state,
  294. /// e.g. register a software event but the event is not in unused state.
  295. #[inline]
  296. pub const fn invalid_state() -> Self {
  297. Self {
  298. error: T::RET_ERR_INVALID_STATE,
  299. value: T::ZERO,
  300. }
  301. }
  302. /// SBI call failed for bad or invalid range,
  303. /// e.g. the software event is not exist in the specified range.
  304. #[inline]
  305. pub const fn bad_range() -> Self {
  306. Self {
  307. error: T::RET_ERR_BAD_RANGE,
  308. value: T::ZERO,
  309. }
  310. }
  311. /// SBI call failed for timeout,
  312. /// e.g. message send timeout.
  313. #[inline]
  314. pub const fn timeout() -> Self {
  315. Self {
  316. error: T::RET_ERR_TIMEOUT,
  317. value: T::ZERO,
  318. }
  319. }
  320. /// SBI call failed for input or output error.
  321. #[inline]
  322. pub const fn io() -> Self {
  323. Self {
  324. error: T::RET_ERR_IO,
  325. value: T::ZERO,
  326. }
  327. }
  328. }
  329. impl<T: SbiRegister> From<Error<T>> for SbiRet<T> {
  330. #[inline]
  331. fn from(value: Error<T>) -> Self {
  332. match value {
  333. Error::Failed => SbiRet::failed(),
  334. Error::NotSupported => SbiRet::not_supported(),
  335. Error::InvalidParam => SbiRet::invalid_param(),
  336. Error::Denied => SbiRet::denied(),
  337. Error::InvalidAddress => SbiRet::invalid_address(),
  338. Error::AlreadyAvailable => SbiRet::already_available(),
  339. Error::AlreadyStarted => SbiRet::already_started(),
  340. Error::AlreadyStopped => SbiRet::already_stopped(),
  341. Error::NoShmem => SbiRet::no_shmem(),
  342. Error::InvalidState => SbiRet::invalid_state(),
  343. Error::BadRange => SbiRet::bad_range(),
  344. Error::Timeout => SbiRet::timeout(),
  345. Error::Io => SbiRet::io(),
  346. Error::Custom(error) => SbiRet {
  347. error,
  348. value: T::ZERO,
  349. },
  350. }
  351. }
  352. }
  353. impl SbiRet {
  354. /// Converts to a [`Result`] of value and error.
  355. #[inline]
  356. pub const fn into_result(self) -> Result<usize, Error> {
  357. match self.error {
  358. RET_SUCCESS => Ok(self.value),
  359. RET_ERR_FAILED => Err(Error::Failed),
  360. RET_ERR_NOT_SUPPORTED => Err(Error::NotSupported),
  361. RET_ERR_INVALID_PARAM => Err(Error::InvalidParam),
  362. RET_ERR_DENIED => Err(Error::Denied),
  363. RET_ERR_INVALID_ADDRESS => Err(Error::InvalidAddress),
  364. RET_ERR_ALREADY_AVAILABLE => Err(Error::AlreadyAvailable),
  365. RET_ERR_ALREADY_STARTED => Err(Error::AlreadyStarted),
  366. RET_ERR_ALREADY_STOPPED => Err(Error::AlreadyStopped),
  367. RET_ERR_NO_SHMEM => Err(Error::NoShmem),
  368. RET_ERR_INVALID_STATE => Err(Error::InvalidState),
  369. RET_ERR_BAD_RANGE => Err(Error::BadRange),
  370. RET_ERR_TIMEOUT => Err(Error::Timeout),
  371. RET_ERR_IO => Err(Error::Io),
  372. unknown => Err(Error::Custom(unknown as _)),
  373. }
  374. }
  375. /// Returns `true` if current SBI return succeeded.
  376. ///
  377. /// # Examples
  378. ///
  379. /// Basic usage:
  380. ///
  381. /// ```
  382. /// # use sbi_spec::binary::SbiRet;
  383. /// let x = SbiRet::success(0);
  384. /// assert_eq!(x.is_ok(), true);
  385. ///
  386. /// let x = SbiRet::failed();
  387. /// assert_eq!(x.is_ok(), false);
  388. /// ```
  389. #[must_use = "if you intended to assert that this is ok, consider `.unwrap()` instead"]
  390. #[inline]
  391. pub const fn is_ok(&self) -> bool {
  392. matches!(self.error, RET_SUCCESS)
  393. }
  394. /// Returns `true` if the SBI call succeeded and the value inside of it matches a predicate.
  395. ///
  396. /// # Examples
  397. ///
  398. /// Basic usage:
  399. ///
  400. /// ```
  401. /// # use sbi_spec::binary::SbiRet;
  402. /// let x = SbiRet::success(2);
  403. /// assert_eq!(x.is_ok_and(|x| x > 1), true);
  404. ///
  405. /// let x = SbiRet::success(0);
  406. /// assert_eq!(x.is_ok_and(|x| x > 1), false);
  407. ///
  408. /// let x = SbiRet::no_shmem();
  409. /// assert_eq!(x.is_ok_and(|x| x > 1), false);
  410. /// ```
  411. #[must_use]
  412. #[inline]
  413. pub fn is_ok_and(self, f: impl FnOnce(usize) -> bool) -> bool {
  414. self.into_result().is_ok_and(f)
  415. }
  416. /// Returns `true` if current SBI return is an error.
  417. ///
  418. /// # Examples
  419. ///
  420. /// Basic usage:
  421. ///
  422. /// ```
  423. /// # use sbi_spec::binary::SbiRet;
  424. /// let x = SbiRet::success(0);
  425. /// assert_eq!(x.is_err(), false);
  426. ///
  427. /// let x = SbiRet::not_supported();
  428. /// assert_eq!(x.is_err(), true);
  429. /// ```
  430. #[must_use = "if you intended to assert that this is err, consider `.unwrap_err()` instead"]
  431. #[inline]
  432. pub const fn is_err(&self) -> bool {
  433. !self.is_ok()
  434. }
  435. /// Returns `true` if the result is an error and the value inside of it matches a predicate.
  436. ///
  437. /// # Examples
  438. ///
  439. /// ```
  440. /// # use sbi_spec::binary::{SbiRet, Error};
  441. /// let x = SbiRet::denied();
  442. /// assert_eq!(x.is_err_and(|x| x == Error::Denied), true);
  443. ///
  444. /// let x = SbiRet::invalid_address();
  445. /// assert_eq!(x.is_err_and(|x| x == Error::Denied), false);
  446. ///
  447. /// let x = SbiRet::success(0);
  448. /// assert_eq!(x.is_err_and(|x| x == Error::Denied), false);
  449. /// ```
  450. #[must_use]
  451. #[inline]
  452. pub fn is_err_and(self, f: impl FnOnce(Error) -> bool) -> bool {
  453. self.into_result().is_err_and(f)
  454. }
  455. /// Converts from `SbiRet` to [`Option<usize>`].
  456. ///
  457. /// Converts `self` into an [`Option<usize>`], consuming `self`,
  458. /// and discarding the error, if any.
  459. ///
  460. /// # Examples
  461. ///
  462. /// Basic usage:
  463. ///
  464. /// ```
  465. /// # use sbi_spec::binary::SbiRet;
  466. /// let x = SbiRet::success(2);
  467. /// assert_eq!(x.ok(), Some(2));
  468. ///
  469. /// let x = SbiRet::invalid_param();
  470. /// assert_eq!(x.ok(), None);
  471. /// ```
  472. // fixme: should be pub const fn once this function in Result is stablized in constant
  473. #[inline]
  474. pub fn ok(self) -> Option<usize> {
  475. self.into_result().ok()
  476. }
  477. /// Converts from `SbiRet` to [`Option<Error>`].
  478. ///
  479. /// Converts `self` into an [`Option<Error>`], consuming `self`,
  480. /// and discarding the success value, if any.
  481. ///
  482. /// # Examples
  483. ///
  484. /// Basic usage:
  485. ///
  486. /// ```
  487. /// # use sbi_spec::binary::{SbiRet, Error};
  488. /// let x = SbiRet::success(2);
  489. /// assert_eq!(x.err(), None);
  490. ///
  491. /// let x = SbiRet::denied();
  492. /// assert_eq!(x.err(), Some(Error::Denied));
  493. /// ```
  494. // fixme: should be pub const fn once this function in Result is stablized in constant
  495. #[inline]
  496. pub fn err(self) -> Option<Error> {
  497. self.into_result().err()
  498. }
  499. /// Maps a `SbiRet` to `Result<U, Error>` by applying a function to a
  500. /// contained success value, leaving an error value untouched.
  501. ///
  502. /// This function can be used to compose the results of two functions.
  503. ///
  504. /// # Examples
  505. ///
  506. /// Gets detail of a PMU counter and judge if it is a firmware counter.
  507. ///
  508. /// ```
  509. /// # use sbi_spec::binary::SbiRet;
  510. /// # use core::mem::size_of;
  511. /// # mod sbi_rt {
  512. /// # use sbi_spec::binary::SbiRet;
  513. /// # const TYPE_MASK: usize = 1 << (core::mem::size_of::<usize>() - 1);
  514. /// # pub fn pmu_counter_get_info(_: usize) -> SbiRet { SbiRet::success(TYPE_MASK) }
  515. /// # }
  516. /// // We assume that counter index 42 is a firmware counter.
  517. /// let counter_idx = 42;
  518. /// // Masks PMU counter type by setting highest bit in `usize`.
  519. /// const TYPE_MASK: usize = 1 << (size_of::<usize>() - 1);
  520. /// // Highest bit of returned `counter_info` represents whether it's
  521. /// // a firmware counter or a hardware counter.
  522. /// let is_firmware_counter = sbi_rt::pmu_counter_get_info(counter_idx)
  523. /// .map(|counter_info| counter_info & TYPE_MASK != 0);
  524. /// // If that bit is set, it is a firmware counter.
  525. /// assert_eq!(is_firmware_counter, Ok(true));
  526. /// ```
  527. #[inline]
  528. pub fn map<U, F: FnOnce(usize) -> U>(self, op: F) -> Result<U, Error> {
  529. self.into_result().map(op)
  530. }
  531. /// Returns the provided default (if error),
  532. /// or applies a function to the contained value (if success).
  533. ///
  534. /// Arguments passed to `map_or` are eagerly evaluated;
  535. /// if you are passing the result of a function call,
  536. /// it is recommended to use [`map_or_else`],
  537. /// which is lazily evaluated.
  538. ///
  539. /// [`map_or_else`]: SbiRet::map_or_else
  540. ///
  541. /// # Examples
  542. ///
  543. /// ```
  544. /// # use sbi_spec::binary::SbiRet;
  545. /// let x = SbiRet::success(3);
  546. /// assert_eq!(x.map_or(42, |v| v & 0b1), 1);
  547. ///
  548. /// let x = SbiRet::invalid_address();
  549. /// assert_eq!(x.map_or(42, |v| v & 0b1), 42);
  550. /// ```
  551. #[inline]
  552. pub fn map_or<U, F: FnOnce(usize) -> U>(self, default: U, f: F) -> U {
  553. self.into_result().map_or(default, f)
  554. }
  555. /// Maps a `SbiRet` to `usize` value by applying fallback function `default` to
  556. /// a contained error, or function `f` to a contained success value.
  557. ///
  558. /// This function can be used to unpack a successful result
  559. /// while handling an error.
  560. ///
  561. /// # Examples
  562. ///
  563. /// Basic usage:
  564. ///
  565. /// ```
  566. /// # use sbi_spec::binary::SbiRet;
  567. /// let k = 21;
  568. ///
  569. /// let x = SbiRet::success(3);
  570. /// assert_eq!(x.map_or_else(|e| k * 2, |v| v & 0b1), 1);
  571. ///
  572. /// let x = SbiRet::already_available();
  573. /// assert_eq!(x.map_or_else(|e| k * 2, |v| v & 0b1), 42);
  574. /// ```
  575. #[inline]
  576. pub fn map_or_else<U, D: FnOnce(Error) -> U, F: FnOnce(usize) -> U>(
  577. self,
  578. default: D,
  579. f: F,
  580. ) -> U {
  581. self.into_result().map_or_else(default, f)
  582. }
  583. /// Maps a `SbiRet` to `Result<T, F>` by applying a function to a
  584. /// contained error as [`Error`] struct, leaving success value untouched.
  585. ///
  586. /// This function can be used to pass through a successful result while handling
  587. /// an error.
  588. ///
  589. /// # Examples
  590. ///
  591. /// Basic usage:
  592. ///
  593. /// ```
  594. /// # use sbi_spec::binary::{SbiRet, Error};
  595. /// fn stringify(x: Error) -> String {
  596. /// if x == Error::AlreadyStarted {
  597. /// "error: already started!".to_string()
  598. /// } else {
  599. /// "error: other error!".to_string()
  600. /// }
  601. /// }
  602. ///
  603. /// let x = SbiRet::success(2);
  604. /// assert_eq!(x.map_err(stringify), Ok(2));
  605. ///
  606. /// let x = SbiRet::already_started();
  607. /// assert_eq!(x.map_err(stringify), Err("error: already started!".to_string()));
  608. /// ```
  609. #[inline]
  610. pub fn map_err<F, O: FnOnce(Error) -> F>(self, op: O) -> Result<usize, F> {
  611. self.into_result().map_err(op)
  612. }
  613. /// Calls a function with a reference to the contained value if current SBI call succeeded.
  614. ///
  615. /// Returns the original result.
  616. ///
  617. /// # Examples
  618. ///
  619. /// ```
  620. /// # use sbi_spec::binary::SbiRet;
  621. /// // Assume that SBI debug console have read 512 bytes into a buffer.
  622. /// let ret = SbiRet::success(512);
  623. /// // Inspect the SBI DBCN call result.
  624. /// let idx = ret
  625. /// .inspect(|x| println!("bytes written: {x}"))
  626. /// .map(|x| x - 1)
  627. /// .expect("SBI DBCN call failed");
  628. /// assert_eq!(idx, 511);
  629. /// ```
  630. #[inline]
  631. pub fn inspect<F: FnOnce(&usize)>(self, f: F) -> Self {
  632. if let Ok(ref t) = self.into_result() {
  633. f(t);
  634. }
  635. self
  636. }
  637. /// Calls a function with a reference to the contained value if current SBI result is an error.
  638. ///
  639. /// Returns the original result.
  640. ///
  641. /// # Examples
  642. ///
  643. /// ```
  644. /// # use sbi_spec::binary::SbiRet;
  645. /// // Assume that SBI debug console write operation failed for invalid parameter.
  646. /// let ret = SbiRet::invalid_param();
  647. /// // Print the error if SBI DBCN call failed.
  648. /// let ret = ret.inspect_err(|e| eprintln!("failed to read from SBI console: {e:?}"));
  649. /// ```
  650. #[inline]
  651. pub fn inspect_err<F: FnOnce(&Error)>(self, f: F) -> Self {
  652. if let Err(ref e) = self.into_result() {
  653. f(e);
  654. }
  655. self
  656. }
  657. // TODO: pub fn iter(&self) -> Iter
  658. // TODO: pub fn iter_mut(&mut self) -> IterMut
  659. /// Returns the contained success value, consuming the `self` value.
  660. ///
  661. /// # Panics
  662. ///
  663. /// Panics if self is an SBI error with a panic message including the
  664. /// passed message, and the content of the SBI state.
  665. ///
  666. /// # Examples
  667. ///
  668. /// Basic usage:
  669. ///
  670. /// ```should_panic
  671. /// # use sbi_spec::binary::SbiRet;
  672. /// let x = SbiRet::already_stopped();
  673. /// x.expect("Testing expect"); // panics with `Testing expect`
  674. /// ```
  675. #[inline]
  676. pub fn expect(self, msg: &str) -> usize {
  677. self.into_result().expect(msg)
  678. }
  679. /// Returns the contained success value, consuming the `self` value.
  680. ///
  681. /// # Panics
  682. ///
  683. /// Panics if self is an SBI error, with a panic message provided by the
  684. /// SBI error converted into [`Error`] struct.
  685. ///
  686. /// # Examples
  687. ///
  688. /// Basic usage:
  689. ///
  690. /// ```
  691. /// # use sbi_spec::binary::SbiRet;
  692. /// let x = SbiRet::success(2);
  693. /// assert_eq!(x.unwrap(), 2);
  694. /// ```
  695. ///
  696. /// ```should_panic
  697. /// # use sbi_spec::binary::SbiRet;
  698. /// let x = SbiRet::failed();
  699. /// x.unwrap(); // panics
  700. /// ```
  701. #[inline]
  702. pub fn unwrap(self) -> usize {
  703. self.into_result().unwrap()
  704. }
  705. // Note: No unwrap_or_default as we cannot determine a meaningful default value for a successful SbiRet.
  706. /// Returns the contained error as [`Error`] struct, consuming the `self` value.
  707. ///
  708. /// # Panics
  709. ///
  710. /// Panics if the self is SBI success value, with a panic message
  711. /// including the passed message, and the content of the success value.
  712. ///
  713. /// # Examples
  714. ///
  715. /// Basic usage:
  716. ///
  717. /// ```should_panic
  718. /// # use sbi_spec::binary::SbiRet;
  719. /// let x = SbiRet::success(10);
  720. /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err`
  721. /// ```
  722. #[inline]
  723. pub fn expect_err(self, msg: &str) -> Error {
  724. self.into_result().expect_err(msg)
  725. }
  726. /// Returns the contained error as [`Error`] struct, consuming the `self` value.
  727. ///
  728. /// # Panics
  729. ///
  730. /// Panics if the self is SBI success value, with a custom panic message provided
  731. /// by the success value.
  732. ///
  733. /// # Examples
  734. ///
  735. /// ```should_panic
  736. /// # use sbi_spec::binary::SbiRet;
  737. /// let x = SbiRet::success(2);
  738. /// x.unwrap_err(); // panics with `2`
  739. /// ```
  740. ///
  741. /// ```
  742. /// # use sbi_spec::binary::{SbiRet, Error};
  743. /// let x = SbiRet::not_supported();
  744. /// assert_eq!(x.unwrap_err(), Error::NotSupported);
  745. /// ```
  746. #[inline]
  747. pub fn unwrap_err(self) -> Error {
  748. self.into_result().unwrap_err()
  749. }
  750. // TODO: pub fn into_ok(self) -> usize and pub fn into_err(self) -> Error
  751. // once `unwrap_infallible` is stablized
  752. /// Returns `res` if self is success value, otherwise otherwise returns the contained error
  753. /// of `self` as [`Error`] struct.
  754. ///
  755. /// Arguments passed to `and` are eagerly evaluated; if you are passing the
  756. /// result of a function call, it is recommended to use [`and_then`], which is
  757. /// lazily evaluated.
  758. ///
  759. /// [`and_then`]: SbiRet::and_then
  760. ///
  761. /// # Examples
  762. ///
  763. /// Basic usage:
  764. ///
  765. /// ```
  766. /// # use sbi_spec::binary::{SbiRet, Error};
  767. /// let x = SbiRet::success(2);
  768. /// let y = SbiRet::invalid_param().into_result();
  769. /// assert_eq!(x.and(y), Err(Error::InvalidParam));
  770. ///
  771. /// let x = SbiRet::denied();
  772. /// let y = SbiRet::success(3).into_result();
  773. /// assert_eq!(x.and(y), Err(Error::Denied));
  774. ///
  775. /// let x = SbiRet::invalid_address();
  776. /// let y = SbiRet::already_available().into_result();
  777. /// assert_eq!(x.and(y), Err(Error::InvalidAddress));
  778. ///
  779. /// let x = SbiRet::success(4);
  780. /// let y = SbiRet::success(5).into_result();
  781. /// assert_eq!(x.and(y), Ok(5));
  782. /// ```
  783. // fixme: should be pub const fn once this function in Result is stablized in constant
  784. // fixme: should parameter be `res: SbiRet`?
  785. #[inline]
  786. pub fn and<U>(self, res: Result<U, Error>) -> Result<U, Error> {
  787. self.into_result().and(res)
  788. }
  789. /// Calls `op` if self is success value, otherwise returns the contained error
  790. /// as [`Error`] struct.
  791. ///
  792. /// This function can be used for control flow based on `SbiRet` values.
  793. ///
  794. /// # Examples
  795. ///
  796. /// ```
  797. /// # use sbi_spec::binary::{SbiRet, Error};
  798. /// fn sq_then_to_string(x: usize) -> Result<String, Error> {
  799. /// x.checked_mul(x).map(|sq| sq.to_string()).ok_or(Error::Failed)
  800. /// }
  801. ///
  802. /// assert_eq!(SbiRet::success(2).and_then(sq_then_to_string), Ok(4.to_string()));
  803. /// assert_eq!(SbiRet::success(1_000_000_000_000).and_then(sq_then_to_string), Err(Error::Failed));
  804. /// assert_eq!(SbiRet::invalid_param().and_then(sq_then_to_string), Err(Error::InvalidParam));
  805. /// ```
  806. #[inline]
  807. pub fn and_then<U, F: FnOnce(usize) -> Result<U, Error>>(self, op: F) -> Result<U, Error> {
  808. self.into_result().and_then(op)
  809. }
  810. /// Returns `res` if self is SBI error, otherwise returns the success value of `self`.
  811. ///
  812. /// Arguments passed to `or` are eagerly evaluated; if you are passing the
  813. /// result of a function call, it is recommended to use [`or_else`], which is
  814. /// lazily evaluated.
  815. ///
  816. /// [`or_else`]: Result::or_else
  817. ///
  818. /// # Examples
  819. ///
  820. /// Basic usage:
  821. ///
  822. /// ```
  823. /// # use sbi_spec::binary::{SbiRet, Error};
  824. /// let x = SbiRet::success(2);
  825. /// let y = SbiRet::invalid_param().into_result();
  826. /// assert_eq!(x.or(y), Ok(2));
  827. ///
  828. /// let x = SbiRet::denied();
  829. /// let y = SbiRet::success(3).into_result();
  830. /// assert_eq!(x.or(y), Ok(3));
  831. ///
  832. /// let x = SbiRet::invalid_address();
  833. /// let y = SbiRet::already_available().into_result();
  834. /// assert_eq!(x.or(y), Err(Error::AlreadyAvailable));
  835. ///
  836. /// let x = SbiRet::success(4);
  837. /// let y = SbiRet::success(100).into_result();
  838. /// assert_eq!(x.or(y), Ok(4));
  839. /// ```
  840. // fixme: should be pub const fn once this function in Result is stablized in constant
  841. // fixme: should parameter be `res: SbiRet`?
  842. #[inline]
  843. pub fn or<F>(self, res: Result<usize, F>) -> Result<usize, F> {
  844. self.into_result().or(res)
  845. }
  846. /// Calls `op` if self is SBI error, otherwise returns the success value of `self`.
  847. ///
  848. /// This function can be used for control flow based on result values.
  849. ///
  850. ///
  851. /// # Examples
  852. ///
  853. /// Basic usage:
  854. ///
  855. /// ```
  856. /// # use sbi_spec::binary::{SbiRet, Error};
  857. /// fn is_failed(x: Error) -> Result<usize, bool> { Err(x == Error::Failed) }
  858. ///
  859. /// assert_eq!(SbiRet::success(2).or_else(is_failed), Ok(2));
  860. /// assert_eq!(SbiRet::failed().or_else(is_failed), Err(true));
  861. /// ```
  862. #[inline]
  863. pub fn or_else<F, O: FnOnce(Error) -> Result<usize, F>>(self, op: O) -> Result<usize, F> {
  864. self.into_result().or_else(op)
  865. }
  866. /// Returns the contained success value or a provided default.
  867. ///
  868. /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing
  869. /// the result of a function call, it is recommended to use [`unwrap_or_else`],
  870. /// which is lazily evaluated.
  871. ///
  872. /// [`unwrap_or_else`]: SbiRet::unwrap_or_else
  873. ///
  874. /// # Examples
  875. ///
  876. /// Basic usage:
  877. ///
  878. /// ```
  879. /// # use sbi_spec::binary::SbiRet;
  880. /// let default = 2;
  881. /// let x = SbiRet::success(9);
  882. /// assert_eq!(x.unwrap_or(default), 9);
  883. ///
  884. /// let x = SbiRet::invalid_param();
  885. /// assert_eq!(x.unwrap_or(default), default);
  886. /// ```
  887. // fixme: should be pub const fn once this function in Result is stablized in constant
  888. #[inline]
  889. pub fn unwrap_or(self, default: usize) -> usize {
  890. self.into_result().unwrap_or(default)
  891. }
  892. /// Returns the contained success value or computes it from a closure.
  893. ///
  894. /// # Examples
  895. ///
  896. /// Basic usage:
  897. ///
  898. /// ```
  899. /// # use sbi_spec::binary::{SbiRet, Error};
  900. /// fn invalid_use_zero(x: Error) -> usize { if x == Error::InvalidParam { 0 } else { 3 } }
  901. ///
  902. /// assert_eq!(SbiRet::success(2).unwrap_or_else(invalid_use_zero), 2);
  903. /// assert_eq!(SbiRet::invalid_param().unwrap_or_else(invalid_use_zero), 0);
  904. /// ```
  905. #[inline]
  906. pub fn unwrap_or_else<F: FnOnce(Error) -> usize>(self, op: F) -> usize {
  907. self.into_result().unwrap_or_else(op)
  908. }
  909. /// Returns the contained success value, consuming the `self` value,
  910. /// without checking that the `SbiRet` contains an error value.
  911. ///
  912. /// # Safety
  913. ///
  914. /// Calling this method on an `SbiRet` containing an error value results
  915. /// in *undefined behavior*.
  916. ///
  917. /// # Examples
  918. ///
  919. /// ```
  920. /// # use sbi_spec::binary::{SbiRet, Error};
  921. /// let x = SbiRet::success(3);
  922. /// assert_eq!(unsafe { x.unwrap_unchecked() }, 3);
  923. /// ```
  924. ///
  925. /// ```no_run
  926. /// # use sbi_spec::binary::SbiRet;
  927. /// let x = SbiRet::no_shmem();
  928. /// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
  929. /// ```
  930. #[inline]
  931. pub unsafe fn unwrap_unchecked(self) -> usize {
  932. unsafe { self.into_result().unwrap_unchecked() }
  933. }
  934. /// Returns the contained `Error` value, consuming the `self` value,
  935. /// without checking that the `SbiRet` does not contain a success value.
  936. ///
  937. /// # Safety
  938. ///
  939. /// Calling this method on an `SbiRet` containing a success value results
  940. /// in *undefined behavior*.
  941. ///
  942. /// # Examples
  943. ///
  944. /// ```no_run
  945. /// # use sbi_spec::binary::SbiRet;
  946. /// let x = SbiRet::success(4);
  947. /// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
  948. /// ```
  949. ///
  950. /// ```
  951. /// # use sbi_spec::binary::{SbiRet, Error};
  952. /// let x = SbiRet::failed();
  953. /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, Error::Failed);
  954. /// ```
  955. #[inline]
  956. pub unsafe fn unwrap_err_unchecked(self) -> Error {
  957. unsafe { self.into_result().unwrap_err_unchecked() }
  958. }
  959. }
  960. impl IntoIterator for SbiRet {
  961. type Item = usize;
  962. type IntoIter = core::result::IntoIter<usize>;
  963. /// Returns a consuming iterator over the possibly contained value.
  964. ///
  965. /// The iterator yields one value if the result contains a success value, otherwise none.
  966. ///
  967. /// # Examples
  968. ///
  969. /// ```
  970. /// # use sbi_spec::binary::SbiRet;
  971. /// let x = SbiRet::success(5);
  972. /// let v: Vec<usize> = x.into_iter().collect();
  973. /// assert_eq!(v, [5]);
  974. ///
  975. /// let x = SbiRet::not_supported();
  976. /// let v: Vec<usize> = x.into_iter().collect();
  977. /// assert_eq!(v, []);
  978. /// ```
  979. #[inline]
  980. fn into_iter(self) -> Self::IntoIter {
  981. self.into_result().into_iter()
  982. }
  983. }
  984. // TODO: implement Try and FromResidual for SbiRet once those traits are stablized
  985. /*
  986. impl core::ops::Try for SbiRet {
  987. type Output = usize;
  988. type Residual = Result<core::convert::Infallible, Error>;
  989. #[inline]
  990. fn from_output(output: Self::Output) -> Self {
  991. SbiRet::success(output)
  992. }
  993. #[inline]
  994. fn branch(self) -> core::ops::ControlFlow<Self::Residual, Self::Output> {
  995. self.into_result().branch()
  996. }
  997. }
  998. impl core::ops::FromResidual<Result<core::convert::Infallible, Error>> for SbiRet {
  999. #[inline]
  1000. #[track_caller]
  1001. fn from_residual(residual: Result<core::convert::Infallible, Error>) -> Self {
  1002. match residual {
  1003. Err(e) => e.into(),
  1004. }
  1005. }
  1006. }
  1007. /// ```
  1008. /// # use sbi_spec::binary::SbiRet;
  1009. /// fn test() -> SbiRet {
  1010. /// let value = SbiRet::failed()?;
  1011. /// SbiRet::success(0)
  1012. /// }
  1013. /// assert_eq!(test(), SbiRet::failed());
  1014. /// ```
  1015. mod test_try_trait_for_sbiret {}
  1016. */
  1017. /// Check if the implementation can contains the provided `bit`.
  1018. #[inline]
  1019. pub(crate) const fn valid_bit(base: usize, bit: usize) -> bool {
  1020. if bit < base {
  1021. // invalid index, under minimum range.
  1022. false
  1023. } else if (bit - base) >= usize::BITS as usize {
  1024. // invalid index, over max range.
  1025. false
  1026. } else {
  1027. true
  1028. }
  1029. }
  1030. /// Check if the implementation contains the provided `bit`.
  1031. ///
  1032. /// ## Parameters
  1033. ///
  1034. /// - `mask`: bitmask defining the range of bits.
  1035. /// - `base`: the starting bit index. (default: `0`)
  1036. /// - `ignore`: if `base` is equal to this value, ignore the `mask` parameter, and consider all `bit`s set.
  1037. /// - `bit`: the bit index to check for membership in the `mask`.
  1038. #[inline]
  1039. pub(crate) const fn has_bit(mask: usize, base: usize, ignore: usize, bit: usize) -> bool {
  1040. if base == ignore {
  1041. // ignore the `mask`, consider all `bit`s as set.
  1042. true
  1043. } else if !valid_bit(base, bit) {
  1044. false
  1045. } else {
  1046. // index is in range, check if it is set in the mask.
  1047. mask & (1 << (bit - base)) != 0
  1048. }
  1049. }
  1050. /// Hart mask structure in SBI function calls.
  1051. #[repr(C)]
  1052. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
  1053. pub struct HartMask<T = usize> {
  1054. hart_mask: T,
  1055. hart_mask_base: T,
  1056. }
  1057. impl<T: SbiRegister> HartMask<T> {
  1058. /// Special value to ignore the `mask`, and consider all `bit`s as set.
  1059. pub const IGNORE_MASK: T = T::FULL_MASK;
  1060. /// Construct a [HartMask] from mask value and base hart id.
  1061. #[inline]
  1062. pub const fn from_mask_base(hart_mask: T, hart_mask_base: T) -> Self {
  1063. Self {
  1064. hart_mask,
  1065. hart_mask_base,
  1066. }
  1067. }
  1068. /// Construct a [HartMask] that selects all available harts on the current environment.
  1069. ///
  1070. /// According to the RISC-V SBI Specification, `hart_mask_base` can be set to `-1` (i.e. `usize::MAX`)
  1071. /// to indicate that `hart_mask` shall be ignored and all available harts must be considered.
  1072. /// In case of this function in the `sbi-spec` crate, we fill in `usize::MAX` in `hart_mask_base`
  1073. /// parameter to match the RISC-V SBI standard, while choosing 0 as the ignored `hart_mask` value.
  1074. #[inline]
  1075. pub const fn all() -> Self {
  1076. Self {
  1077. hart_mask: T::ZERO,
  1078. hart_mask_base: T::FULL_MASK,
  1079. }
  1080. }
  1081. /// Gets the special value for ignoring the `mask` parameter.
  1082. #[inline]
  1083. pub const fn ignore_mask(&self) -> T {
  1084. Self::IGNORE_MASK
  1085. }
  1086. /// Returns `mask` and `base` parameters from the [HartMask].
  1087. #[inline]
  1088. pub const fn into_inner(self) -> (T, T) {
  1089. (self.hart_mask, self.hart_mask_base)
  1090. }
  1091. }
  1092. // FIXME: implement for T: SbiRegister once we can implement this using const traits.
  1093. // Ref: https://rust-lang.github.io/rust-project-goals/2024h2/const-traits.html
  1094. impl HartMask<usize> {
  1095. /// Returns whether the [HartMask] contains the provided `hart_id`.
  1096. #[inline]
  1097. pub const fn has_bit(self, hart_id: usize) -> bool {
  1098. has_bit(
  1099. self.hart_mask,
  1100. self.hart_mask_base,
  1101. Self::IGNORE_MASK,
  1102. hart_id,
  1103. )
  1104. }
  1105. /// Insert a hart id into this [HartMask].
  1106. ///
  1107. /// Returns error when `hart_id` is invalid.
  1108. #[inline]
  1109. pub const fn insert(&mut self, hart_id: usize) -> Result<(), MaskError> {
  1110. if self.hart_mask_base == Self::IGNORE_MASK {
  1111. Ok(())
  1112. } else if valid_bit(self.hart_mask_base, hart_id) {
  1113. self.hart_mask |= 1usize << (hart_id - self.hart_mask_base);
  1114. Ok(())
  1115. } else {
  1116. Err(MaskError::InvalidBit)
  1117. }
  1118. }
  1119. /// Remove a hart id from this [HartMask].
  1120. ///
  1121. /// Returns error when `hart_id` is invalid, or it has been ignored.
  1122. #[inline]
  1123. pub const fn remove(&mut self, hart_id: usize) -> Result<(), MaskError> {
  1124. if self.hart_mask_base == Self::IGNORE_MASK {
  1125. Err(MaskError::Ignored)
  1126. } else if valid_bit(self.hart_mask_base, hart_id) {
  1127. self.hart_mask &= !(1usize << (hart_id - self.hart_mask_base));
  1128. Ok(())
  1129. } else {
  1130. Err(MaskError::InvalidBit)
  1131. }
  1132. }
  1133. /// Returns [HartIds] of self.
  1134. #[inline]
  1135. pub const fn iter(&self) -> HartIds {
  1136. HartIds {
  1137. inner: match self.hart_mask_base {
  1138. Self::IGNORE_MASK => UnvisitedMask::Range(0, usize::MAX),
  1139. _ => UnvisitedMask::MaskBase(self.hart_mask, self.hart_mask_base),
  1140. },
  1141. }
  1142. }
  1143. }
  1144. impl IntoIterator for HartMask {
  1145. type Item = usize;
  1146. type IntoIter = HartIds;
  1147. #[inline]
  1148. fn into_iter(self) -> Self::IntoIter {
  1149. self.iter()
  1150. }
  1151. }
  1152. /// Iterator structure for `HartMask`.
  1153. ///
  1154. /// It will iterate hart id from low to high.
  1155. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
  1156. pub struct HartIds {
  1157. inner: UnvisitedMask,
  1158. }
  1159. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
  1160. enum UnvisitedMask {
  1161. MaskBase(usize, usize),
  1162. Range(usize, usize),
  1163. }
  1164. impl Iterator for HartIds {
  1165. type Item = usize;
  1166. #[inline]
  1167. fn next(&mut self) -> Option<Self::Item> {
  1168. match &mut self.inner {
  1169. UnvisitedMask::MaskBase(0, _base) => None,
  1170. UnvisitedMask::MaskBase(unvisited_mask, base) => {
  1171. let low_bit = unvisited_mask.trailing_zeros();
  1172. let hart_id = usize::try_from(low_bit).unwrap() + *base;
  1173. *unvisited_mask &= !(1usize << low_bit);
  1174. Some(hart_id)
  1175. }
  1176. UnvisitedMask::Range(start, end) => {
  1177. assert!(start <= end);
  1178. if *start < *end {
  1179. let ans = *start;
  1180. *start += 1;
  1181. Some(ans)
  1182. } else {
  1183. None
  1184. }
  1185. }
  1186. }
  1187. }
  1188. #[inline]
  1189. fn size_hint(&self) -> (usize, Option<usize>) {
  1190. match self.inner {
  1191. UnvisitedMask::MaskBase(unvisited_mask, _base) => {
  1192. let exact_popcnt = usize::try_from(unvisited_mask.count_ones()).unwrap();
  1193. (exact_popcnt, Some(exact_popcnt))
  1194. }
  1195. UnvisitedMask::Range(start, end) => {
  1196. assert!(start <= end);
  1197. let exact_num_harts = end - start;
  1198. (exact_num_harts, Some(exact_num_harts))
  1199. }
  1200. }
  1201. }
  1202. #[inline]
  1203. fn count(self) -> usize {
  1204. self.size_hint().0
  1205. }
  1206. #[inline]
  1207. fn last(mut self) -> Option<Self::Item> {
  1208. self.next_back()
  1209. }
  1210. #[inline]
  1211. fn min(mut self) -> Option<Self::Item> {
  1212. self.next()
  1213. }
  1214. #[inline]
  1215. fn max(mut self) -> Option<Self::Item> {
  1216. self.next_back()
  1217. }
  1218. #[inline]
  1219. fn is_sorted(self) -> bool {
  1220. true
  1221. }
  1222. // TODO: implement fn advance_by once it's stablized: https://github.com/rust-lang/rust/issues/77404
  1223. // #[inline]
  1224. // fn advance_by(&mut self, n: usize) -> Result<(), core::num::NonZero<usize>> { ... }
  1225. }
  1226. impl DoubleEndedIterator for HartIds {
  1227. #[inline]
  1228. fn next_back(&mut self) -> Option<Self::Item> {
  1229. match &mut self.inner {
  1230. UnvisitedMask::MaskBase(0, _base) => None,
  1231. UnvisitedMask::MaskBase(unvisited_mask, base) => {
  1232. let high_bit = unvisited_mask.leading_zeros();
  1233. let hart_id = usize::try_from(usize::BITS - high_bit - 1).unwrap() + *base;
  1234. *unvisited_mask &= !(1usize << (usize::BITS - high_bit - 1));
  1235. Some(hart_id)
  1236. }
  1237. UnvisitedMask::Range(start, end) => {
  1238. assert!(start <= end);
  1239. if *start < *end {
  1240. let ans = *end;
  1241. *end -= 1;
  1242. Some(ans)
  1243. } else {
  1244. None
  1245. }
  1246. }
  1247. }
  1248. }
  1249. // TODO: implement advance_back_by once stablized.
  1250. // #[inline]
  1251. // fn advance_back_by(&mut self, n: usize) -> Result<(), core::num::NonZero<usize>> { ... }
  1252. }
  1253. impl ExactSizeIterator for HartIds {}
  1254. impl core::iter::FusedIterator for HartIds {}
  1255. /// Error of mask modification.
  1256. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
  1257. pub enum MaskError {
  1258. /// This mask has been ignored.
  1259. Ignored,
  1260. /// Request bit is invalid.
  1261. InvalidBit,
  1262. }
  1263. /// Counter index mask structure in SBI function calls for the `PMU` extension §11.
  1264. #[repr(C)]
  1265. #[derive(Debug, Copy, Clone, Eq, PartialEq)]
  1266. pub struct CounterMask<T = usize> {
  1267. counter_idx_mask: T,
  1268. counter_idx_base: T,
  1269. }
  1270. impl<T: SbiRegister> CounterMask<T> {
  1271. /// Special value to ignore the `mask`, and consider all `bit`s as set.
  1272. pub const IGNORE_MASK: T = T::FULL_MASK;
  1273. /// Construct a [CounterMask] from mask value and base counter index.
  1274. #[inline]
  1275. pub const fn from_mask_base(counter_idx_mask: T, counter_idx_base: T) -> Self {
  1276. Self {
  1277. counter_idx_mask,
  1278. counter_idx_base,
  1279. }
  1280. }
  1281. /// Gets the special value for ignoring the `mask` parameter.
  1282. #[inline]
  1283. pub const fn ignore_mask(&self) -> T {
  1284. Self::IGNORE_MASK
  1285. }
  1286. /// Returns `mask` and `base` parameters from the [CounterMask].
  1287. #[inline]
  1288. pub const fn into_inner(self) -> (T, T) {
  1289. (self.counter_idx_mask, self.counter_idx_base)
  1290. }
  1291. }
  1292. // FIXME: implement for T: SbiRegister once we can implement this using const traits.
  1293. // Ref: https://rust-lang.github.io/rust-project-goals/2024h2/const-traits.html
  1294. impl CounterMask<usize> {
  1295. /// Returns whether the [CounterMask] contains the provided `counter`.
  1296. #[inline]
  1297. pub const fn has_bit(self, counter: usize) -> bool {
  1298. has_bit(
  1299. self.counter_idx_mask,
  1300. self.counter_idx_base,
  1301. Self::IGNORE_MASK,
  1302. counter,
  1303. )
  1304. }
  1305. }
  1306. /// Physical slice wrapper with type annotation.
  1307. ///
  1308. /// This struct wraps slices in RISC-V physical memory by low and high part of the
  1309. /// physical base address as well as its length. It is usually used by SBI extensions
  1310. /// as parameter types to pass base address and length parameters on physical memory
  1311. /// other than a virtual one.
  1312. ///
  1313. /// Generic parameter `P` represents a hint of how this physical slice would be used.
  1314. /// For example, `Physical<&[u8]>` represents an immutable reference to physical byte slice,
  1315. /// while `Physical<&mut [u8]>` represents a mutable one.
  1316. ///
  1317. /// An SBI implementation should load or store memory using both `phys_addr_lo` and
  1318. /// `phys_addr_hi` combined as base address. A supervisor program (kernels etc.)
  1319. /// should provide continuous physical memory, wrapping its reference using this structure
  1320. /// before passing into SBI runtime.
  1321. #[derive(Clone, Copy)]
  1322. pub struct Physical<P> {
  1323. num_bytes: usize,
  1324. phys_addr_lo: usize,
  1325. phys_addr_hi: usize,
  1326. _marker: PhantomData<P>,
  1327. }
  1328. impl<P> Physical<P> {
  1329. /// Create a physical memory slice by length and physical address.
  1330. #[inline]
  1331. pub const fn new(num_bytes: usize, phys_addr_lo: usize, phys_addr_hi: usize) -> Self {
  1332. Self {
  1333. num_bytes,
  1334. phys_addr_lo,
  1335. phys_addr_hi,
  1336. _marker: core::marker::PhantomData,
  1337. }
  1338. }
  1339. /// Returns length of the physical memory slice.
  1340. #[inline]
  1341. pub const fn num_bytes(&self) -> usize {
  1342. self.num_bytes
  1343. }
  1344. /// Returns low-part base address of physical memory slice.
  1345. #[inline]
  1346. pub const fn phys_addr_lo(&self) -> usize {
  1347. self.phys_addr_lo
  1348. }
  1349. /// Returns high-part base address of physical memory slice.
  1350. #[inline]
  1351. pub const fn phys_addr_hi(&self) -> usize {
  1352. self.phys_addr_hi
  1353. }
  1354. }
  1355. /// Shared memory physical address raw pointer with type annotation.
  1356. ///
  1357. /// This is a structure wrapping a raw pointer to the value of the type `T` without
  1358. /// a pointer metadata. `SharedPtr`'s are _thin_; they won't include metadata
  1359. /// as RISC-V SBI does not provide an approach to pass them via SBI calls,
  1360. /// thus the length of type `T` should be decided independently of raw
  1361. /// pointer structure.
  1362. ///
  1363. /// `SharedPtr` can be used as a parameter to pass the shared memory physical pointer
  1364. /// with a given base address in RISC-V SBI calls. For example, a `SharedPtr<[u8; 64]>`
  1365. /// would represent a fixed-size 64 byte array on a RISC-V SBI function argument
  1366. /// type.
  1367. ///
  1368. /// This structure cannot be dereferenced directly with physical addresses,
  1369. /// because on RISC-V systems the physical address space could be larger than the
  1370. /// virtual ones. Hence, this structure describes the physical memory range by
  1371. /// two `usize` values: the upper `phys_addr_hi` and lower `phys_addr_lo`.
  1372. ///
  1373. /// RISC-V SBI extensions may declare special pointer values for shared memory
  1374. /// raw pointers. For example, SBI STA declares that steal-time information
  1375. /// should stop from reporting when the SBI call is invoked using all-ones
  1376. /// bitwise shared pointer, i.e. `phys_addr_hi` and `phys_addr_lo` both equals
  1377. /// `usize::MAX`. `SharedPtr` can be constructed using such special values
  1378. /// by providing them to the `SharedPtr::new` function.
  1379. ///
  1380. /// # Requirements
  1381. ///
  1382. /// If an SBI function needs to pass a shared memory physical address range to
  1383. /// the SBI implementation (or higher privilege mode), then this physical memory
  1384. /// address range MUST satisfy the following requirements:
  1385. ///
  1386. /// * The SBI implementation MUST check that the supervisor-mode software is
  1387. /// allowed to access the specified physical memory range with the access
  1388. /// type requested (read and/or write).
  1389. /// * The SBI implementation MUST access the specified physical memory range
  1390. /// using the PMA attributes.
  1391. /// * The data in the shared memory MUST follow little-endian byte ordering.
  1392. ///
  1393. /// *NOTE:* If the supervisor-mode software accesses the same physical memory
  1394. /// range using a memory type different from the PMA, then a loss of coherence
  1395. /// or unexpected memory ordering may occur. The invoking software should
  1396. /// follow the rules and sequences defined in the RISC-V Svpbmt specification
  1397. /// to prevent the loss of coherence and memory ordering.
  1398. ///
  1399. /// It is recommended that a memory physical address passed to an SBI function
  1400. /// should use at least two `usize` parameters to support platforms
  1401. /// which have memory physical addresses wider than `XLEN` bits.
  1402. // FIXME: should constrain with `T: Thin` once ptr_metadata feature is stabled;
  1403. // RISC-V SBI does not provide an approach to pass pointer metadata by SBI calls.
  1404. pub struct SharedPtr<T> {
  1405. phys_addr_lo: usize,
  1406. phys_addr_hi: usize,
  1407. _marker: PhantomData<*mut T>,
  1408. }
  1409. // FIXME: we should consider strict provenance rules for this pointer-like structure
  1410. // once feature strict_provenance is stabled.
  1411. impl<T> SharedPtr<T> {
  1412. /// Create a shared physical memory pointer by physical address.
  1413. #[inline]
  1414. pub const fn new(phys_addr_lo: usize, phys_addr_hi: usize) -> Self {
  1415. Self {
  1416. phys_addr_lo,
  1417. phys_addr_hi,
  1418. _marker: PhantomData,
  1419. }
  1420. }
  1421. /// Returns low-part physical address of the shared physical memory pointer.
  1422. #[inline]
  1423. pub const fn phys_addr_lo(self) -> usize {
  1424. self.phys_addr_lo
  1425. }
  1426. /// Returns high-part physical address of the shared physical memory pointer.
  1427. #[inline]
  1428. pub const fn phys_addr_hi(self) -> usize {
  1429. self.phys_addr_hi
  1430. }
  1431. }
  1432. impl<T> Clone for SharedPtr<T> {
  1433. #[inline(always)]
  1434. fn clone(&self) -> Self {
  1435. *self
  1436. }
  1437. }
  1438. impl<T> Copy for SharedPtr<T> {}
  1439. #[cfg(test)]
  1440. mod tests {
  1441. use super::*;
  1442. #[test]
  1443. #[rustfmt::skip]
  1444. fn rustsbi_sbi_ret_constructors() {
  1445. assert_eq!(SbiRet::success(0), SbiRet { value: 0, error: 0 });
  1446. assert_eq!(SbiRet::success(1037), SbiRet { value: 1037, error: 0 });
  1447. assert_eq!(SbiRet::success(usize::MAX), SbiRet { value: usize::MAX, error: 0 });
  1448. assert_eq!(SbiRet::failed(), SbiRet { value: 0, error: usize::MAX - 1 + 1 });
  1449. assert_eq!(SbiRet::not_supported(), SbiRet { value: 0, error: usize::MAX - 2 + 1 });
  1450. assert_eq!(SbiRet::invalid_param(), SbiRet { value: 0, error: usize::MAX - 3 + 1 });
  1451. assert_eq!(SbiRet::denied(), SbiRet { value: 0, error: usize::MAX - 4 + 1 });
  1452. assert_eq!(SbiRet::invalid_address(), SbiRet { value: 0, error: usize::MAX - 5 + 1 });
  1453. assert_eq!(SbiRet::already_available(), SbiRet { value: 0, error: usize::MAX - 6 + 1 });
  1454. assert_eq!(SbiRet::already_started(), SbiRet { value: 0, error: usize::MAX - 7 + 1 });
  1455. assert_eq!(SbiRet::already_stopped(), SbiRet { value: 0, error: usize::MAX - 8 + 1 });
  1456. assert_eq!(SbiRet::no_shmem(), SbiRet { value: 0, error: usize::MAX - 9 + 1 });
  1457. assert_eq!(SbiRet::invalid_state(), SbiRet { value: 0, error: usize::MAX - 10 + 1 });
  1458. assert_eq!(SbiRet::bad_range(), SbiRet { value: 0, error: usize::MAX - 11 + 1 });
  1459. assert_eq!(SbiRet::timeout(), SbiRet { value: 0, error: usize::MAX - 12 + 1 });
  1460. assert_eq!(SbiRet::io(), SbiRet { value: 0, error: usize::MAX - 13 + 1 });
  1461. }
  1462. #[test]
  1463. fn rustsbi_hart_mask() {
  1464. let mask = HartMask::from_mask_base(0b1, 400);
  1465. assert!(!mask.has_bit(0));
  1466. assert!(mask.has_bit(400));
  1467. assert!(!mask.has_bit(401));
  1468. let mask = HartMask::from_mask_base(0b110, 500);
  1469. assert!(!mask.has_bit(0));
  1470. assert!(!mask.has_bit(500));
  1471. assert!(mask.has_bit(501));
  1472. assert!(mask.has_bit(502));
  1473. assert!(!mask.has_bit(500 + (usize::BITS as usize)));
  1474. let max_bit = 1 << (usize::BITS - 1);
  1475. let mask = HartMask::from_mask_base(max_bit, 600);
  1476. assert!(mask.has_bit(600 + (usize::BITS as usize) - 1));
  1477. assert!(!mask.has_bit(600 + (usize::BITS as usize)));
  1478. let mask = HartMask::from_mask_base(0b11, usize::MAX - 1);
  1479. assert!(!mask.has_bit(usize::MAX - 2));
  1480. assert!(mask.has_bit(usize::MAX - 1));
  1481. assert!(mask.has_bit(usize::MAX));
  1482. assert!(!mask.has_bit(0));
  1483. // hart_mask_base == usize::MAX is special, it means hart_mask should be ignored
  1484. // and this hart mask contains all harts available
  1485. let mask = HartMask::from_mask_base(0, usize::MAX);
  1486. for i in 0..5 {
  1487. assert!(mask.has_bit(i));
  1488. }
  1489. assert!(mask.has_bit(usize::MAX));
  1490. let mut mask = HartMask::from_mask_base(0, 1);
  1491. assert!(!mask.has_bit(1));
  1492. assert!(mask.insert(1).is_ok());
  1493. assert!(mask.has_bit(1));
  1494. assert!(mask.remove(1).is_ok());
  1495. assert!(!mask.has_bit(1));
  1496. }
  1497. #[test]
  1498. fn rustsbi_hart_ids_iterator() {
  1499. let mask = HartMask::from_mask_base(0b101011, 1);
  1500. // Test the `next` method of `HartIds` structure.
  1501. let mut hart_ids = mask.iter();
  1502. assert_eq!(hart_ids.next(), Some(1));
  1503. assert_eq!(hart_ids.next(), Some(2));
  1504. assert_eq!(hart_ids.next(), Some(4));
  1505. assert_eq!(hart_ids.next(), Some(6));
  1506. assert_eq!(hart_ids.next(), None);
  1507. // `HartIds` structures are fused, meaning they return `None` forever once iteration finished.
  1508. assert_eq!(hart_ids.next(), None);
  1509. // Test `for` loop on mask (`HartMask`) as `IntoIterator`.
  1510. let mut ans = [0; 4];
  1511. let mut idx = 0;
  1512. for hart_id in mask {
  1513. ans[idx] = hart_id;
  1514. idx += 1;
  1515. }
  1516. assert_eq!(ans, [1, 2, 4, 6]);
  1517. // Test `Iterator` methods on `HartIds`.
  1518. let mut hart_ids = mask.iter();
  1519. assert_eq!(hart_ids.size_hint(), (4, Some(4)));
  1520. let _ = hart_ids.next();
  1521. assert_eq!(hart_ids.size_hint(), (3, Some(3)));
  1522. let _ = hart_ids.next();
  1523. let _ = hart_ids.next();
  1524. assert_eq!(hart_ids.size_hint(), (1, Some(1)));
  1525. let _ = hart_ids.next();
  1526. assert_eq!(hart_ids.size_hint(), (0, Some(0)));
  1527. let _ = hart_ids.next();
  1528. assert_eq!(hart_ids.size_hint(), (0, Some(0)));
  1529. let mut hart_ids = mask.iter();
  1530. assert_eq!(hart_ids.count(), 4);
  1531. let _ = hart_ids.next();
  1532. assert_eq!(hart_ids.count(), 3);
  1533. let _ = hart_ids.next();
  1534. let _ = hart_ids.next();
  1535. let _ = hart_ids.next();
  1536. assert_eq!(hart_ids.count(), 0);
  1537. let _ = hart_ids.next();
  1538. assert_eq!(hart_ids.count(), 0);
  1539. let hart_ids = mask.iter();
  1540. assert_eq!(hart_ids.last(), Some(6));
  1541. let mut hart_ids = mask.iter();
  1542. assert_eq!(hart_ids.nth(2), Some(4));
  1543. let mut hart_ids = mask.iter();
  1544. assert_eq!(hart_ids.nth(0), Some(1));
  1545. let mut iter = mask.iter().step_by(2);
  1546. assert_eq!(iter.next(), Some(1));
  1547. assert_eq!(iter.next(), Some(4));
  1548. assert_eq!(iter.next(), None);
  1549. let mask_2 = HartMask::from_mask_base(0b1001101, 64);
  1550. let mut iter = mask.iter().chain(mask_2);
  1551. assert_eq!(iter.next(), Some(1));
  1552. assert_eq!(iter.next(), Some(2));
  1553. assert_eq!(iter.next(), Some(4));
  1554. assert_eq!(iter.next(), Some(6));
  1555. assert_eq!(iter.next(), Some(64));
  1556. assert_eq!(iter.next(), Some(66));
  1557. assert_eq!(iter.next(), Some(67));
  1558. assert_eq!(iter.next(), Some(70));
  1559. assert_eq!(iter.next(), None);
  1560. let mut iter = mask.iter().zip(mask_2);
  1561. assert_eq!(iter.next(), Some((1, 64)));
  1562. assert_eq!(iter.next(), Some((2, 66)));
  1563. assert_eq!(iter.next(), Some((4, 67)));
  1564. assert_eq!(iter.next(), Some((6, 70)));
  1565. assert_eq!(iter.next(), None);
  1566. fn to_plic_context_id(hart_id_machine: usize) -> usize {
  1567. hart_id_machine * 2
  1568. }
  1569. let mut iter = mask.iter().map(to_plic_context_id);
  1570. assert_eq!(iter.next(), Some(2));
  1571. assert_eq!(iter.next(), Some(4));
  1572. assert_eq!(iter.next(), Some(8));
  1573. assert_eq!(iter.next(), Some(12));
  1574. assert_eq!(iter.next(), None);
  1575. let mut channel_received = [0; 4];
  1576. let mut idx = 0;
  1577. let mut channel_send = |hart_id| {
  1578. channel_received[idx] = hart_id;
  1579. idx += 1;
  1580. };
  1581. mask.iter().for_each(|value| channel_send(value));
  1582. assert_eq!(channel_received, [1, 2, 4, 6]);
  1583. let is_in_cluster_1 = |hart_id: &usize| *hart_id >= 4 && *hart_id < 7;
  1584. let mut iter = mask.iter().filter(is_in_cluster_1);
  1585. assert_eq!(iter.next(), Some(4));
  1586. assert_eq!(iter.next(), Some(6));
  1587. assert_eq!(iter.next(), None);
  1588. let if_in_cluster_1_get_plic_context_id = |hart_id: usize| {
  1589. if hart_id >= 4 && hart_id < 7 {
  1590. Some(hart_id * 2)
  1591. } else {
  1592. None
  1593. }
  1594. };
  1595. let mut iter = mask.iter().filter_map(if_in_cluster_1_get_plic_context_id);
  1596. assert_eq!(iter.next(), Some(8));
  1597. assert_eq!(iter.next(), Some(12));
  1598. assert_eq!(iter.next(), None);
  1599. let mut iter = mask.iter().enumerate();
  1600. assert_eq!(iter.next(), Some((0, 1)));
  1601. assert_eq!(iter.next(), Some((1, 2)));
  1602. assert_eq!(iter.next(), Some((2, 4)));
  1603. assert_eq!(iter.next(), Some((3, 6)));
  1604. assert_eq!(iter.next(), None);
  1605. let mut ans = [(0, 0); 4];
  1606. let mut idx = 0;
  1607. for (i, hart_id) in mask.iter().enumerate() {
  1608. ans[idx] = (i, hart_id);
  1609. idx += 1;
  1610. }
  1611. assert_eq!(ans, [(0, 1), (1, 2), (2, 4), (3, 6)]);
  1612. let mut iter = mask.iter().peekable();
  1613. assert_eq!(iter.peek(), Some(&1));
  1614. assert_eq!(iter.next(), Some(1));
  1615. assert_eq!(iter.peek(), Some(&2));
  1616. assert_eq!(iter.next(), Some(2));
  1617. assert_eq!(iter.peek(), Some(&4));
  1618. assert_eq!(iter.next(), Some(4));
  1619. assert_eq!(iter.peek(), Some(&6));
  1620. assert_eq!(iter.next(), Some(6));
  1621. assert_eq!(iter.peek(), None);
  1622. assert_eq!(iter.next(), None);
  1623. // TODO: other iterator tests.
  1624. assert!(mask.iter().is_sorted());
  1625. assert!(mask.iter().is_sorted_by(|a, b| a <= b));
  1626. // Reverse iterator as `DoubleEndedIterator`.
  1627. let mut iter = mask.iter().rev();
  1628. assert_eq!(iter.next(), Some(6));
  1629. assert_eq!(iter.next(), Some(4));
  1630. assert_eq!(iter.next(), Some(2));
  1631. assert_eq!(iter.next(), Some(1));
  1632. assert_eq!(iter.next(), None);
  1633. // Special iterator values.
  1634. let nothing = HartMask::from_mask_base(0, 1000);
  1635. assert!(nothing.iter().eq([]));
  1636. let all_mask_bits_set = HartMask::from_mask_base(usize::MAX, 1000);
  1637. let range = 1000..(1000 + usize::BITS as usize);
  1638. assert!(all_mask_bits_set.iter().eq(range));
  1639. let all_harts = HartMask::all();
  1640. let mut iter = all_harts.iter();
  1641. assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX)));
  1642. // Don't use `Iterator::eq` here; it would literally run `Iterator::try_for_each` from 0 to usize::MAX
  1643. // which will cost us forever to run the test.
  1644. assert_eq!(iter.next(), Some(0));
  1645. assert_eq!(iter.size_hint(), (usize::MAX - 1, Some(usize::MAX - 1)));
  1646. assert_eq!(iter.next(), Some(1));
  1647. assert_eq!(iter.next(), Some(2));
  1648. // skip 500 elements
  1649. let _ = iter.nth(500 - 1);
  1650. assert_eq!(iter.next(), Some(503));
  1651. assert_eq!(iter.size_hint(), (usize::MAX - 504, Some(usize::MAX - 504)));
  1652. assert_eq!(iter.next_back(), Some(usize::MAX));
  1653. assert_eq!(iter.next_back(), Some(usize::MAX - 1));
  1654. assert_eq!(iter.size_hint(), (usize::MAX - 506, Some(usize::MAX - 506)));
  1655. // A common usage of `HartMask::all`, we assume that this platform filters out hart 0..=3.
  1656. let environment_available_hart_ids = 4..128;
  1657. // `hart_mask_iter` contains 64..=usize::MAX.
  1658. let hart_mask_iter = all_harts.iter().skip(64);
  1659. let filtered_iter = environment_available_hart_ids.filter(|&x| {
  1660. hart_mask_iter
  1661. .clone()
  1662. .find(|&y| y >= x)
  1663. .map_or(false, |y| y == x)
  1664. });
  1665. assert!(filtered_iter.eq(64..128));
  1666. // The following operations should have O(1) complexity.
  1667. let all_harts = HartMask::all();
  1668. assert_eq!(all_harts.iter().count(), usize::MAX);
  1669. assert_eq!(all_harts.iter().last(), Some(usize::MAX));
  1670. assert_eq!(all_harts.iter().min(), Some(0));
  1671. assert_eq!(all_harts.iter().max(), Some(usize::MAX));
  1672. assert!(all_harts.iter().is_sorted());
  1673. let partial_all_harts = {
  1674. let mut ans = HartMask::all().iter();
  1675. let _ = ans.nth(65536 - 1);
  1676. let _ = ans.nth_back(4096 - 1);
  1677. ans
  1678. };
  1679. assert_eq!(partial_all_harts.clone().count(), usize::MAX - 65536 - 4096);
  1680. assert_eq!(partial_all_harts.clone().last(), Some(usize::MAX - 4096));
  1681. assert_eq!(partial_all_harts.clone().min(), Some(65536));
  1682. assert_eq!(partial_all_harts.clone().max(), Some(usize::MAX - 4096));
  1683. assert!(partial_all_harts.is_sorted());
  1684. let nothing = HartMask::from_mask_base(0, 1000);
  1685. assert_eq!(nothing.iter().count(), 0);
  1686. assert_eq!(nothing.iter().last(), None);
  1687. assert_eq!(nothing.iter().min(), None);
  1688. assert_eq!(nothing.iter().max(), None);
  1689. assert!(nothing.iter().is_sorted());
  1690. let mask = HartMask::from_mask_base(0b101011, 1);
  1691. assert_eq!(mask.iter().count(), 4);
  1692. assert_eq!(mask.iter().last(), Some(6));
  1693. assert_eq!(mask.iter().min(), Some(1));
  1694. assert_eq!(mask.iter().max(), Some(6));
  1695. assert!(mask.iter().is_sorted());
  1696. let all_mask_bits_set = HartMask::from_mask_base(usize::MAX, 1000);
  1697. let last = 1000 + usize::BITS as usize - 1;
  1698. assert_eq!(all_mask_bits_set.iter().count(), usize::BITS as usize);
  1699. assert_eq!(all_mask_bits_set.iter().last(), Some(last));
  1700. assert_eq!(all_mask_bits_set.iter().min(), Some(1000));
  1701. assert_eq!(all_mask_bits_set.iter().max(), Some(last));
  1702. assert!(all_mask_bits_set.iter().is_sorted());
  1703. }
  1704. #[test]
  1705. fn rustsbi_counter_index_mask() {
  1706. let mask = CounterMask::from_mask_base(0b1, 400);
  1707. assert!(!mask.has_bit(0));
  1708. assert!(mask.has_bit(400));
  1709. assert!(!mask.has_bit(401));
  1710. let mask = CounterMask::from_mask_base(0b110, 500);
  1711. assert!(!mask.has_bit(0));
  1712. assert!(!mask.has_bit(500));
  1713. assert!(mask.has_bit(501));
  1714. assert!(mask.has_bit(502));
  1715. assert!(!mask.has_bit(500 + (usize::BITS as usize)));
  1716. let max_bit = 1 << (usize::BITS - 1);
  1717. let mask = CounterMask::from_mask_base(max_bit, 600);
  1718. assert!(mask.has_bit(600 + (usize::BITS as usize) - 1));
  1719. assert!(!mask.has_bit(600 + (usize::BITS as usize)));
  1720. let mask = CounterMask::from_mask_base(0b11, usize::MAX - 1);
  1721. assert!(!mask.has_bit(usize::MAX - 2));
  1722. assert!(mask.has_bit(usize::MAX - 1));
  1723. assert!(mask.has_bit(usize::MAX));
  1724. assert!(!mask.has_bit(0));
  1725. let mask = CounterMask::from_mask_base(0, usize::MAX);
  1726. let null_mask = CounterMask::from_mask_base(0, 0);
  1727. (0..=usize::BITS as usize).for_each(|i| {
  1728. assert!(mask.has_bit(i));
  1729. assert!(!null_mask.has_bit(i));
  1730. });
  1731. assert!(mask.has_bit(usize::MAX));
  1732. }
  1733. #[test]
  1734. fn rustsbi_mask_non_usize() {
  1735. assert_eq!(CounterMask::<i32>::IGNORE_MASK, -1);
  1736. assert_eq!(CounterMask::<i64>::IGNORE_MASK, -1);
  1737. assert_eq!(CounterMask::<i128>::IGNORE_MASK, -1);
  1738. assert_eq!(CounterMask::<u32>::IGNORE_MASK, u32::MAX);
  1739. assert_eq!(CounterMask::<u64>::IGNORE_MASK, u64::MAX);
  1740. assert_eq!(CounterMask::<u128>::IGNORE_MASK, u128::MAX);
  1741. assert_eq!(HartMask::<i32>::IGNORE_MASK, -1);
  1742. assert_eq!(HartMask::<i64>::IGNORE_MASK, -1);
  1743. assert_eq!(HartMask::<i128>::IGNORE_MASK, -1);
  1744. assert_eq!(HartMask::<u32>::IGNORE_MASK, u32::MAX);
  1745. assert_eq!(HartMask::<u64>::IGNORE_MASK, u64::MAX);
  1746. assert_eq!(HartMask::<u128>::IGNORE_MASK, u128::MAX);
  1747. assert_eq!(HartMask::<i32>::all(), HartMask::from_mask_base(0, -1));
  1748. }
  1749. }