susp.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. use sbi_spec::binary::SbiRet;
  2. /// System-Suspend extension.
  3. ///
  4. /// The system-suspend extension defines a set of system-level sleep states and a
  5. /// function which allows the supervisor-mode software to request that the system
  6. /// transitions to a sleep state. Sleep states are identified with 32-bit wide
  7. /// identifiers (`sleep_type`). The possible values for the identifiers are shown
  8. /// in the table below:
  9. ///
  10. /// | Type | Name | Description
  11. /// |-------------------------|----------------|-------------------------------
  12. /// | 0 | SUSPEND_TO_RAM | This is a "suspend to RAM" sleep type, similar to ACPI’s S2 or S3. Entry requires all but the calling hart be in the HSM `STOPPED` state and all hart registers and CSRs saved to RAM.
  13. /// | 0x00000001 - 0x7fffffff | | Reserved for future use
  14. /// | 0x80000000 - 0xffffffff | | Platform-specific system sleep types
  15. /// | > 0xffffffff | | Reserved
  16. ///
  17. /// The term "system" refers to the world-view of supervisor software. The
  18. /// underlying SBI implementation may be provided by machine mode firmware or a
  19. /// hypervisor.
  20. ///
  21. /// The system suspend extension does not provide any way for supported sleep types
  22. /// to be probed. Platforms are expected to specify their supported system sleep
  23. /// types and per-type wake-up devices in their hardware descriptions. The
  24. /// `SUSPEND_TO_RAM` sleep type is the one exception, and its presence is implied
  25. /// by that of the extension.
  26. pub trait Susp {
  27. /// Request the SBI implementation to put the system transitions to a sleep state.
  28. ///
  29. /// A return from a `system_suspend()` call implies an error and an error code
  30. /// will be in `sbiret.error`.
  31. /// A successful suspend and wake up operation results in the
  32. /// hart, which initiated to suspend, resuming from the `STOPPED` state.
  33. /// To resume, the hart will jump to supervisor-mode, at the address specified by `resume_addr`,
  34. /// with the specific register values described in the table below.
  35. ///
  36. /// | Register Name | Register Value
  37. /// | ------------------------------------------------- | ------------------
  38. /// | satp | 0
  39. /// | sstatus.SIE | 0
  40. /// | a0 | hartid
  41. /// | a1 | `opaque` parameter
  42. /// All other registers remain in an undefined state.
  43. ///
  44. /// # Parameters
  45. ///
  46. /// The `resume_addr` parameter points to a runtime-specified physical address,
  47. /// where the hart can resume execution in supervisor-mode after a system suspend.
  48. ///
  49. /// *NOTE:* A single `usize` parameter is sufficient as `resume_addr`,
  50. /// because the hart will resume execution in supervisor-mode with the MMU off,
  51. /// hence `resume_addr` must be less than XLEN bits wide.
  52. ///
  53. /// The `opaque` parameter is an XLEN-bit value that will be set in the `a1`
  54. /// register when the hart resumes execution at `resume_addr` after a
  55. /// system suspend.
  56. ///
  57. /// Besides ensuring all entry criteria for the selected sleep type are met, such
  58. /// as ensuring other harts are in the `STOPPED` state, the caller must ensure all
  59. /// power units and domains are in a state compatible with the selected sleep type.
  60. /// The preparation of the power units, power domains, and wake-up devices used for
  61. /// resumption from the system sleep state is platform-specific and beyond the
  62. /// scope of this specification.
  63. ///
  64. /// When supervisor software is running inside a virtual machine, the SBI
  65. /// implementation is provided by a hypervisor.
  66. /// The system suspend will behave
  67. /// functionally the same as the native case, but might not result in any physical
  68. /// power changes.
  69. ///
  70. /// # Return value
  71. ///
  72. /// The possible return error codes returned in `SbiRet.error` are shown in the table below:
  73. ///
  74. /// | Error code | Description
  75. /// | --------------------------- | -------------------
  76. /// | `SbiRet::success()` | System has been suspended and resumed successfully.
  77. /// | `SbiRet::invalid_param()` | `sleep_type` is reserved or is platform-specific and unimplemented.
  78. /// | `SbiRet::not_supported()` | `sleep_type` is not reserved and is implemented, but the platform does not support it due to one or more missing dependencies.
  79. /// | `SbiRet::invalid_address()` | `resume_addr` is not valid, possibly because it is not a valid physical address, or because executable access is prohibited (e.g. by physical memory protection or H-extension G-stage for supervisor mode).
  80. /// | `SbiRet::denied()` | The suspend request failed due to unsatisfied entry criteria.
  81. /// | `SbiRet::failed()` | The suspend request failed for unspecified or unknown other reasons.
  82. fn system_suspend(&self, sleep_type: u32, resume_addr: usize, opaque: usize) -> SbiRet;
  83. /// Function internal to macros. Do not use.
  84. #[doc(hidden)]
  85. #[inline]
  86. fn _rustsbi_probe(&self) -> usize {
  87. sbi_spec::base::UNAVAILABLE_EXTENSION.wrapping_add(1)
  88. }
  89. }
  90. impl<T: Susp> Susp for &T {
  91. #[inline]
  92. fn system_suspend(&self, sleep_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
  93. T::system_suspend(self, sleep_type, resume_addr, opaque)
  94. }
  95. }
  96. impl<T: Susp> Susp for Option<T> {
  97. #[inline]
  98. fn system_suspend(&self, sleep_type: u32, resume_addr: usize, opaque: usize) -> SbiRet {
  99. self.as_ref()
  100. .map(|inner| T::system_suspend(inner, sleep_type, resume_addr, opaque))
  101. .unwrap_or(SbiRet::not_supported())
  102. }
  103. #[inline]
  104. fn _rustsbi_probe(&self) -> usize {
  105. match self {
  106. Some(_) => sbi_spec::base::UNAVAILABLE_EXTENSION.wrapping_add(1),
  107. None => sbi_spec::base::UNAVAILABLE_EXTENSION,
  108. }
  109. }
  110. }