xref: /rk3399_ARM-atf/bl32/sp_min/sp_min_main.c (revision 51faada71a219a8b94cd8d8e423f0f22e9da4d8f)
1 /*
2  * Copyright (c) 2016-2017, 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 <utils.h>
49 #include "sp_min_private.h"
50 
51 /* Pointers to per-core cpu contexts */
52 static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT];
53 
54 /* SP_MIN only stores the non secure smc context */
55 static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT];
56 
57 /******************************************************************************
58  * Define the smcc helper library API's
59  *****************************************************************************/
60 void *smc_get_ctx(int security_state)
61 {
62 	assert(security_state == NON_SECURE);
63 	return &sp_min_smc_context[plat_my_core_pos()];
64 }
65 
66 void smc_set_next_ctx(int security_state)
67 {
68 	assert(security_state == NON_SECURE);
69 	/* SP_MIN stores only non secure smc context. Nothing to do here */
70 }
71 
72 void *smc_get_next_ctx(void)
73 {
74 	return &sp_min_smc_context[plat_my_core_pos()];
75 }
76 
77 /*******************************************************************************
78  * This function returns a pointer to the most recent 'cpu_context' structure
79  * for the calling CPU that was set as the context for the specified security
80  * state. NULL is returned if no such structure has been specified.
81  ******************************************************************************/
82 void *cm_get_context(uint32_t security_state)
83 {
84 	assert(security_state == NON_SECURE);
85 	return sp_min_cpu_ctx_ptr[plat_my_core_pos()];
86 }
87 
88 /*******************************************************************************
89  * This function sets the pointer to the current 'cpu_context' structure for the
90  * specified security state for the calling CPU
91  ******************************************************************************/
92 void cm_set_context(void *context, uint32_t security_state)
93 {
94 	assert(security_state == NON_SECURE);
95 	sp_min_cpu_ctx_ptr[plat_my_core_pos()] = context;
96 }
97 
98 /*******************************************************************************
99  * This function returns a pointer to the most recent 'cpu_context' structure
100  * for the CPU identified by `cpu_idx` that was set as the context for the
101  * specified security state. NULL is returned if no such structure has been
102  * specified.
103  ******************************************************************************/
104 void *cm_get_context_by_index(unsigned int cpu_idx,
105 				unsigned int security_state)
106 {
107 	assert(security_state == NON_SECURE);
108 	return sp_min_cpu_ctx_ptr[cpu_idx];
109 }
110 
111 /*******************************************************************************
112  * This function sets the pointer to the current 'cpu_context' structure for the
113  * specified security state for the CPU identified by CPU index.
114  ******************************************************************************/
115 void cm_set_context_by_index(unsigned int cpu_idx, void *context,
116 				unsigned int security_state)
117 {
118 	assert(security_state == NON_SECURE);
119 	sp_min_cpu_ctx_ptr[cpu_idx] = context;
120 }
121 
122 static void copy_cpu_ctx_to_smc_stx(const regs_t *cpu_reg_ctx,
123 				smc_ctx_t *next_smc_ctx)
124 {
125 	next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0);
126 	next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR);
127 	next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR);
128 }
129 
130 /*******************************************************************************
131  * This function invokes the PSCI library interface to initialize the
132  * non secure cpu context and copies the relevant cpu context register values
133  * to smc context. These registers will get programmed during `smc_exit`.
134  ******************************************************************************/
135 static void sp_min_prepare_next_image_entry(void)
136 {
137 	entry_point_info_t *next_image_info;
138 
139 	/* Program system registers to proceed to non-secure */
140 	next_image_info = sp_min_plat_get_bl33_ep_info();
141 	assert(next_image_info);
142 	assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr));
143 
144 	INFO("SP_MIN: Preparing exit to normal world\n");
145 
146 	psci_prepare_next_non_secure_ctx(next_image_info);
147 	smc_set_next_ctx(NON_SECURE);
148 
149 	/* Copy r0, lr and spsr from cpu context to SMC context */
150 	copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
151 			smc_get_next_ctx());
152 }
153 
154 /******************************************************************************
155  * Implement the ARM Standard Service function to get arguments for a
156  * particular service.
157  *****************************************************************************/
158 uintptr_t get_arm_std_svc_args(unsigned int svc_mask)
159 {
160 	/* Setup the arguments for PSCI Library */
161 	DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint);
162 
163 	/* PSCI is the only ARM Standard Service implemented */
164 	assert(svc_mask == PSCI_FID_MASK);
165 
166 	return (uintptr_t)&psci_args;
167 }
168 
169 /******************************************************************************
170  * The SP_MIN main function. Do the platform and PSCI Library setup. Also
171  * initialize the runtime service framework.
172  *****************************************************************************/
173 void sp_min_main(void)
174 {
175 	NOTICE("SP_MIN: %s\n", version_string);
176 	NOTICE("SP_MIN: %s\n", build_message);
177 
178 	/* Perform the SP_MIN platform setup */
179 	sp_min_platform_setup();
180 
181 	/* Initialize the runtime services e.g. psci */
182 	INFO("SP_MIN: Initializing runtime services\n");
183 	runtime_svc_init();
184 
185 	/*
186 	 * We are ready to enter the next EL. Prepare entry into the image
187 	 * corresponding to the desired security state after the next ERET.
188 	 */
189 	sp_min_prepare_next_image_entry();
190 }
191 
192 /******************************************************************************
193  * This function is invoked during warm boot. Invoke the PSCI library
194  * warm boot entry point which takes care of Architectural and platform setup/
195  * restore. Copy the relevant cpu_context register values to smc context which
196  * will get programmed during `smc_exit`.
197  *****************************************************************************/
198 void sp_min_warm_boot(void)
199 {
200 	smc_ctx_t *next_smc_ctx;
201 
202 	psci_warmboot_entrypoint();
203 
204 	smc_set_next_ctx(NON_SECURE);
205 
206 	next_smc_ctx = smc_get_next_ctx();
207 	zeromem(next_smc_ctx, sizeof(smc_ctx_t));
208 
209 	copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)),
210 			next_smc_ctx);
211 }
212