summaryrefslogtreecommitdiff
path: root/lib/psci/psci_main.c
diff options
context:
space:
mode:
authorWing Li <wingers@google.com>2022-09-14 13:18:17 -0700
committerWing Li <wingers@google.com>2023-03-20 22:20:35 -0700
commit606b7430077c15695a5b3bcfbad4975f00c9bf95 (patch)
tree341df6d7d352afc086f6315d9fef4f25e84651f3 /lib/psci/psci_main.c
parentb88a4416b5e5f2bda2240c632ba79e15a9a75c45 (diff)
feat(psci): add support for OS-initiated mode
This patch adds a `psci_validate_state_coordination` function that is called by `psci_cpu_suspend_start` in OS-initiated mode. This function validates the request per sections 4.2.3.2, 5.4.5, and 6.3 of the PSCI spec (DEN0022D.b): - The requested power states are consistent with the system's state - The calling core is the last running core at the requested power level This function differs from `psci_do_state_coordination` in that: - The `psci_req_local_pwr_states` map is not modified if the request were to be denied - The `state_info` argument is never modified since it contains the power states requested by the calling OS This is conditionally compiled into the build depending on the value of the `PSCI_OS_INIT_MODE` build option. Change-Id: I667041c842d2856e9d128c98db4d5ae4e4552df3 Signed-off-by: Wing Li <wingers@google.com>
Diffstat (limited to 'lib/psci/psci_main.c')
-rw-r--r--lib/psci/psci_main.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 4b5fc81d7..fe12f06ba 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -60,6 +60,10 @@ int psci_cpu_suspend(unsigned int power_state,
entry_point_info_t ep;
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
plat_local_state_t cpu_pd_state;
+#if PSCI_OS_INIT_MODE
+ unsigned int cpu_idx = plat_my_core_pos();
+ plat_local_state_t prev[PLAT_MAX_PWR_LVL];
+#endif
/* Validate the power_state parameter */
rc = psci_validate_power_state(power_state, &state_info);
@@ -95,6 +99,18 @@ int psci_cpu_suspend(unsigned int power_state,
cpu_pd_state = state_info.pwr_domain_state[PSCI_CPU_PWR_LVL];
psci_set_cpu_local_state(cpu_pd_state);
+#if PSCI_OS_INIT_MODE
+ /*
+ * If in OS-initiated mode, save a copy of the previous
+ * requested local power states and update the new requested
+ * local power states for this CPU.
+ */
+ if (psci_suspend_mode == OS_INIT) {
+ psci_update_req_local_pwr_states(target_pwrlvl, cpu_idx,
+ &state_info, prev);
+ }
+#endif
+
#if ENABLE_PSCI_STAT
plat_psci_stat_accounting_start(&state_info);
#endif
@@ -110,6 +126,16 @@ int psci_cpu_suspend(unsigned int power_state,
/* Upon exit from standby, set the state back to RUN. */
psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN);
+#if PSCI_OS_INIT_MODE
+ /*
+ * If in OS-initiated mode, restore the previous requested
+ * local power states for this CPU.
+ */
+ if (psci_suspend_mode == OS_INIT) {
+ psci_restore_req_local_pwr_states(cpu_idx, prev);
+ }
+#endif
+
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
RT_INSTR_EXIT_HW_LOW_PWR,
@@ -142,12 +168,12 @@ int psci_cpu_suspend(unsigned int power_state,
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- psci_cpu_suspend_start(&ep,
- target_pwrlvl,
- &state_info,
- is_power_down_state);
+ rc = psci_cpu_suspend_start(&ep,
+ target_pwrlvl,
+ &state_info,
+ is_power_down_state);
- return PSCI_E_SUCCESS;
+ return rc;
}
@@ -187,12 +213,12 @@ int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id)
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- psci_cpu_suspend_start(&ep,
- PLAT_MAX_PWR_LVL,
- &state_info,
- PSTATE_TYPE_POWERDOWN);
+ rc = psci_cpu_suspend_start(&ep,
+ PLAT_MAX_PWR_LVL,
+ &state_info,
+ PSTATE_TYPE_POWERDOWN);
- return PSCI_E_SUCCESS;
+ return rc;
}
int psci_cpu_off(void)