instance.rs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. use crate::{
  2. spec::binary::SbiRet, Console, Cppc, Fence, HartMask, Hsm, Ipi, Pmu, Reset, Susp, Timer,
  3. IMPL_ID_RUSTSBI, RUSTSBI_VERSION, SBI_SPEC_MAJOR, SBI_SPEC_MINOR,
  4. };
  5. use core::convert::Infallible;
  6. #[cfg(feature = "machine")]
  7. use riscv::register::{marchid, mimpid, mvendorid};
  8. use spec::binary::Physical;
  9. /// RustSBI instance including standard extensions
  10. ///
  11. /// By now RustSBI supports to run instance based interface on systems has environment pointer width
  12. /// that is the same as supervisor pointer width.
  13. #[derive(Clone, Debug)]
  14. pub struct RustSBI<T, I, R, H, S, P, C, SU, CP> {
  15. timer: Option<T>,
  16. ipi: Option<I>,
  17. rfnc: Option<R>,
  18. hsm: Option<H>,
  19. srst: Option<S>,
  20. pmu: Option<P>,
  21. dbcn: Option<C>,
  22. susp: Option<SU>,
  23. cppc: Option<CP>,
  24. #[cfg(not(feature = "machine"))]
  25. info: MachineInfo,
  26. }
  27. /// Machine information for SBI environment
  28. ///
  29. /// This structure is useful to build an SBI environment when RustSBI is not run directly on RISC-V machine mode.
  30. #[cfg(not(feature = "machine"))]
  31. #[derive(Clone, Copy, Debug)]
  32. pub struct MachineInfo {
  33. /// Register `mvendorid` for supervisor environment
  34. pub mvendorid: usize,
  35. /// Register `marchid` for supervisor environment
  36. pub marchid: usize,
  37. /// Register `mimpid` for supervisor environment
  38. pub mimpid: usize,
  39. }
  40. impl<T: Timer, I: Ipi, R: Fence, H: Hsm, S: Reset, P: Pmu, C: Console, SU: Susp, CP: Cppc>
  41. RustSBI<T, I, R, H, S, P, C, SU, CP>
  42. {
  43. /// Create RustSBI instance on current machine environment for all the SBI extensions
  44. #[cfg(feature = "machine")]
  45. #[inline]
  46. pub const fn new_machine(
  47. timer: T,
  48. ipi: I,
  49. rfnc: R,
  50. hsm: H,
  51. srst: S,
  52. pmu: P,
  53. dbcn: C,
  54. susp: SU,
  55. cppc: CP,
  56. ) -> Self {
  57. Self {
  58. timer: Some(timer),
  59. ipi: Some(ipi),
  60. rfnc: Some(rfnc),
  61. hsm: Some(hsm),
  62. srst: Some(srst),
  63. pmu: Some(pmu),
  64. dbcn: Some(dbcn),
  65. susp: Some(susp),
  66. cppc: Some(cppc),
  67. }
  68. }
  69. /// Create an uninitialized RustSBI instance on current machine environment.
  70. #[cfg(feature = "machine")]
  71. #[inline]
  72. pub const fn new_uninit_machine() -> Self {
  73. Self {
  74. timer: None,
  75. ipi: None,
  76. rfnc: None,
  77. hsm: None,
  78. srst: None,
  79. pmu: None,
  80. dbcn: None,
  81. susp: None,
  82. cppc: None,
  83. }
  84. }
  85. /// Create RustSBI instance on given machine information for all the SBI extensions
  86. #[cfg(not(feature = "machine"))]
  87. #[allow(clippy::too_many_arguments)] // fixme: is it possible to have a better design here?
  88. #[inline]
  89. pub const fn with_machine_info(
  90. timer: T,
  91. ipi: I,
  92. rfnc: R,
  93. hsm: H,
  94. srst: S,
  95. pmu: P,
  96. dbcn: C,
  97. susp: SU,
  98. cppc: CP,
  99. info: MachineInfo,
  100. ) -> Self {
  101. Self {
  102. timer: Some(timer),
  103. ipi: Some(ipi),
  104. rfnc: Some(rfnc),
  105. hsm: Some(hsm),
  106. srst: Some(srst),
  107. pmu: Some(pmu),
  108. dbcn: Some(dbcn),
  109. susp: Some(susp),
  110. cppc: Some(cppc),
  111. info,
  112. }
  113. }
  114. /// Create an uninitialized RustSBI instance on current machine environment.
  115. #[cfg(not(feature = "machine"))]
  116. #[inline]
  117. pub const fn uninit_with_machine_info(info: MachineInfo) -> Self {
  118. Self {
  119. timer: None,
  120. ipi: None,
  121. rfnc: None,
  122. hsm: None,
  123. srst: None,
  124. pmu: None,
  125. dbcn: None,
  126. susp: None,
  127. cppc: None,
  128. info,
  129. }
  130. }
  131. /// Handle supervisor environment call with given parameters and return the `SbiRet` result.
  132. #[inline]
  133. pub fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> SbiRet {
  134. match extension {
  135. spec::rfnc::EID_RFNC => {
  136. let Some(rfnc) = &self.rfnc else {
  137. return SbiRet::not_supported();
  138. };
  139. let [param0, param1, param2, param3, param4] =
  140. [param[0], param[1], param[2], param[3], param[4]];
  141. let hart_mask = crate::HartMask::from_mask_base(param0, param1);
  142. match function {
  143. spec::rfnc::REMOTE_FENCE_I => rfnc.remote_fence_i(hart_mask),
  144. spec::rfnc::REMOTE_SFENCE_VMA => {
  145. rfnc.remote_sfence_vma(hart_mask, param2, param3)
  146. }
  147. spec::rfnc::REMOTE_SFENCE_VMA_ASID => {
  148. rfnc.remote_sfence_vma_asid(hart_mask, param2, param3, param4)
  149. }
  150. spec::rfnc::REMOTE_HFENCE_GVMA_VMID => {
  151. rfnc.remote_hfence_gvma_vmid(hart_mask, param2, param3, param4)
  152. }
  153. spec::rfnc::REMOTE_HFENCE_GVMA => {
  154. rfnc.remote_hfence_gvma(hart_mask, param2, param3)
  155. }
  156. spec::rfnc::REMOTE_HFENCE_VVMA_ASID => {
  157. rfnc.remote_hfence_vvma_asid(hart_mask, param2, param3, param4)
  158. }
  159. spec::rfnc::REMOTE_HFENCE_VVMA => {
  160. rfnc.remote_hfence_vvma(hart_mask, param2, param3)
  161. }
  162. _ => SbiRet::not_supported(),
  163. }
  164. }
  165. spec::time::EID_TIME => match () {
  166. #[cfg(target_pointer_width = "64")]
  167. () => {
  168. let Some(timer) = &self.timer else {
  169. return SbiRet::not_supported();
  170. };
  171. let [param0] = [param[0]];
  172. match function {
  173. spec::time::SET_TIMER => {
  174. timer.set_timer(param0 as _);
  175. SbiRet::success(0)
  176. }
  177. _ => SbiRet::not_supported(),
  178. }
  179. }
  180. #[cfg(target_pointer_width = "32")]
  181. () => {
  182. let Some(timer) = &self.timer else {
  183. return SbiRet::not_supported();
  184. };
  185. let [param0, param1] = [param[0], param[1]];
  186. match function {
  187. spec::time::SET_TIMER => {
  188. timer.set_timer(concat_u32(param1, param0));
  189. SbiRet::success(0)
  190. }
  191. _ => SbiRet::not_supported(),
  192. }
  193. }
  194. },
  195. spec::spi::EID_SPI => {
  196. let Some(ipi) = &self.ipi else {
  197. return SbiRet::not_supported();
  198. };
  199. let [param0, param1] = [param[0], param[1]];
  200. match function {
  201. spec::spi::SEND_IPI => ipi.send_ipi(HartMask::from_mask_base(param0, param1)),
  202. _ => SbiRet::not_supported(),
  203. }
  204. }
  205. spec::base::EID_BASE => {
  206. let [param0] = [param[0]];
  207. let value = match function {
  208. spec::base::GET_SBI_SPEC_VERSION => (SBI_SPEC_MAJOR << 24) | (SBI_SPEC_MINOR),
  209. spec::base::GET_SBI_IMPL_ID => IMPL_ID_RUSTSBI,
  210. spec::base::GET_SBI_IMPL_VERSION => RUSTSBI_VERSION,
  211. spec::base::PROBE_EXTENSION => {
  212. // only provides probes to standard extensions. If you have customized extensions to be probed,
  213. // run it even before this `handle_ecall` function.
  214. self.probe_extension(param0)
  215. }
  216. spec::base::GET_MVENDORID => match () {
  217. #[cfg(feature = "machine")]
  218. () => mvendorid::read().map(|r| r.bits()).unwrap_or(0),
  219. #[cfg(not(feature = "machine"))]
  220. () => self.info.mvendorid,
  221. },
  222. spec::base::GET_MARCHID => match () {
  223. #[cfg(feature = "machine")]
  224. () => marchid::read().map(|r| r.bits()).unwrap_or(0),
  225. #[cfg(not(feature = "machine"))]
  226. () => self.info.marchid,
  227. },
  228. spec::base::GET_MIMPID => match () {
  229. #[cfg(feature = "machine")]
  230. () => mimpid::read().map(|r| r.bits()).unwrap_or(0),
  231. #[cfg(not(feature = "machine"))]
  232. () => self.info.mimpid,
  233. },
  234. _ => return SbiRet::not_supported(),
  235. };
  236. SbiRet::success(value)
  237. }
  238. spec::hsm::EID_HSM => {
  239. let Some(hsm) = &self.hsm else {
  240. return SbiRet::not_supported();
  241. };
  242. let [param0, param1, param2] = [param[0], param[1], param[2]];
  243. match function {
  244. spec::hsm::HART_START => hsm.hart_start(param0, param1, param2),
  245. spec::hsm::HART_STOP => hsm.hart_stop(),
  246. spec::hsm::HART_GET_STATUS => hsm.hart_get_status(param0),
  247. spec::hsm::HART_SUSPEND => {
  248. if let Ok(suspend_type) = u32::try_from(param0) {
  249. hsm.hart_suspend(suspend_type, param1, param2)
  250. } else {
  251. SbiRet::invalid_param()
  252. }
  253. }
  254. _ => SbiRet::not_supported(),
  255. }
  256. }
  257. spec::srst::EID_SRST => {
  258. let Some(srst) = &self.srst else {
  259. return SbiRet::not_supported();
  260. };
  261. let [param0, param1] = [param[0], param[1]];
  262. match function {
  263. spec::srst::SYSTEM_RESET => {
  264. match (u32::try_from(param0), u32::try_from(param1)) {
  265. (Ok(reset_type), Ok(reset_reason)) => {
  266. srst.system_reset(reset_type, reset_reason)
  267. }
  268. (_, _) => SbiRet::invalid_param(),
  269. }
  270. }
  271. _ => SbiRet::not_supported(),
  272. }
  273. }
  274. spec::pmu::EID_PMU => match () {
  275. #[cfg(target_pointer_width = "64")]
  276. () => {
  277. let Some(pmu) = &self.pmu else {
  278. return SbiRet::not_supported();
  279. };
  280. let [param0, param1, param2, param3, param4] =
  281. [param[0], param[1], param[2], param[3], param[4]];
  282. match function {
  283. spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
  284. spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
  285. spec::pmu::PMU_COUNTER_CONFIG_MATCHING => {
  286. pmu.counter_config_matching(param0, param1, param2, param3, param4 as _)
  287. }
  288. spec::pmu::PMU_COUNTER_START => {
  289. pmu.counter_start(param0, param1, param2, param3 as _)
  290. }
  291. spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
  292. spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
  293. spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
  294. _ => SbiRet::not_supported(),
  295. }
  296. }
  297. #[cfg(target_pointer_width = "32")]
  298. () => {
  299. let Some(pmu) = &self.pmu else {
  300. return SbiRet::not_supported();
  301. };
  302. let [param0, param1, param2, param3, param4, param5] =
  303. [param[0], param[1], param[2], param[3], param[4], param[5]];
  304. match function {
  305. spec::pmu::PMU_NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
  306. spec::pmu::PMU_COUNTER_GET_INFO => pmu.counter_get_info(param0),
  307. spec::pmu::PMU_COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
  308. param0,
  309. param1,
  310. param2,
  311. param3,
  312. concat_u32(param5, param4),
  313. ),
  314. spec::pmu::PMU_COUNTER_START => {
  315. pmu.counter_start(param0, param1, param2, concat_u32(param4, param3))
  316. }
  317. spec::pmu::PMU_COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
  318. spec::pmu::PMU_COUNTER_FW_READ => pmu.counter_fw_read(param0),
  319. spec::pmu::PMU_COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
  320. _ => SbiRet::not_supported(),
  321. }
  322. }
  323. },
  324. spec::dbcn::EID_DBCN => {
  325. let Some(dbcn) = &self.dbcn else {
  326. return SbiRet::not_supported();
  327. };
  328. let [param0, param1, param2] = [param[0], param[1], param[2]];
  329. match function {
  330. spec::dbcn::CONSOLE_WRITE => {
  331. let bytes = Physical::new(param0, param1, param2);
  332. dbcn.write(bytes)
  333. }
  334. spec::dbcn::CONSOLE_READ => {
  335. let bytes = Physical::new(param0, param1, param2);
  336. dbcn.read(bytes)
  337. }
  338. spec::dbcn::CONSOLE_WRITE_BYTE => dbcn.write_byte((param0 & 0xFF) as u8),
  339. _ => SbiRet::not_supported(),
  340. }
  341. }
  342. spec::susp::EID_SUSP => {
  343. let Some(susp) = &self.susp else {
  344. return SbiRet::not_supported();
  345. };
  346. let [param0, param1, param2] = [param[0], param[1], param[2]];
  347. match function {
  348. spec::susp::SUSPEND => match u32::try_from(param0) {
  349. Ok(sleep_type) => susp.system_suspend(sleep_type, param1, param2),
  350. _ => SbiRet::invalid_param(),
  351. },
  352. _ => SbiRet::not_supported(),
  353. }
  354. }
  355. spec::cppc::EID_CPPC => match () {
  356. #[cfg(target_pointer_width = "64")]
  357. () => {
  358. let Some(cppc) = &self.cppc else {
  359. return SbiRet::not_supported();
  360. };
  361. let [param0, param1] = [param[0], param[1]];
  362. match function {
  363. spec::cppc::PROBE => match u32::try_from(param0) {
  364. Ok(reg_id) => cppc.probe(reg_id),
  365. _ => SbiRet::invalid_param(),
  366. },
  367. spec::cppc::READ => match u32::try_from(param0) {
  368. Ok(reg_id) => cppc.read(reg_id),
  369. _ => SbiRet::invalid_param(),
  370. },
  371. spec::cppc::READ_HI => match u32::try_from(param0) {
  372. Ok(reg_id) => cppc.read_hi(reg_id),
  373. _ => SbiRet::invalid_param(),
  374. },
  375. spec::cppc::WRITE => match u32::try_from(param0) {
  376. Ok(reg_id) => cppc.write(reg_id, param1 as _),
  377. _ => SbiRet::invalid_param(),
  378. },
  379. _ => SbiRet::not_supported(),
  380. }
  381. }
  382. #[cfg(target_pointer_width = "32")]
  383. () => {
  384. let Some(cppc) = &self.cppc else {
  385. return SbiRet::not_supported();
  386. };
  387. let [param0, param1, param2] = [param[0], param[1], param[2]];
  388. match function {
  389. spec::cppc::PROBE => cppc.probe(param0 as _),
  390. spec::cppc::READ => cppc.read(param0 as _),
  391. spec::cppc::READ_HI => cppc.read_hi(param0 as _),
  392. spec::cppc::WRITE => cppc.write(param0 as _, concat_u32(param2, param1)),
  393. _ => SbiRet::not_supported(),
  394. }
  395. }
  396. },
  397. _ => SbiRet::not_supported(),
  398. }
  399. }
  400. #[inline]
  401. fn probe_extension(&self, extension: usize) -> usize {
  402. let ans = match extension {
  403. spec::base::EID_BASE => true,
  404. spec::time::EID_TIME => self.timer.is_some(),
  405. spec::spi::EID_SPI => self.ipi.is_some(),
  406. spec::rfnc::EID_RFNC => self.rfnc.is_some(),
  407. spec::srst::EID_SRST => self.srst.is_some(),
  408. spec::hsm::EID_HSM => self.hsm.is_some(),
  409. spec::pmu::EID_PMU => self.pmu.is_some(),
  410. spec::dbcn::EID_DBCN => self.dbcn.is_some(),
  411. spec::susp::EID_SUSP => self.susp.is_some(),
  412. spec::cppc::EID_CPPC => self.cppc.is_some(),
  413. _ => false,
  414. };
  415. if ans {
  416. spec::base::UNAVAILABLE_EXTENSION.wrapping_add(1)
  417. } else {
  418. spec::base::UNAVAILABLE_EXTENSION
  419. }
  420. }
  421. }
  422. #[cfg(target_pointer_width = "32")]
  423. #[inline]
  424. const fn concat_u32(h: usize, l: usize) -> u64 {
  425. ((h as u64) << 32) | (l as u64)
  426. }
  427. /// Structure to build a RustSBI instance
  428. pub struct Builder<T, I, R, H, S, P, C, SU, CP> {
  429. inner: RustSBI<T, I, R, H, S, P, C, SU, CP>,
  430. }
  431. impl
  432. Builder<
  433. Infallible,
  434. Infallible,
  435. Infallible,
  436. Infallible,
  437. Infallible,
  438. Infallible,
  439. Infallible,
  440. Infallible,
  441. Infallible,
  442. >
  443. {
  444. /// Create a new `Builder` from current machine environment
  445. #[inline]
  446. #[cfg(feature = "machine")]
  447. pub const fn new_machine() -> Builder<
  448. Infallible,
  449. Infallible,
  450. Infallible,
  451. Infallible,
  452. Infallible,
  453. Infallible,
  454. Infallible,
  455. Infallible,
  456. Infallible,
  457. > {
  458. Builder {
  459. inner: RustSBI {
  460. timer: None,
  461. ipi: None,
  462. rfnc: None,
  463. hsm: None,
  464. srst: None,
  465. pmu: None,
  466. dbcn: None,
  467. susp: None,
  468. cppc: None,
  469. },
  470. }
  471. }
  472. /// Create a new `Builder` from machine information
  473. #[inline]
  474. #[cfg(not(feature = "machine"))]
  475. pub const fn with_machine_info(
  476. info: MachineInfo,
  477. ) -> Builder<
  478. Infallible,
  479. Infallible,
  480. Infallible,
  481. Infallible,
  482. Infallible,
  483. Infallible,
  484. Infallible,
  485. Infallible,
  486. Infallible,
  487. > {
  488. Builder {
  489. inner: RustSBI {
  490. timer: None,
  491. ipi: None,
  492. rfnc: None,
  493. hsm: None,
  494. srst: None,
  495. pmu: None,
  496. dbcn: None,
  497. susp: None,
  498. cppc: None,
  499. info,
  500. },
  501. }
  502. }
  503. }
  504. // fixme: in future releases we may use type-changing struct update syntax like:
  505. // Builder { inner: RustSBI { timer: None, ..self.inner } }
  506. // https://github.com/rust-lang/rust/issues/86555
  507. // fixme: struct `Infallible` should be replaced to never type once it's stablized
  508. impl<T, I, R, H, S, P, C, SU, CP> Builder<T, I, R, H, S, P, C, SU, CP> {
  509. /// Add Timer programmer extension to RustSBI
  510. #[inline]
  511. pub fn with_timer<T2: Timer>(self, timer: T2) -> Builder<T2, I, R, H, S, P, C, SU, CP> {
  512. Builder {
  513. inner: RustSBI {
  514. timer: Some(timer),
  515. ipi: self.inner.ipi,
  516. rfnc: self.inner.rfnc,
  517. hsm: self.inner.hsm,
  518. srst: self.inner.srst,
  519. pmu: self.inner.pmu,
  520. dbcn: self.inner.dbcn,
  521. susp: self.inner.susp,
  522. cppc: self.inner.cppc,
  523. #[cfg(not(feature = "machine"))]
  524. info: self.inner.info,
  525. },
  526. }
  527. }
  528. /// Add Inter-processor Interrupt extension to RustSBI
  529. #[inline]
  530. pub fn with_ipi<I2: Ipi>(self, ipi: I2) -> Builder<T, I2, R, H, S, P, C, SU, CP> {
  531. Builder {
  532. inner: RustSBI {
  533. timer: self.inner.timer,
  534. ipi: Some(ipi),
  535. rfnc: self.inner.rfnc,
  536. hsm: self.inner.hsm,
  537. srst: self.inner.srst,
  538. pmu: self.inner.pmu,
  539. dbcn: self.inner.dbcn,
  540. susp: self.inner.susp,
  541. cppc: self.inner.cppc,
  542. #[cfg(not(feature = "machine"))]
  543. info: self.inner.info,
  544. },
  545. }
  546. }
  547. /// Add Remote Fence extension to RustSBI
  548. #[inline]
  549. pub fn with_fence<R2: Fence>(self, fence: R2) -> Builder<T, I, R2, H, S, P, C, SU, CP> {
  550. Builder {
  551. inner: RustSBI {
  552. timer: self.inner.timer,
  553. ipi: self.inner.ipi,
  554. rfnc: Some(fence),
  555. hsm: self.inner.hsm,
  556. srst: self.inner.srst,
  557. pmu: self.inner.pmu,
  558. dbcn: self.inner.dbcn,
  559. susp: self.inner.susp,
  560. cppc: self.inner.cppc,
  561. #[cfg(not(feature = "machine"))]
  562. info: self.inner.info,
  563. },
  564. }
  565. }
  566. /// Add Hart State Monitor extension to RustSBI
  567. #[inline]
  568. pub fn with_hsm<H2: Hsm>(self, hsm: H2) -> Builder<T, I, R, H2, S, P, C, SU, CP> {
  569. Builder {
  570. inner: RustSBI {
  571. timer: self.inner.timer,
  572. ipi: self.inner.ipi,
  573. rfnc: self.inner.rfnc,
  574. hsm: Some(hsm),
  575. srst: self.inner.srst,
  576. pmu: self.inner.pmu,
  577. dbcn: self.inner.dbcn,
  578. susp: self.inner.susp,
  579. cppc: self.inner.cppc,
  580. #[cfg(not(feature = "machine"))]
  581. info: self.inner.info,
  582. },
  583. }
  584. }
  585. /// Add System Reset extension to RustSBI
  586. #[inline]
  587. pub fn with_reset<S2: Reset>(self, reset: S2) -> Builder<T, I, R, H, S2, P, C, SU, CP> {
  588. Builder {
  589. inner: RustSBI {
  590. timer: self.inner.timer,
  591. ipi: self.inner.ipi,
  592. rfnc: self.inner.rfnc,
  593. hsm: self.inner.hsm,
  594. srst: Some(reset),
  595. pmu: self.inner.pmu,
  596. dbcn: self.inner.dbcn,
  597. susp: self.inner.susp,
  598. cppc: self.inner.cppc,
  599. #[cfg(not(feature = "machine"))]
  600. info: self.inner.info,
  601. },
  602. }
  603. }
  604. /// Add Performance Monitor Unit extension to RustSBI
  605. #[inline]
  606. pub fn with_pmu<P2: Pmu>(self, pmu: P2) -> Builder<T, I, R, H, S, P2, C, SU, CP> {
  607. Builder {
  608. inner: RustSBI {
  609. timer: self.inner.timer,
  610. ipi: self.inner.ipi,
  611. rfnc: self.inner.rfnc,
  612. hsm: self.inner.hsm,
  613. srst: self.inner.srst,
  614. pmu: Some(pmu),
  615. dbcn: self.inner.dbcn,
  616. susp: self.inner.susp,
  617. cppc: self.inner.cppc,
  618. #[cfg(not(feature = "machine"))]
  619. info: self.inner.info,
  620. },
  621. }
  622. }
  623. /// Add Debug Console extension to RustSBI
  624. #[inline]
  625. pub fn with_console<C2: Console>(self, console: C2) -> Builder<T, I, R, H, S, P, C2, SU, CP> {
  626. Builder {
  627. inner: RustSBI {
  628. timer: self.inner.timer,
  629. ipi: self.inner.ipi,
  630. rfnc: self.inner.rfnc,
  631. hsm: self.inner.hsm,
  632. srst: self.inner.srst,
  633. pmu: self.inner.pmu,
  634. dbcn: Some(console),
  635. susp: self.inner.susp,
  636. cppc: self.inner.cppc,
  637. #[cfg(not(feature = "machine"))]
  638. info: self.inner.info,
  639. },
  640. }
  641. }
  642. /// Add System Suspend extension to RustSBI
  643. #[inline]
  644. pub fn with_susp<SU2: Susp>(self, susp: SU2) -> Builder<T, I, R, H, S, P, C, SU2, CP> {
  645. Builder {
  646. inner: RustSBI {
  647. timer: self.inner.timer,
  648. ipi: self.inner.ipi,
  649. rfnc: self.inner.rfnc,
  650. hsm: self.inner.hsm,
  651. srst: self.inner.srst,
  652. pmu: self.inner.pmu,
  653. dbcn: self.inner.dbcn,
  654. susp: Some(susp),
  655. cppc: self.inner.cppc,
  656. #[cfg(not(feature = "machine"))]
  657. info: self.inner.info,
  658. },
  659. }
  660. }
  661. /// Add CPPC extension to RustSBI
  662. #[inline]
  663. pub fn with_cppc<CP2: Cppc>(self, cppc: CP2) -> Builder<T, I, R, H, S, P, C, SU, CP2> {
  664. Builder {
  665. inner: RustSBI {
  666. timer: self.inner.timer,
  667. ipi: self.inner.ipi,
  668. rfnc: self.inner.rfnc,
  669. hsm: self.inner.hsm,
  670. srst: self.inner.srst,
  671. pmu: self.inner.pmu,
  672. dbcn: self.inner.dbcn,
  673. susp: self.inner.susp,
  674. cppc: Some(cppc),
  675. #[cfg(not(feature = "machine"))]
  676. info: self.inner.info,
  677. },
  678. }
  679. }
  680. /// Build the target RustSBI instance
  681. #[inline]
  682. pub fn build(self) -> RustSBI<T, I, R, H, S, P, C, SU, CP> {
  683. self.inner
  684. }
  685. }
  686. // Placeholder for a structure that implements all RustSBI traits but is never accessed
  687. // fixme: Should be replaced to never type `!` once it's stablized
  688. // https://github.com/rust-lang/rust/issues/35121
  689. // fixme: should be replaced to impl SomeTrait for ! once never type is stablized
  690. impl Timer for Infallible {
  691. fn set_timer(&self, _: u64) {
  692. unreachable!()
  693. }
  694. }
  695. impl Ipi for Infallible {
  696. fn send_ipi(&self, _: HartMask) -> SbiRet {
  697. unreachable!()
  698. }
  699. }
  700. impl Fence for Infallible {
  701. fn remote_fence_i(&self, _: HartMask) -> SbiRet {
  702. unreachable!()
  703. }
  704. fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
  705. unreachable!()
  706. }
  707. fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
  708. unreachable!()
  709. }
  710. fn remote_hfence_gvma_vmid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
  711. unreachable!()
  712. }
  713. fn remote_hfence_gvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
  714. unreachable!()
  715. }
  716. fn remote_hfence_vvma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
  717. unreachable!()
  718. }
  719. fn remote_hfence_vvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
  720. unreachable!()
  721. }
  722. }
  723. impl Hsm for Infallible {
  724. fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet {
  725. unreachable!()
  726. }
  727. fn hart_stop(&self) -> SbiRet {
  728. unreachable!()
  729. }
  730. fn hart_get_status(&self, _: usize) -> SbiRet {
  731. unreachable!()
  732. }
  733. fn hart_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
  734. unreachable!()
  735. }
  736. }
  737. impl Reset for Infallible {
  738. fn system_reset(&self, _: u32, _: u32) -> SbiRet {
  739. unreachable!()
  740. }
  741. }
  742. impl Pmu for Infallible {
  743. fn num_counters(&self) -> usize {
  744. unreachable!()
  745. }
  746. fn counter_get_info(&self, _: usize) -> SbiRet {
  747. unreachable!()
  748. }
  749. fn counter_config_matching(&self, _: usize, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
  750. unreachable!()
  751. }
  752. fn counter_start(&self, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
  753. unreachable!()
  754. }
  755. fn counter_stop(&self, _: usize, _: usize, _: usize) -> SbiRet {
  756. unreachable!()
  757. }
  758. fn counter_fw_read(&self, _: usize) -> SbiRet {
  759. unreachable!()
  760. }
  761. fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
  762. unreachable!()
  763. }
  764. }
  765. impl Console for Infallible {
  766. fn write(&self, _: Physical<&[u8]>) -> SbiRet {
  767. unreachable!()
  768. }
  769. fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
  770. unreachable!()
  771. }
  772. fn write_byte(&self, _: u8) -> SbiRet {
  773. unreachable!()
  774. }
  775. }
  776. impl Susp for Infallible {
  777. fn system_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
  778. unreachable!()
  779. }
  780. }
  781. impl Cppc for Infallible {
  782. fn probe(&self, _: u32) -> SbiRet {
  783. unreachable!()
  784. }
  785. fn read(&self, _: u32) -> SbiRet {
  786. unreachable!()
  787. }
  788. fn read_hi(&self, _: u32) -> SbiRet {
  789. unreachable!()
  790. }
  791. fn write(&self, _: u32, _: u64) -> SbiRet {
  792. unreachable!()
  793. }
  794. }