xref: /rk3399_ARM-atf/bl32/sp_min/sp_min_main.c (revision f426fc0519103defb3dcf4a9d86d985d48204424)
1 /*
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 */
51 static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT];
52 
53 /* SP_MIN only stores the non secure smc context */
54 static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT];
55 
56 /******************************************************************************
57  * Define the smcc helper library API's
58  *****************************************************************************/
59 void *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 
65 void 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 
71 void *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  ******************************************************************************/
81 void *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  ******************************************************************************/
91 void 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  ******************************************************************************/
103 void *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  ******************************************************************************/
114 void 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 
121 static 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  ******************************************************************************/
134 static 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  *****************************************************************************/
157 void sp_min_main(void)
158 {
159 	/* 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 */
166 	sp_min_platform_setup();
167 
168 	/*
169 	 * Initialize the PSCI library and perform the remaining generic
170 	 * architectural setup from PSCI.
171 	 */
172 	psci_setup(&psci_args);
173 
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  *****************************************************************************/
194 void 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 }
208