blob: c1ba8fc5123208a87c8aa1548e3183ee9258db81 [file] [log] [blame]
Soby Mathewec8ac1c2016-05-05 14:32:05 +01001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch.h>
32#include <arch_helpers.h>
33#include <assert.h>
34#include <bl_common.h>
35#include <context.h>
36#include <context_mgmt.h>
37#include <debug.h>
38#include <platform.h>
39#include <platform_def.h>
40#include <platform_sp_min.h>
41#include <psci.h>
42#include <runtime_svc.h>
43#include <smcc_helpers.h>
44#include <stddef.h>
45#include <stdint.h>
46#include <string.h>
47#include <types.h>
48#include "sp_min_private.h"
49
50/* Pointers to per-core cpu contexts */
51static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT];
52
53/* SP_MIN only stores the non secure smc context */
54static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT];
55
56/******************************************************************************
57 * Define the smcc helper library API's
58 *****************************************************************************/
59void *smc_get_ctx(int security_state)
60{
61 assert(security_state == NON_SECURE);
62 return &sp_min_smc_context[plat_my_core_pos()];
63}
64
65void smc_set_next_ctx(int security_state)
66{
67 assert(security_state == NON_SECURE);
68 /* SP_MIN stores only non secure smc context. Nothing to do here */
69}
70
71void *smc_get_next_ctx(void)
72{
73 return &sp_min_smc_context[plat_my_core_pos()];
74}
75
76/*******************************************************************************
77 * This function returns a pointer to the most recent 'cpu_context' structure
78 * for the calling CPU that was set as the context for the specified security
79 * state. NULL is returned if no such structure has been specified.
80 ******************************************************************************/
81void *cm_get_context(uint32_t security_state)
82{
83 assert(security_state == NON_SECURE);
84 return sp_min_cpu_ctx_ptr[plat_my_core_pos()];
85}
86
87/*******************************************************************************
88 * This function sets the pointer to the current 'cpu_context' structure for the
89 * specified security state for the calling CPU
90 ******************************************************************************/
91void cm_set_context(void *context, uint32_t security_state)
92{
93 assert(security_state == NON_SECURE);
94 sp_min_cpu_ctx_ptr[plat_my_core_pos()] = context;
95}
96
97/*******************************************************************************
98 * This function returns a pointer to the most recent 'cpu_context' structure
99 * for the CPU identified by `cpu_idx` that was set as the context for the
100 * specified security state. NULL is returned if no such structure has been
101 * specified.
102 ******************************************************************************/
103void *cm_get_context_by_index(unsigned int cpu_idx,
104 unsigned int security_state)
105{
106 assert(security_state == NON_SECURE);
107 return sp_min_cpu_ctx_ptr[cpu_idx];
108}
109
110/*******************************************************************************
111 * This function sets the pointer to the current 'cpu_context' structure for the
112 * specified security state for the CPU identified by CPU index.
113 ******************************************************************************/
114void cm_set_context_by_index(unsigned int cpu_idx, void *context,
115 unsigned int security_state)
116{
117 assert(security_state == NON_SECURE);
118 sp_min_cpu_ctx_ptr[cpu_idx] = context;
119}
120
121static void copy_cpu_ctx_to_smc_stx(const regs_t *cpu_reg_ctx,
122 smc_ctx_t *next_smc_ctx)
123{
124 next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0);
125 next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR);
126 next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR);
127}
128
129/*******************************************************************************
130 * This function invokes the PSCI library interface to initialize the
131 * non secure cpu context and copies the relevant cpu context register values
132 * to smc context. These registers will get programmed during `smc_exit`.
133 ******************************************************************************/
134static void sp_min_prepare_next_image_entry(void)
135{
136 entry_point_info_t *next_image_info;
137
138 /* Program system registers to proceed to non-secure */
139 next_image_info = sp_min_plat_get_bl33_ep_info();
140 assert(next_image_info);
141 assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr));
142
143 INFO("SP_MIN: Preparing exit to normal world\n");
144
145 psci_prepare_next_non_secure_ctx(next_image_info);
146 smc_set_next_ctx(NON_SECURE);
147
148 /* Copy r0, lr and spsr from cpu context to SMC context */
149 copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
150 smc_get_next_ctx());
151}
152
153/******************************************************************************
154 * The SP_MIN main function. Do the platform and PSCI Library setup. Also
155 * initialize the runtime service framework.
156 *****************************************************************************/
157void sp_min_main(void)
158{
Soby Mathew89256b82016-09-13 14:19:08 +0100159 /* Setup the arguments for PSCI Library */
160 DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint);
161
162 NOTICE("SP_MIN: %s\n", version_string);
163 NOTICE("SP_MIN: %s\n", build_message);
164
165 /* Perform the SP_MIN platform setup */
Soby Mathewec8ac1c2016-05-05 14:32:05 +0100166 sp_min_platform_setup();
167
168 /*
169 * Initialize the PSCI library and perform the remaining generic
170 * architectural setup from PSCI.
171 */
Soby Mathew89256b82016-09-13 14:19:08 +0100172 psci_setup(&psci_args);
Soby Mathewec8ac1c2016-05-05 14:32:05 +0100173
174 /*
175 * Initialize the runtime services e.g. psci
176 * This is where the monitor mode will be initialized
177 */
178 INFO("SP_MIN: Initializing runtime services\n");
179 runtime_svc_init();
180
181 /*
182 * We are ready to enter the next EL. Prepare entry into the image
183 * corresponding to the desired security state after the next ERET.
184 */
185 sp_min_prepare_next_image_entry();
186}
187
188/******************************************************************************
189 * This function is invoked during warm boot. Invoke the PSCI library
190 * warm boot entry point which takes care of Architectural and platform setup/
191 * restore. Copy the relevant cpu_context register values to smc context which
192 * will get programmed during `smc_exit`.
193 *****************************************************************************/
194void sp_min_warm_boot(void)
195{
196 smc_ctx_t *next_smc_ctx;
197
198 psci_warmboot_entrypoint();
199
200 smc_set_next_ctx(NON_SECURE);
201
202 next_smc_ctx = smc_get_next_ctx();
203 memset(next_smc_ctx, 0, sizeof(smc_ctx_t));
204
205 copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
206 next_smc_ctx);
207}