forked from rustsbi/rustsbi
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathreset.rs
101 lines (92 loc) · 3.89 KB
/
reset.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use sbi_spec::binary::SbiRet;
/// System Reset Extension
///
/// Provides a function that allow the supervisor software to request system-level reboot or shutdown.
///
/// The term "system" refers to the world-view of supervisor software and the underlying SBI implementation
/// could be machine mode firmware or hypervisor.
///
/// Ref: [Section 9, RISC-V Supervisor Binary Interface Specification](https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc#9-system-reset-extension-eid-0x53525354-srst)
pub trait Reset: Send + Sync {
/// Reset the system based on provided `reset_type` and `reset_reason`.
///
/// This is a synchronous call and does not return if it succeeds.
///
/// # Warm reboot and cold reboot
///
/// When supervisor software is running natively, the SBI implementation is machine mode firmware.
/// In this case, shutdown is equivalent to physical power down of the entire system and
/// cold reboot is equivalent to physical power cycle of the entire system. Further, warm reboot
/// is equivalent to a power cycle of main processor and parts of the system but not the entire system.
///
/// For example, on a server class system with a BMC (board management controller),
/// a warm reboot will not power cycle the BMC whereas a cold reboot will definitely power cycle the BMC.
///
/// When supervisor software is running inside a virtual machine, the SBI implementation is a hypervisor.
/// The shutdown, cold reboot and warm reboot will behave functionally the same as the native case but might
/// not result in any physical power changes.
///
/// # Return value
///
/// The possible return error codes returned in `SbiRet.error` are shown in the table below:
///
/// | Error code | Description
/// |:--------------------------|:---------------
/// | `SbiRet::invalid_param()` | `reset_type` or `reset_reason` is not valid.
/// | `SbiRet::not_supported()` | `reset_type` is valid but not implemented.
/// | `SbiRet::failed()` | Reset request failed for unknown reasons.
fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet;
/// Legacy extension's reset function
///
/// Puts all the harts to shut down state from supervisor point of view. This SBI call doesn’t return.
#[cfg(feature = "legacy")]
fn legacy_reset(&self) -> ! {
use sbi_spec::srst::{RESET_REASON_NO_REASON, RESET_TYPE_SHUTDOWN};
// By default, this function redirects to `system_reset`.
self.system_reset(RESET_TYPE_SHUTDOWN, RESET_REASON_NO_REASON);
unreachable!()
}
}
impl<T: Reset> Reset for &T {
#[inline]
fn system_reset(&self, reset_type: u32, reset_reason: u32) -> SbiRet {
T::system_reset(self, reset_type, reset_reason)
}
#[cfg(feature = "legacy")]
#[inline]
fn legacy_reset(&self) -> ! {
T::legacy_reset(self)
}
}
#[cfg(feature = "singleton")]
use crate::util::AmoOnceRef;
#[cfg(feature = "singleton")]
static RESET: AmoOnceRef<dyn Reset> = AmoOnceRef::new();
#[cfg(feature = "singleton")]
/// Init SRST module
pub fn init_reset(reset: &'static dyn Reset) {
if !RESET.try_call_once(reset) {
panic!("load sbi module when already loaded")
}
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn probe_reset() -> bool {
RESET.get().is_some()
}
#[cfg(feature = "singleton")]
#[inline]
pub(crate) fn system_reset(reset_type: u32, reset_reason: u32) -> SbiRet {
if let Some(obj) = RESET.get() {
return obj.system_reset(reset_type, reset_reason);
}
SbiRet::not_supported()
}
#[cfg(all(feature = "singleton", feature = "legacy"))]
#[inline]
pub(crate) fn legacy_reset() -> ! {
if let Some(obj) = RESET.get() {
obj.legacy_reset()
}
unreachable!("no reset handler available; this is okay if your platform didn't declare a legacy reset handler")
}