2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 #include <arch_helpers.h>
10 #include <context_mgmt.h>
14 #include <interrupt_mgmt.h>
16 #include <runtime_svc.h>
18 #include <smccc_helpers.h>
23 #include <xlat_tables_v2.h>
25 #include "spm_private.h"
27 /*******************************************************************************
28 * Secure Partition context information.
29 ******************************************************************************/
30 sp_context_t sp_ctx_array
[PLAT_SPM_MAX_PARTITIONS
];
32 /* Last Secure Partition last used by the CPU */
33 sp_context_t
*cpu_sp_ctx
[PLATFORM_CORE_COUNT
];
35 void spm_cpu_set_sp_ctx(unsigned int linear_id
, sp_context_t
*sp_ctx
)
37 assert(linear_id
< PLATFORM_CORE_COUNT
);
39 cpu_sp_ctx
[linear_id
] = sp_ctx
;
42 sp_context_t
*spm_cpu_get_sp_ctx(unsigned int linear_id
)
44 assert(linear_id
< PLATFORM_CORE_COUNT
);
46 return cpu_sp_ctx
[linear_id
];
49 /*******************************************************************************
50 * Functions to keep track of how many requests a Secure Partition has received
51 * and hasn't finished.
52 ******************************************************************************/
53 void spm_sp_request_increase(sp_context_t
*sp_ctx
)
55 spin_lock(&(sp_ctx
->request_count_lock
));
56 sp_ctx
->request_count
++;
57 spin_unlock(&(sp_ctx
->request_count_lock
));
60 void spm_sp_request_decrease(sp_context_t
*sp_ctx
)
62 spin_lock(&(sp_ctx
->request_count_lock
));
63 sp_ctx
->request_count
--;
64 spin_unlock(&(sp_ctx
->request_count_lock
));
67 /* Returns 0 if it was originally 0, -1 otherwise. */
68 int spm_sp_request_increase_if_zero(sp_context_t
*sp_ctx
)
72 spin_lock(&(sp_ctx
->request_count_lock
));
73 if (sp_ctx
->request_count
== 0U) {
74 sp_ctx
->request_count
++;
77 spin_unlock(&(sp_ctx
->request_count_lock
));
82 /*******************************************************************************
83 * This function returns a pointer to the context of the Secure Partition that
84 * handles the service specified by an UUID. It returns NULL if the UUID wasn't
86 ******************************************************************************/
87 sp_context_t
*spm_sp_get_by_uuid(const uint32_t (*svc_uuid
)[4])
91 for (i
= 0U; i
< PLAT_SPM_MAX_PARTITIONS
; i
++) {
93 sp_context_t
*sp_ctx
= &sp_ctx_array
[i
];
95 if (sp_ctx
->is_present
== 0) {
99 struct sp_rd_sect_service
*rdsvc
;
101 for (rdsvc
= sp_ctx
->rd
.service
; rdsvc
!= NULL
;
102 rdsvc
= rdsvc
->next
) {
103 uint32_t *rd_uuid
= (uint32_t *)(rdsvc
->uuid
);
105 if (memcmp(rd_uuid
, svc_uuid
, sizeof(rd_uuid
)) == 0) {
114 /*******************************************************************************
115 * Set state of a Secure Partition context.
116 ******************************************************************************/
117 void sp_state_set(sp_context_t
*sp_ptr
, sp_state_t state
)
119 spin_lock(&(sp_ptr
->state_lock
));
120 sp_ptr
->state
= state
;
121 spin_unlock(&(sp_ptr
->state_lock
));
124 /*******************************************************************************
125 * Wait until the state of a Secure Partition is the specified one and change it
126 * to the desired state.
127 ******************************************************************************/
128 void sp_state_wait_switch(sp_context_t
*sp_ptr
, sp_state_t from
, sp_state_t to
)
132 while (success
== 0) {
133 spin_lock(&(sp_ptr
->state_lock
));
135 if (sp_ptr
->state
== from
) {
141 spin_unlock(&(sp_ptr
->state_lock
));
145 /*******************************************************************************
146 * Check if the state of a Secure Partition is the specified one and, if so,
147 * change it to the desired state. Returns 0 on success, -1 on error.
148 ******************************************************************************/
149 int sp_state_try_switch(sp_context_t
*sp_ptr
, sp_state_t from
, sp_state_t to
)
153 spin_lock(&(sp_ptr
->state_lock
));
155 if (sp_ptr
->state
== from
) {
161 spin_unlock(&(sp_ptr
->state_lock
));
166 /*******************************************************************************
167 * This function takes an SP context pointer and performs a synchronous entry
169 ******************************************************************************/
170 uint64_t spm_sp_synchronous_entry(sp_context_t
*sp_ctx
, int can_preempt
)
173 unsigned int linear_id
= plat_my_core_pos();
175 assert(sp_ctx
!= NULL
);
177 /* Assign the context of the SP to this CPU */
178 spm_cpu_set_sp_ctx(linear_id
, sp_ctx
);
179 cm_set_context(&(sp_ctx
->cpu_ctx
), SECURE
);
181 /* Restore the context assigned above */
182 cm_el1_sysregs_context_restore(SECURE
);
183 cm_set_next_eret_context(SECURE
);
185 /* Invalidate TLBs at EL1. */
189 if (can_preempt
== 1) {
190 enable_intr_rm_local(INTR_TYPE_NS
, SECURE
);
192 disable_intr_rm_local(INTR_TYPE_NS
, SECURE
);
195 /* Enter Secure Partition */
196 rc
= spm_secure_partition_enter(&sp_ctx
->c_rt_ctx
);
198 /* Save secure state */
199 cm_el1_sysregs_context_save(SECURE
);
204 /*******************************************************************************
205 * This function returns to the place where spm_sp_synchronous_entry() was
207 ******************************************************************************/
208 __dead2
void spm_sp_synchronous_exit(uint64_t rc
)
210 /* Get context of the SP in use by this CPU. */
211 unsigned int linear_id
= plat_my_core_pos();
212 sp_context_t
*ctx
= spm_cpu_get_sp_ctx(linear_id
);
215 * The SPM must have initiated the original request through a
216 * synchronous entry into the secure partition. Jump back to the
217 * original C runtime context with the value of rc in x0;
219 spm_secure_partition_exit(ctx
->c_rt_ctx
, rc
);
224 /*******************************************************************************
225 * This function is the handler registered for Non secure interrupts by the SPM.
226 * It validates the interrupt and upon success arranges entry into the normal
227 * world for handling the interrupt.
228 ******************************************************************************/
229 static uint64_t spm_ns_interrupt_handler(uint32_t id
, uint32_t flags
,
230 void *handle
, void *cookie
)
232 /* Check the security state when the exception was generated */
233 assert(get_interrupt_src_ss(flags
) == SECURE
);
235 spm_sp_synchronous_exit(SPM_SECURE_PARTITION_PREEMPTED
);
238 /*******************************************************************************
239 * Jump to each Secure Partition for the first time.
240 ******************************************************************************/
241 static int32_t spm_init(void)
246 for (unsigned int i
= 0U; i
< PLAT_SPM_MAX_PARTITIONS
; i
++) {
248 ctx
= &sp_ctx_array
[i
];
250 if (ctx
->is_present
== 0) {
254 INFO("Secure Partition %u init...\n", i
);
256 ctx
->state
= SP_STATE_RESET
;
258 rc
= spm_sp_synchronous_entry(ctx
, 0);
259 if (rc
!= SPRT_YIELD_AARCH64
) {
260 ERROR("Unexpected return value 0x%llx\n", rc
);
264 ctx
->state
= SP_STATE_IDLE
;
266 INFO("Secure Partition %u initialized.\n", i
);
272 /*******************************************************************************
273 * Initialize contexts of all Secure Partitions.
274 ******************************************************************************/
275 int32_t spm_setup(void)
279 void *sp_base
, *rd_base
;
280 size_t sp_size
, rd_size
;
283 /* Disable MMU at EL1 (initialized by BL2) */
284 disable_mmu_icache_el1();
287 * Non-blocking services can be interrupted by Non-secure interrupts.
288 * Register an interrupt handler for NS interrupts when generated while
289 * the CPU is in secure state. They are routed to EL3.
291 set_interrupt_rm_flag(flags
, SECURE
);
293 uint64_t rc_int
= register_interrupt_type_handler(INTR_TYPE_NS
,
294 spm_ns_interrupt_handler
, flags
);
296 ERROR("SPM: Failed to register NS interrupt handler with rc = %llx\n",
302 * Setup all Secure Partitions.
307 rc
= plat_spm_sp_get_next_address(&sp_base
, &sp_size
,
310 /* Reached the end of the package. */
314 if (i
>= PLAT_SPM_MAX_PARTITIONS
) {
315 ERROR("Too many partitions in the package.\n");
319 ctx
= &sp_ctx_array
[i
];
321 assert(ctx
->is_present
== 0);
323 /* Initialize context of the SP */
324 INFO("Secure Partition %u context setup start...\n", i
);
326 /* Assign translation tables context. */
327 ctx
->xlat_ctx_handle
= spm_sp_xlat_context_alloc();
329 /* Save location of the image in physical memory */
330 ctx
->image_base
= (uintptr_t)sp_base
;
331 ctx
->image_size
= sp_size
;
333 rc
= plat_spm_sp_rd_load(&ctx
->rd
, rd_base
, rd_size
);
335 ERROR("Error while loading RD blob.\n");
343 INFO("Secure Partition %u setup done.\n", i
);
349 ERROR("No present partitions in the package.\n");
353 /* Register init function for deferred init. */
354 bl31_register_bl32_init(&spm_init
);