1 // Copyright 2022 the authors. 2 // This project is dual-licensed under Apache 2.0 and MIT terms. 3 // See LICENSE-APACHE and LICENSE-MIT for details. 4 5 //! Constants for version 1.1 of the Arm Power State Coordination Interface (PSCI) version 1.1, and 6 //! functions to call them. 7 //! 8 //! Note that PSCI and other SMCCC calls may be made via either HVC or SMC. You can choose which one 9 //! to use by building this crate with the corresponding feature (i.e. `hvc` or `smc`). By default 10 //! `hvc` is enabled. If neither feature is enabled then the functions to make calls will not be 11 //! available, but the constants and types are still provided. 12 //! 13 //! This crate currently only supports aarch64 and the SMC64 versions of the various calls, in the 14 //! cases that both SMC32 and SMC64 versions exist. 15 16 mod calls; 17 pub mod error; 18 19 pub use calls::{ 20 affinity_info, cpu_default_suspend, cpu_freeze, cpu_off, cpu_on, cpu_suspend, mem_protect, 21 mem_protect_check_range, migrate, migrate_info_type, migrate_info_up_cpu, node_hw_state, 22 psci_features, set_suspend_mode, stat_count, stat_residency, system_off, system_reset, 23 system_reset2, system_suspend, version, 24 }; 25 pub use error::Error; 26 27 pub const PSCI_VERSION: u32 = 0x84000000; 28 pub const PSCI_CPU_SUSPEND_32: u32 = 0x84000001; 29 pub const PSCI_CPU_SUSPEND_64: u32 = 0xC4000001; 30 pub const PSCI_CPU_OFF: u32 = 0x84000002; 31 pub const PSCI_CPU_ON_32: u32 = 0x84000003; 32 pub const PSCI_CPU_ON_64: u32 = 0xC4000003; 33 pub const PSCI_AFFINITY_INFO_32: u32 = 0x84000004; 34 pub const PSCI_AFFINITY_INFO_64: u32 = 0xC4000004; 35 pub const PSCI_MIGRATE_32: u32 = 0x84000005; 36 pub const PSCI_MIGRATE_64: u32 = 0xC4000005; 37 pub const PSCI_MIGRATE_INFO_TYPE: u32 = 0x84000006; 38 pub const PSCI_MIGRATE_INFO_UP_CPU_32: u32 = 0x84000007; 39 pub const PSCI_MIGRATE_INFO_UP_CPU_64: u32 = 0xC4000007; 40 pub const PSCI_SYSTEM_OFF: u32 = 0x84000008; 41 pub const PSCI_SYSTEM_RESET: u32 = 0x84000009; 42 pub const PSCI_SYSTEM_RESET2_32: u32 = 0x84000012; 43 pub const PSCI_SYSTEM_RESET2_64: u32 = 0xC4000012; 44 pub const PSCI_MEM_PROTECT: u32 = 0x84000013; 45 pub const PSCI_MEM_PROTECT_CHECK_RANGE_32: u32 = 0x84000014; 46 pub const PSCI_MEM_PROTECT_CHECK_RANGE_64: u32 = 0xC4000014; 47 pub const PSCI_FEATURES: u32 = 0x8400000A; 48 pub const PSCI_CPU_FREEZE: u32 = 0x8400000B; 49 pub const PSCI_CPU_DEFAULT_SUSPEND_32: u32 = 0x8400000C; 50 pub const PSCI_CPU_DEFAULT_SUSPEND_64: u32 = 0xC400000C; 51 pub const PSCI_NODE_HW_STATE_32: u32 = 0x8400000D; 52 pub const PSCI_NODE_HW_STATE_64: u32 = 0xC400000D; 53 pub const PSCI_SYSTEM_SUSPEND_32: u32 = 0x8400000E; 54 pub const PSCI_SYSTEM_SUSPEND_64: u32 = 0xC400000E; 55 pub const PSCI_SET_SUSPEND_MODE: u32 = 0x8400000F; 56 pub const PSCI_STAT_RESIDENCY_32: u32 = 0x84000010; 57 pub const PSCI_STAT_RESIDENCY_64: u32 = 0xC4000010; 58 pub const PSCI_STAT_COUNT_32: u32 = 0x84000011; 59 pub const PSCI_STAT_COUNT_64: u32 = 0xC4000011; 60 61 /// Selects which affinity level fields are valid in the `target_affinity` parameter to 62 /// `AFFINITY_INFO`. 63 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 64 pub enum LowestAffinityLevel { 65 /// All afinity level fields are valid. 66 All = 0, 67 /// The `Aff0` field is ignored. 68 Aff0Ignored = 1, 69 /// The `Aff0` and `Aff1` fields are ignored. 70 Aff0Aff1Ignored = 2, 71 /// The `Aff0`, `Aff1` and `Aff2` fields are ignored. 72 Aff0Aff1Aff2Ignored = 3, 73 } 74 75 impl From<LowestAffinityLevel> for u64 { from(lowest_affinity_level: LowestAffinityLevel) -> u6476 fn from(lowest_affinity_level: LowestAffinityLevel) -> u64 { 77 (lowest_affinity_level as u32).into() 78 } 79 } 80 81 /// Affinity state values returned by `AFFINITY_INFO`. 82 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 83 pub enum AffinityState { 84 /// At least one core in the affinity instance is on. 85 On = 0, 86 /// All cores in the affinity instance are off. 87 Off = 1, 88 /// The affinity instance is transitioning to the on state. 89 OnPending = 2, 90 } 91 92 impl TryFrom<i32> for AffinityState { 93 type Error = Error; 94 try_from(value: i32) -> Result<Self, Error>95 fn try_from(value: i32) -> Result<Self, Error> { 96 match value { 97 0 => Ok(Self::On), 98 1 => Ok(Self::Off), 99 2 => Ok(Self::OnPending), 100 _ => Err(value.into()), 101 } 102 } 103 } 104 105 /// The level of multicore support in the Trusted OS, as returned by `MIGRATE_INFO_TYPE`. 106 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 107 pub enum MigrateType { 108 /// The Trusted OS will only run on one core, and supports the `MIGRATE` function. 109 MigrateCapable = 0, 110 /// The Trusted OS does not support the `MIGRATE` function. 111 NotMigrateCapable = 1, 112 /// Either there is no Trusted OS, or it doesn't require migration. 113 MigrationNotRequired = 2, 114 } 115 116 impl TryFrom<i32> for MigrateType { 117 type Error = Error; 118 try_from(value: i32) -> Result<Self, Error>119 fn try_from(value: i32) -> Result<Self, Error> { 120 match value { 121 0 => Ok(Self::MigrateCapable), 122 1 => Ok(Self::NotMigrateCapable), 123 2 => Ok(Self::MigrationNotRequired), 124 _ => Err(value.into()), 125 } 126 } 127 } 128 129 /// The power state of a node in the power domain topology, as returned by `NODE_HW_STATE`. 130 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 131 pub enum PowerState { 132 /// The node is in the run state. 133 HwOn = 0, 134 /// The node is fully powered down. 135 HwOff = 1, 136 /// The node is in a standby or retention power state. 137 HwStandby = 2, 138 } 139 140 impl TryFrom<i32> for PowerState { 141 type Error = Error; 142 try_from(value: i32) -> Result<Self, Error>143 fn try_from(value: i32) -> Result<Self, Error> { 144 match value { 145 0 => Ok(Self::HwOn), 146 1 => Ok(Self::HwOff), 147 2 => Ok(Self::HwStandby), 148 _ => Err(value.into()), 149 } 150 } 151 } 152 153 /// The mode to be used by `CPU_SUSPEND`, as set by `PSCI_SET_SUSPEND_MODE`. 154 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 155 pub enum SuspendMode { 156 /// Platform-coordinated mode. 157 PlatformCoordinated = 0, 158 /// OS-initiated mode. 159 OsInitiated = 1, 160 } 161 162 impl From<SuspendMode> for u32 { from(suspend_mode: SuspendMode) -> u32163 fn from(suspend_mode: SuspendMode) -> u32 { 164 suspend_mode as u32 165 } 166 } 167