Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AArch32: add a minimal secure payload (SP_MIN)
This patch adds a minimal AArch32 secure payload SP_MIN. It relies on PSCI library to initialize the normal world context. It runs in Monitor mode and uses the runtime service framework to handle SMCs. It is added as a BL32 component in the Trusted Firmware source tree. Change-Id: Icc04fa6b242025a769c1f6c7022fde19459c43e9
- Loading branch information
1 parent
727e523
commit c11ba85
Showing
6 changed files
with
907 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,331 @@ | ||
/* | ||
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are met: | ||
* | ||
* Redistributions of source code must retain the above copyright notice, this | ||
* list of conditions and the following disclaimer. | ||
* | ||
* Redistributions in binary form must reproduce the above copyright notice, | ||
* this list of conditions and the following disclaimer in the documentation | ||
* and/or other materials provided with the distribution. | ||
* | ||
* Neither the name of ARM nor the names of its contributors may be used | ||
* to endorse or promote products derived from this software without specific | ||
* prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
#include <arch.h> | ||
#include <asm_macros.S> | ||
#include <bl_common.h> | ||
#include <context.h> | ||
#include <runtime_svc.h> | ||
#include <smcc_helpers.h> | ||
#include <smcc_macros.S> | ||
#include <xlat_tables.h> | ||
|
||
.globl sp_min_vector_table | ||
.globl sp_min_entrypoint | ||
.globl sp_min_warm_entrypoint | ||
|
||
func sp_min_vector_table | ||
b sp_min_entrypoint | ||
b plat_panic_handler /* Undef */ | ||
b handle_smc /* Syscall */ | ||
b plat_panic_handler /* Prefetch abort */ | ||
b plat_panic_handler /* Data abort */ | ||
b plat_panic_handler /* Reserved */ | ||
b plat_panic_handler /* IRQ */ | ||
b plat_panic_handler /* FIQ */ | ||
endfunc sp_min_vector_table | ||
|
||
func handle_smc | ||
smcc_save_gp_mode_regs | ||
|
||
/* r0 points to smc_context */ | ||
mov r2, r0 /* handle */ | ||
ldcopr r0, SCR | ||
|
||
/* Save SCR in stack */ | ||
push {r0} | ||
and r3, r0, #SCR_NS_BIT /* flags */ | ||
|
||
/* Switch to Secure Mode*/ | ||
bic r0, #SCR_NS_BIT | ||
stcopr r0, SCR | ||
isb | ||
ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */ | ||
/* Check whether an SMC64 is issued */ | ||
tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT) | ||
beq 1f /* SMC32 is detected */ | ||
mov r0, #SMC_UNK | ||
str r0, [r2, #SMC_CTX_GPREG_R0] | ||
mov r0, r2 | ||
b 2f /* Skip handling the SMC */ | ||
1: | ||
mov r1, #0 /* cookie */ | ||
bl handle_runtime_svc | ||
2: | ||
/* r0 points to smc context */ | ||
|
||
/* Restore SCR from stack */ | ||
pop {r1} | ||
stcopr r1, SCR | ||
isb | ||
|
||
b sp_min_exit | ||
endfunc handle_smc | ||
|
||
/* | ||
* The Cold boot/Reset entrypoint for SP_MIN | ||
*/ | ||
func sp_min_entrypoint | ||
|
||
/* | ||
* The caches and TLBs are disabled at reset. If any implementation | ||
* allows the caches/TLB to be hit while they are disabled, ensure | ||
* that they are invalidated here | ||
*/ | ||
|
||
/* Make sure we are in Secure Mode*/ | ||
ldcopr r0, SCR | ||
bic r0, #SCR_NS_BIT | ||
stcopr r0, SCR | ||
isb | ||
|
||
/* Switch to monitor mode */ | ||
cps #MODE32_mon | ||
isb | ||
|
||
/* | ||
* Set sane values for NS SCTLR as well. | ||
* Switch to non secure mode for this. | ||
*/ | ||
ldr r0, =(SCTLR_RES1) | ||
ldcopr r1, SCR | ||
orr r2, r1, #SCR_NS_BIT | ||
stcopr r2, SCR | ||
isb | ||
|
||
ldcopr r2, SCTLR | ||
orr r0, r0, r2 | ||
stcopr r0, SCTLR | ||
isb | ||
|
||
stcopr r1, SCR | ||
isb | ||
|
||
/* | ||
* Set the CPU endianness before doing anything that might involve | ||
* memory reads or writes. | ||
*/ | ||
ldcopr r0, SCTLR | ||
bic r0, r0, #SCTLR_EE_BIT | ||
stcopr r0, SCTLR | ||
isb | ||
|
||
/* Run the CPU Specific Reset handler */ | ||
bl reset_handler | ||
|
||
/* | ||
* Enable the instruction cache and data access | ||
* alignment checks | ||
*/ | ||
ldcopr r0, SCTLR | ||
ldr r1, =(SCTLR_RES1 | SCTLR_A_BIT | SCTLR_I_BIT) | ||
orr r0, r0, r1 | ||
stcopr r0, SCTLR | ||
isb | ||
|
||
/* Set the vector tables */ | ||
ldr r0, =sp_min_vector_table | ||
stcopr r0, VBAR | ||
stcopr r0, MVBAR | ||
isb | ||
|
||
/* | ||
* Enable the SIF bit to disable instruction fetches | ||
* from Non-secure memory. | ||
*/ | ||
ldcopr r0, SCR | ||
orr r0, r0, #SCR_SIF_BIT | ||
stcopr r0, SCR | ||
|
||
/* | ||
* Enable the SError interrupt now that the exception vectors have been | ||
* setup. | ||
*/ | ||
cpsie a | ||
isb | ||
|
||
/* Enable access to Advanced SIMD registers */ | ||
ldcopr r0, NSACR | ||
bic r0, r0, #NSASEDIS_BIT | ||
orr r0, r0, #(NASCR_CP10_BIT | NASCR_CP11_BIT) | ||
stcopr r0, NSACR | ||
isb | ||
|
||
/* | ||
* Enable access to Advanced SIMD, Floating point and to the Trace | ||
* functionality as well. | ||
*/ | ||
ldcopr r0, CPACR | ||
bic r0, r0, #ASEDIS_BIT | ||
bic r0, r0, #TRCDIS_BIT | ||
orr r0, r0, #CPACR_ENABLE_FP_ACCESS | ||
stcopr r0, CPACR | ||
isb | ||
|
||
vmrs r0, FPEXC | ||
orr r0, r0, #FPEXC_EN_BIT | ||
vmsr FPEXC, r0 | ||
|
||
/* Detect whether Warm or Cold boot */ | ||
bl plat_get_my_entrypoint | ||
cmp r0, #0 | ||
/* If warm boot detected, jump to warm boot entry */ | ||
bxne r0 | ||
|
||
/* Setup C runtime stack */ | ||
bl plat_set_my_stack | ||
|
||
/* Perform platform specific memory initialization */ | ||
bl platform_mem_init | ||
|
||
/* Initialize the C Runtime Environment */ | ||
|
||
/* | ||
* Invalidate the RW memory used by SP_MIN image. This includes | ||
* the data and NOBITS sections. This is done to safeguard against | ||
* possible corruption of this memory by dirty cache lines in a system | ||
* cache as a result of use by an earlier boot loader stage. | ||
*/ | ||
ldr r0, =__RW_START__ | ||
ldr r1, =__RW_END__ | ||
sub r1, r1, r0 | ||
bl inv_dcache_range | ||
|
||
ldr r0, =__BSS_START__ | ||
ldr r1, =__BSS_SIZE__ | ||
bl zeromem | ||
|
||
#if USE_COHERENT_MEM | ||
ldr r0, =__COHERENT_RAM_START__ | ||
ldr r1, =__COHERENT_RAM_UNALIGNED_SIZE__ | ||
bl zeromem | ||
#endif | ||
|
||
/* Perform platform specific early arch. setup */ | ||
bl sp_min_early_platform_setup | ||
bl sp_min_plat_arch_setup | ||
|
||
/* Jump to the main function */ | ||
bl sp_min_main | ||
|
||
/* ------------------------------------------------------------- | ||
* Clean the .data & .bss sections to main memory. This ensures | ||
* that any global data which was initialised by the primary CPU | ||
* is visible to secondary CPUs before they enable their data | ||
* caches and participate in coherency. | ||
* ------------------------------------------------------------- | ||
*/ | ||
ldr r0, =__DATA_START__ | ||
ldr r1, =__DATA_END__ | ||
sub r1, r1, r0 | ||
bl clean_dcache_range | ||
|
||
ldr r0, =__BSS_START__ | ||
ldr r1, =__BSS_END__ | ||
sub r1, r1, r0 | ||
bl clean_dcache_range | ||
|
||
/* Program the registers in cpu_context and exit monitor mode */ | ||
mov r0, #NON_SECURE | ||
bl cm_get_context | ||
|
||
/* Restore the SCR */ | ||
ldr r2, [r0, #CTX_REGS_OFFSET + CTX_SCR] | ||
stcopr r2, SCR | ||
isb | ||
|
||
/* Restore the SCTLR */ | ||
ldr r2, [r0, #CTX_REGS_OFFSET + CTX_NS_SCTLR] | ||
stcopr r2, SCTLR | ||
|
||
bl smc_get_next_ctx | ||
/* The other cpu_context registers have been copied to smc context */ | ||
b sp_min_exit | ||
endfunc sp_min_entrypoint | ||
|
||
/* | ||
* The Warm boot entrypoint for SP_MIN. | ||
*/ | ||
func sp_min_warm_entrypoint | ||
|
||
/* Setup C runtime stack */ | ||
bl plat_set_my_stack | ||
|
||
/* -------------------------------------------- | ||
* Enable the MMU with the DCache disabled. It | ||
* is safe to use stacks allocated in normal | ||
* memory as a result. All memory accesses are | ||
* marked nGnRnE when the MMU is disabled. So | ||
* all the stack writes will make it to memory. | ||
* All memory accesses are marked Non-cacheable | ||
* when the MMU is enabled but D$ is disabled. | ||
* So used stack memory is guaranteed to be | ||
* visible immediately after the MMU is enabled | ||
* Enabling the DCache at the same time as the | ||
* MMU can lead to speculatively fetched and | ||
* possibly stale stack memory being read from | ||
* other caches. This can lead to coherency | ||
* issues. | ||
* -------------------------------------------- | ||
*/ | ||
mov r0, #DISABLE_DCACHE | ||
bl bl32_plat_enable_mmu | ||
|
||
bl sp_min_warm_boot | ||
|
||
/* Program the registers in cpu_context and exit monitor mode */ | ||
mov r0, #NON_SECURE | ||
bl cm_get_context | ||
|
||
/* Restore the SCR */ | ||
ldr r2, [r0, #CTX_REGS_OFFSET + CTX_SCR] | ||
stcopr r2, SCR | ||
isb | ||
|
||
/* Restore the SCTLR */ | ||
ldr r2, [r0, #CTX_REGS_OFFSET + CTX_NS_SCTLR] | ||
stcopr r2, SCTLR | ||
|
||
bl smc_get_next_ctx | ||
|
||
/* The other cpu_context registers have been copied to smc context */ | ||
b sp_min_exit | ||
endfunc sp_min_warm_entrypoint | ||
|
||
/* | ||
* The function to restore the registers from SMC context and return | ||
* to the mode restored to SPSR. | ||
* | ||
* Arguments : r0 must point to the SMC context to restore from. | ||
*/ | ||
func sp_min_exit | ||
smcc_restore_gp_mode_regs | ||
eret | ||
endfunc sp_min_exit |
Oops, something went wrong.