/* * 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 #include #include #include #include #include #include #include .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