blob: 6bf1ff456bb2eecb3dac5aede65b4f06a9ca3e3a [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Govindraj Rajaeee28e72023-08-01 15:52:40 -05002 * Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta4f6ad662013-10-25 09:08:21 +01005 */
6
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00007#include <assert.h>
8#include <stddef.h>
9
Dan Handley2bd4ef22014-04-09 13:14:54 +010010#include <arch.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010011#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000012#include <common/bl_common.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010013#include <context.h>
Boyan Karatotev5d38cb32023-01-27 09:37:07 +000014#include <lib/cpus/errata.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000015#include <lib/el3_runtime/context_mgmt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <plat/common/platform.h>
17
Dan Handley714a0d22014-04-09 13:13:04 +010018#include "psci_private.h"
Achin Gupta4f6ad662013-10-25 09:08:21 +010019
Graeme Gregory1b4938b2020-12-02 16:24:32 +000020/*
21 * Check that PLATFORM_CORE_COUNT fits into the number of cores
22 * that can be represented by PSCI_MAX_CPUS_INDEX.
23 */
24CASSERT(PLATFORM_CORE_COUNT <= (PSCI_MAX_CPUS_INDEX + 1U), assert_psci_cores_overflow);
25
Achin Gupta4f6ad662013-10-25 09:08:21 +010026/*******************************************************************************
Achin Guptaef7a28c2014-02-01 08:59:56 +000027 * Per cpu non-secure contexts used to program the architectural state prior
28 * return to the normal world.
29 * TODO: Use the memory allocator to set aside memory for the contexts instead
Soby Mathew981487a2015-07-13 14:10:57 +010030 * of relying on platform defined constants.
Achin Guptaef7a28c2014-02-01 08:59:56 +000031 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010032static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
Achin Guptaef7a28c2014-02-01 08:59:56 +000033
Soby Mathew6cdddaf2015-01-07 11:10:22 +000034/******************************************************************************
35 * Define the psci capability variable.
36 *****************************************************************************/
Soby Mathew011ca182015-07-29 17:05:03 +010037unsigned int psci_caps;
Soby Mathew6cdddaf2015-01-07 11:10:22 +000038
Dan Handley60b13e32014-05-14 15:13:16 +010039/*******************************************************************************
Soby Mathew981487a2015-07-13 14:10:57 +010040 * Function which initializes the 'psci_non_cpu_pd_nodes' or the
41 * 'psci_cpu_pd_nodes' corresponding to the power level.
Achin Gupta4f6ad662013-10-25 09:08:21 +010042 ******************************************************************************/
Graeme Gregory1b4938b2020-12-02 16:24:32 +000043static void __init psci_init_pwr_domain_node(uint16_t node_idx,
Soby Mathew011ca182015-07-29 17:05:03 +010044 unsigned int parent_idx,
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +010045 unsigned char level)
Achin Gupta4f6ad662013-10-25 09:08:21 +010046{
Soby Mathew981487a2015-07-13 14:10:57 +010047 if (level > PSCI_CPU_PWR_LVL) {
Graeme Gregory1b4938b2020-12-02 16:24:32 +000048 assert(node_idx < PSCI_NUM_NON_CPU_PWR_DOMAINS);
49
Soby Mathew981487a2015-07-13 14:10:57 +010050 psci_non_cpu_pd_nodes[node_idx].level = level;
51 psci_lock_init(psci_non_cpu_pd_nodes, node_idx);
52 psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx;
53 psci_non_cpu_pd_nodes[node_idx].local_state =
54 PLAT_MAX_OFF_STATE;
55 } else {
56 psci_cpu_data_t *svc_cpu_data;
Achin Gupta4f6ad662013-10-25 09:08:21 +010057
Graeme Gregory1b4938b2020-12-02 16:24:32 +000058 assert(node_idx < PLATFORM_CORE_COUNT);
59
Soby Mathew981487a2015-07-13 14:10:57 +010060 psci_cpu_pd_nodes[node_idx].parent_node = parent_idx;
Achin Gupta4f6ad662013-10-25 09:08:21 +010061
Soby Mathew981487a2015-07-13 14:10:57 +010062 /* Initialize with an invalid mpidr */
63 psci_cpu_pd_nodes[node_idx].mpidr = PSCI_INVALID_MPIDR;
Soby Mathew2b697502014-10-02 17:24:19 +010064
Soby Mathew981487a2015-07-13 14:10:57 +010065 svc_cpu_data =
66 &(_cpu_data_by_index(node_idx)->psci_svc_cpu_data);
Soby Mathew2b697502014-10-02 17:24:19 +010067
Soby Mathew981487a2015-07-13 14:10:57 +010068 /* Set the Affinity Info for the cores as OFF */
69 svc_cpu_data->aff_info_state = AFF_STATE_OFF;
Achin Gupta4f6ad662013-10-25 09:08:21 +010070
Soby Mathew981487a2015-07-13 14:10:57 +010071 /* Invalidate the suspend level for the cpu */
Soby Mathew011ca182015-07-29 17:05:03 +010072 svc_cpu_data->target_pwrlvl = PSCI_INVALID_PWR_LVL;
Achin Gupta4f6ad662013-10-25 09:08:21 +010073
Soby Mathew981487a2015-07-13 14:10:57 +010074 /* Set the power state to OFF state */
75 svc_cpu_data->local_state = PLAT_MAX_OFF_STATE;
Soby Mathew2b697502014-10-02 17:24:19 +010076
Jeenu Viswambharan0b56d6f2017-01-06 14:58:11 +000077 psci_flush_dcache_range((uintptr_t)svc_cpu_data,
Soby Mathew981487a2015-07-13 14:10:57 +010078 sizeof(*svc_cpu_data));
Achin Gupta4f6ad662013-10-25 09:08:21 +010079
Soby Mathew981487a2015-07-13 14:10:57 +010080 cm_set_context_by_index(node_idx,
81 (void *) &psci_ns_context[node_idx],
82 NON_SECURE);
83 }
Achin Gupta4f6ad662013-10-25 09:08:21 +010084}
85
86/*******************************************************************************
Soby Mathew981487a2015-07-13 14:10:57 +010087 * This functions updates cpu_start_idx and ncpus field for each of the node in
88 * psci_non_cpu_pd_nodes[]. It does so by comparing the parent nodes of each of
89 * the CPUs and check whether they match with the parent of the previous
90 * CPU. The basic assumption for this work is that children of the same parent
91 * are allocated adjacent indices. The platform should ensure this though proper
92 * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and
93 * plat_my_core_pos() APIs.
94 *******************************************************************************/
Daniel Boulby5753e492018-09-20 14:12:46 +010095static void __init psci_update_pwrlvl_limits(void)
Achin Gupta0959db52013-12-02 17:33:04 +000096{
Pankaj Gupta02c35682019-10-15 15:44:45 +053097 unsigned int cpu_idx;
98 int j;
Soby Mathew981487a2015-07-13 14:10:57 +010099 unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0};
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100100 unsigned int temp_index[PLAT_MAX_PWR_LVL];
Achin Gupta0959db52013-12-02 17:33:04 +0000101
Pankaj Gupta02c35682019-10-15 15:44:45 +0530102 for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) {
Soby Mathew981487a2015-07-13 14:10:57 +0100103 psci_get_parent_pwr_domain_nodes(cpu_idx,
Deepika Bhavnani4287c0c2019-12-13 10:23:18 -0600104 PLAT_MAX_PWR_LVL,
Soby Mathew981487a2015-07-13 14:10:57 +0100105 temp_index);
Deepika Bhavnani4287c0c2019-12-13 10:23:18 -0600106 for (j = (int)PLAT_MAX_PWR_LVL - 1; j >= 0; j--) {
Soby Mathew981487a2015-07-13 14:10:57 +0100107 if (temp_index[j] != nodes_idx[j]) {
108 nodes_idx[j] = temp_index[j];
109 psci_non_cpu_pd_nodes[nodes_idx[j]].cpu_start_idx
110 = cpu_idx;
Achin Gupta0959db52013-12-02 17:33:04 +0000111 }
Soby Mathew981487a2015-07-13 14:10:57 +0100112 psci_non_cpu_pd_nodes[nodes_idx[j]].ncpus++;
113 }
Achin Gupta0959db52013-12-02 17:33:04 +0000114 }
Achin Gupta0959db52013-12-02 17:33:04 +0000115}
116
117/*******************************************************************************
Soby Mathew981487a2015-07-13 14:10:57 +0100118 * Core routine to populate the power domain tree. The tree descriptor passed by
119 * the platform is populated breadth-first and the first entry in the map
120 * informs the number of root power domains. The parent nodes of the root nodes
121 * will point to an invalid entry(-1).
Achin Gupta4f6ad662013-10-25 09:08:21 +0100122 ******************************************************************************/
Pankaj Gupta02c35682019-10-15 15:44:45 +0530123static unsigned int __init populate_power_domain_tree(const unsigned char
124 *topology)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100125{
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100126 unsigned int i, j = 0U, num_nodes_at_lvl = 1U, num_nodes_at_next_lvl;
127 unsigned int node_index = 0U, num_children;
Deepika Bhavnani4287c0c2019-12-13 10:23:18 -0600128 unsigned int parent_node_index = 0U;
129 int level = (int)PLAT_MAX_PWR_LVL;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100130
131 /*
Soby Mathew981487a2015-07-13 14:10:57 +0100132 * For each level the inputs are:
133 * - number of nodes at this level in plat_array i.e. num_nodes_at_level
134 * This is the sum of values of nodes at the parent level.
135 * - Index of first entry at this level in the plat_array i.e.
136 * parent_node_index.
137 * - Index of first free entry in psci_non_cpu_pd_nodes[] or
138 * psci_cpu_pd_nodes[] i.e. node_index depending upon the level.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100139 */
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100140 while (level >= (int) PSCI_CPU_PWR_LVL) {
141 num_nodes_at_next_lvl = 0U;
Achin Guptaef7a28c2014-02-01 08:59:56 +0000142 /*
Soby Mathew981487a2015-07-13 14:10:57 +0100143 * For each entry (parent node) at this level in the plat_array:
144 * - Find the number of children
145 * - Allocate a node in a power domain array for each child
146 * - Set the parent of the child to the parent_node_index - 1
147 * - Increment parent_node_index to point to the next parent
148 * - Accumulate the number of children at next level.
Achin Guptaef7a28c2014-02-01 08:59:56 +0000149 */
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100150 for (i = 0U; i < num_nodes_at_lvl; i++) {
Soby Mathew981487a2015-07-13 14:10:57 +0100151 assert(parent_node_index <=
152 PSCI_NUM_NON_CPU_PWR_DOMAINS);
153 num_children = topology[parent_node_index];
Achin Guptaef7a28c2014-02-01 08:59:56 +0000154
Soby Mathew981487a2015-07-13 14:10:57 +0100155 for (j = node_index;
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100156 j < (node_index + num_children); j++)
Graeme Gregory1b4938b2020-12-02 16:24:32 +0000157 psci_init_pwr_domain_node((uint16_t)j,
Deepika Bhavnani4287c0c2019-12-13 10:23:18 -0600158 parent_node_index - 1U,
159 (unsigned char)level);
Achin Guptaf3ccbab2014-07-25 14:52:47 +0100160
Soby Mathew981487a2015-07-13 14:10:57 +0100161 node_index = j;
162 num_nodes_at_next_lvl += num_children;
163 parent_node_index++;
164 }
Achin Guptaf6b9e992014-07-31 11:19:11 +0100165
Soby Mathew981487a2015-07-13 14:10:57 +0100166 num_nodes_at_lvl = num_nodes_at_next_lvl;
167 level--;
Soby Mathew7d861ea2014-11-18 10:14:14 +0000168
Soby Mathew981487a2015-07-13 14:10:57 +0100169 /* Reset the index for the cpu power domain array */
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100170 if (level == (int) PSCI_CPU_PWR_LVL)
Soby Mathew981487a2015-07-13 14:10:57 +0100171 node_index = 0;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100172 }
173
Soby Mathew981487a2015-07-13 14:10:57 +0100174 /* Validate the sanity of array exported by the platform */
Deepika Bhavnani4287c0c2019-12-13 10:23:18 -0600175 assert(j <= PLATFORM_CORE_COUNT);
Pankaj Gupta02c35682019-10-15 15:44:45 +0530176 return j;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100177}
178
179/*******************************************************************************
Soby Mathewd0194872016-04-29 19:01:30 +0100180 * This function does the architectural setup and takes the warm boot
181 * entry-point `mailbox_ep` as an argument. The function also initializes the
182 * power domain topology tree by querying the platform. The power domain nodes
183 * higher than the CPU are populated in the array psci_non_cpu_pd_nodes[] and
184 * the CPU power domains are populated in psci_cpu_pd_nodes[]. The platform
185 * exports its static topology map through the
Soby Mathew981487a2015-07-13 14:10:57 +0100186 * populate_power_domain_topology_tree() API. The algorithm populates the
187 * psci_non_cpu_pd_nodes and psci_cpu_pd_nodes iteratively by using this
Soby Mathewd0194872016-04-29 19:01:30 +0100188 * topology map. On a platform that implements two clusters of 2 cpus each,
189 * and supporting 3 domain levels, the populated psci_non_cpu_pd_nodes would
190 * look like this:
Achin Gupta4f6ad662013-10-25 09:08:21 +0100191 *
Achin Gupta4f6ad662013-10-25 09:08:21 +0100192 * ---------------------------------------------------
Soby Mathew981487a2015-07-13 14:10:57 +0100193 * | system node | cluster 0 node | cluster 1 node |
Achin Gupta4f6ad662013-10-25 09:08:21 +0100194 * ---------------------------------------------------
Achin Gupta4f6ad662013-10-25 09:08:21 +0100195 *
Soby Mathew981487a2015-07-13 14:10:57 +0100196 * And populated psci_cpu_pd_nodes would look like this :
197 * <- cpus cluster0 -><- cpus cluster1 ->
198 * ------------------------------------------------
199 * | CPU 0 | CPU 1 | CPU 2 | CPU 3 |
200 * ------------------------------------------------
Achin Gupta4f6ad662013-10-25 09:08:21 +0100201 ******************************************************************************/
Daniel Boulby5753e492018-09-20 14:12:46 +0100202int __init psci_setup(const psci_lib_args_t *lib_args)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100203{
Soby Mathew981487a2015-07-13 14:10:57 +0100204 const unsigned char *topology_tree;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100205
Soby Mathew89256b82016-09-13 14:19:08 +0100206 assert(VERIFY_PSCI_LIB_ARGS_V1(lib_args));
207
Soby Mathewd0194872016-04-29 19:01:30 +0100208 /* Do the Architectural initialization */
209 psci_arch_setup();
210
Soby Mathew981487a2015-07-13 14:10:57 +0100211 /* Query the topology map from the platform */
212 topology_tree = plat_get_power_domain_tree_desc();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100213
Soby Mathew981487a2015-07-13 14:10:57 +0100214 /* Populate the power domain arrays using the platform topology map */
Pankaj Gupta02c35682019-10-15 15:44:45 +0530215 psci_plat_core_count = populate_power_domain_tree(topology_tree);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100216
Soby Mathew981487a2015-07-13 14:10:57 +0100217 /* Update the CPU limits for each node in psci_non_cpu_pd_nodes */
218 psci_update_pwrlvl_limits();
219
220 /* Populate the mpidr field of cpu node for this CPU */
221 psci_cpu_pd_nodes[plat_my_core_pos()].mpidr =
222 read_mpidr() & MPIDR_AFFINITY_MASK;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100223
Soby Mathew981487a2015-07-13 14:10:57 +0100224 psci_init_req_local_pwr_states();
Achin Gupta4f6ad662013-10-25 09:08:21 +0100225
226 /*
Soby Mathew981487a2015-07-13 14:10:57 +0100227 * Set the requested and target state of this CPU and all the higher
228 * power domain levels for this CPU to run.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100229 */
Soby Mathew981487a2015-07-13 14:10:57 +0100230 psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100231
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100232 (void) plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep,
233 &psci_plat_pm_ops);
234 assert(psci_plat_pm_ops != NULL);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100235
Soby Mathew7c9d5f82016-09-09 11:33:58 +0100236 /*
237 * Flush `psci_plat_pm_ops` as it will be accessed by secondary CPUs
Jeenu Viswambharan0b56d6f2017-01-06 14:58:11 +0000238 * during warm boot, possibly before data cache is enabled.
Soby Mathew7c9d5f82016-09-09 11:33:58 +0100239 */
Jeenu Viswambharan0b56d6f2017-01-06 14:58:11 +0000240 psci_flush_dcache_range((uintptr_t)&psci_plat_pm_ops,
Soby Mathew7c9d5f82016-09-09 11:33:58 +0100241 sizeof(psci_plat_pm_ops));
242
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000243 /* Initialize the psci capability */
244 psci_caps = PSCI_GENERIC_CAP;
245
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100246 if (psci_plat_pm_ops->pwr_domain_off != NULL)
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000247 psci_caps |= define_psci_cap(PSCI_CPU_OFF);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100248 if ((psci_plat_pm_ops->pwr_domain_on != NULL) &&
249 (psci_plat_pm_ops->pwr_domain_on_finish != NULL))
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000250 psci_caps |= define_psci_cap(PSCI_CPU_ON_AARCH64);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100251 if ((psci_plat_pm_ops->pwr_domain_suspend != NULL) &&
252 (psci_plat_pm_ops->pwr_domain_suspend_finish != NULL)) {
Samuel Hollande7e2afd2021-04-28 17:52:02 -0500253 if (psci_plat_pm_ops->validate_power_state != NULL)
254 psci_caps |= define_psci_cap(PSCI_CPU_SUSPEND_AARCH64);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100255 if (psci_plat_pm_ops->get_sys_suspend_power_state != NULL)
Soby Mathew96168382014-12-17 14:47:57 +0000256 psci_caps |= define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64);
Wing Li71f69df2022-09-14 13:18:15 -0700257#if PSCI_OS_INIT_MODE
258 psci_caps |= define_psci_cap(PSCI_SET_SUSPEND_MODE);
259#endif
Soby Mathew96168382014-12-17 14:47:57 +0000260 }
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100261 if (psci_plat_pm_ops->system_off != NULL)
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000262 psci_caps |= define_psci_cap(PSCI_SYSTEM_OFF);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100263 if (psci_plat_pm_ops->system_reset != NULL)
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000264 psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100265 if (psci_plat_pm_ops->get_node_hw_state != NULL)
Jeenu Viswambharan7f03e9d92016-08-03 15:54:50 +0100266 psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100267 if ((psci_plat_pm_ops->read_mem_protect != NULL) &&
268 (psci_plat_pm_ops->write_mem_protect != NULL))
Roberto Vargas0a4c2612017-08-03 08:16:16 +0100269 psci_caps |= define_psci_cap(PSCI_MEM_PROTECT);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100270 if (psci_plat_pm_ops->mem_protect_chk != NULL)
Roberto Vargas0a4c2612017-08-03 08:16:16 +0100271 psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64);
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100272 if (psci_plat_pm_ops->system_reset2 != NULL)
Roberto Vargasb820ad02017-07-26 09:23:09 +0100273 psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64);
Soby Mathew6cdddaf2015-01-07 11:10:22 +0000274
Yatharth Kochar241ec6c2016-05-09 18:26:35 +0100275#if ENABLE_PSCI_STAT
276 psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64);
277 psci_caps |= define_psci_cap(PSCI_STAT_COUNT_AARCH64);
278#endif
279
Achin Gupta7421b462014-02-01 18:53:26 +0000280 return 0;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100281}
Soby Mathewd0194872016-04-29 19:01:30 +0100282
283/*******************************************************************************
284 * This duplicates what the primary cpu did after a cold boot in BL1. The same
285 * needs to be done when a cpu is hotplugged in. This function could also over-
286 * ride any EL3 setup done by BL1 as this code resides in rw memory.
287 ******************************************************************************/
288void psci_arch_setup(void)
289{
Antonio Nino Diaz78a95a62018-07-17 15:10:08 +0100290#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
Soby Mathewd0194872016-04-29 19:01:30 +0100291 /* Program the counter frequency */
292 write_cntfrq_el0(plat_get_syscnt_freq2());
Etienne Carrieree259fa72017-11-08 14:41:47 +0100293#endif
Soby Mathewd0194872016-04-29 19:01:30 +0100294
295 /* Initialize the cpu_ops pointer. */
296 init_cpu_ops();
Jeenu Viswambharand5ec3672017-01-03 11:01:51 +0000297
298 /* Having initialized cpu_ops, we can now print errata status */
299 print_errata_status();
Alexei Fedorovf41355c2019-09-13 14:11:59 +0100300
301#if ENABLE_PAUTH
302 /* Store APIAKey_EL1 key */
303 set_cpu_data(apiakey[0], read_apiakeylo_el1());
304 set_cpu_data(apiakey[1], read_apiakeyhi_el1());
305#endif /* ENABLE_PAUTH */
Soby Mathewd0194872016-04-29 19:01:30 +0100306}
Soby Mathew89d90dc2016-05-05 14:11:23 +0100307
308/******************************************************************************
309 * PSCI Library interface to initialize the cpu context for the next non
310 * secure image during cold boot. The relevant registers in the cpu context
311 * need to be retrieved and programmed on return from this interface.
312 *****************************************************************************/
313void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info)
314{
315 assert(GET_SECURITY_STATE(next_image_info->h.attr) == NON_SECURE);
316 cm_init_my_context(next_image_info);
317 cm_prepare_el3_exit(NON_SECURE);
318}