reset.rs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
  2. use rustsbi::SbiRet;
  3. use crate::board::SBI_IMPL;
  4. pub trait ResetDevice {
  5. fn fail(&self, code: u16) -> !;
  6. fn pass(&self) -> !;
  7. fn reset(&self) -> !;
  8. }
  9. pub struct SbiReset<'a, T: ResetDevice> {
  10. pub reset_dev: &'a AtomicPtr<T>,
  11. }
  12. impl<'a, T: ResetDevice> SbiReset<'a, T> {
  13. pub fn new(reset_dev: &'a AtomicPtr<T>) -> Self {
  14. Self { reset_dev }
  15. }
  16. pub fn fail(&self) -> ! {
  17. let reset_dev = self.reset_dev.load(Relaxed);
  18. if reset_dev.is_null() {
  19. trace!("test fail, begin dead loop");
  20. loop {
  21. core::hint::spin_loop()
  22. }
  23. } else {
  24. trace!("Test fail, invoke process exit procedure on Reset device");
  25. unsafe { (*reset_dev).fail(0) }
  26. }
  27. }
  28. }
  29. impl<'a, T: ResetDevice> rustsbi::Reset for SbiReset<'a, T> {
  30. #[inline]
  31. fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet {
  32. use rustsbi::spec::srst::{
  33. RESET_REASON_NO_REASON, RESET_REASON_SYSTEM_FAILURE, RESET_TYPE_COLD_REBOOT,
  34. RESET_TYPE_SHUTDOWN, RESET_TYPE_WARM_REBOOT,
  35. };
  36. match reset_type {
  37. RESET_TYPE_SHUTDOWN => match reset_reason {
  38. RESET_REASON_NO_REASON => unsafe {
  39. (*self.reset_dev.load(Relaxed)).pass();
  40. },
  41. RESET_REASON_SYSTEM_FAILURE => unsafe {
  42. (*self.reset_dev.load(Relaxed)).fail(u16::MAX);
  43. },
  44. value => unsafe {
  45. (*self.reset_dev.load(Relaxed)).fail(value as _);
  46. },
  47. },
  48. RESET_TYPE_COLD_REBOOT | RESET_TYPE_WARM_REBOOT => unsafe {
  49. (*self.reset_dev.load(Relaxed)).reset();
  50. },
  51. _ => SbiRet::invalid_param(),
  52. }
  53. }
  54. }
  55. pub fn fail() -> ! {
  56. unsafe { SBI_IMPL.assume_init_ref() }.reset.as_ref().unwrap().fail()
  57. }