/* * Copyright (c) 2015, 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. */ #ifndef __EL3_COMMON_MACROS_S__ #define __EL3_COMMON_MACROS_S__ #include #include /* * Helper macro to initialise EL3 registers we care about. */ .macro el3_arch_init_common _exception_vectors /* --------------------------------------------------------------------- * Enable the instruction cache, stack pointer and data access alignment * checks * --------------------------------------------------------------------- */ mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) mrs x0, sctlr_el3 orr x0, x0, x1 msr sctlr_el3, x0 isb #if IMAGE_BL31 /* --------------------------------------------------------------------- * Initialise the per-cpu cache pointer to the CPU. * This is done early to enable crash reporting to have access to crash * stack. Since crash reporting depends on cpu_data to report the * unhandled exception, not doing so can lead to recursive exceptions * due to a NULL TPIDR_EL3. * --------------------------------------------------------------------- */ bl init_cpu_data_ptr #endif /* IMAGE_BL31 */ /* --------------------------------------------------------------------- * Set the exception vectors. * --------------------------------------------------------------------- */ adr x0, \_exception_vectors msr vbar_el3, x0 isb /* --------------------------------------------------------------------- * Enable the SError interrupt now that the exception vectors have been * setup. * --------------------------------------------------------------------- */ msr daifclr, #DAIF_ABT_BIT /* --------------------------------------------------------------------- * The initial state of the Architectural feature trap register * (CPTR_EL3) is unknown and it must be set to a known state. All * feature traps are disabled. Some bits in this register are marked as * reserved and should not be modified. * * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1 * or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2. * * CPTR_EL3.TTA: This causes access to the Trace functionality to trap * to EL3 when executed from EL0, EL1, EL2, or EL3. If system register * access to trace functionality is not supported, this bit is RES0. * * CPTR_EL3.TFP: This causes instructions that access the registers * associated with Floating Point and Advanced SIMD execution to trap * to EL3 when executed from any exception level, unless trapped to EL1 * or EL2. * --------------------------------------------------------------------- */ mrs x0, cptr_el3 bic w0, w0, #TCPAC_BIT bic w0, w0, #TTA_BIT bic w0, w0, #TFP_BIT msr cptr_el3, x0 .endm /* ----------------------------------------------------------------------------- * This is the super set of actions that need to be performed during a cold boot * or a warm boot in EL3. This code is shared by BL1 and BL3-1. * * This macro will always perform reset handling, architectural initialisations * and stack setup. The rest of the actions are optional because they might not * be needed, depending on the context in which this macro is called. This is * why this macro is parameterised ; each parameter allows to enable/disable * some actions. * * _set_endian: * Whether the macro needs to configure the endianness of data accesses. * * _warm_boot_mailbox: * Whether the macro needs to detect the type of boot (cold/warm). The * detection is based on the platform entrypoint address : if it is zero * then it is a cold boot, otherwise it is a warm boot. In the latter case, * this macro jumps on the platform entrypoint address. * * _secondary_cold_boot: * Whether the macro needs to identify the CPU that is calling it: primary * CPU or secondary CPU. The primary CPU will be allowed to carry on with * the platform initialisations, while the secondaries will be put in a * platform-specific state in the meantime. * * If the caller knows this macro will only be called by the primary CPU * then this parameter can be defined to 0 to skip this step. * * _init_memory: * Whether the macro needs to initialise the memory. * * _init_c_runtime: * Whether the macro needs to initialise the C runtime environment. * * _exception_vectors: * Address of the exception vectors to program in the VBAR_EL3 register. * ----------------------------------------------------------------------------- */ .macro el3_entrypoint_common \ _set_endian, _warm_boot_mailbox, _secondary_cold_boot, \ _init_memory, _init_c_runtime, _exception_vectors .if \_set_endian /* ------------------------------------------------------------- * Set the CPU endianness before doing anything that might * involve memory reads or writes. * ------------------------------------------------------------- */ mrs x0, sctlr_el3 bic x0, x0, #SCTLR_EE_BIT msr sctlr_el3, x0 isb .endif /* _set_endian */ .if \_warm_boot_mailbox /* ------------------------------------------------------------- * This code will be executed for both warm and cold resets. * Now is the time to distinguish between the two. * Query the platform entrypoint address and if it is not zero * then it means it is a warm boot so jump to this address. * ------------------------------------------------------------- */ bl plat_get_my_entrypoint cbz x0, do_cold_boot br x0 do_cold_boot: .endif /* _warm_boot_mailbox */ .if \_secondary_cold_boot /* ------------------------------------------------------------- * It is a cold boot. * The primary CPU will set up the platform while the * secondaries are placed in a platform-specific state until the * primary CPU performs the necessary actions to bring them out * of that state and allows entry into the OS. * ------------------------------------------------------------- */ bl plat_is_my_cpu_primary cbnz x0, do_primary_cold_boot /* This is a cold boot on a secondary CPU */ bl plat_secondary_cold_boot_setup /* plat_secondary_cold_boot_setup() is not supposed to return */ secondary_panic: b secondary_panic do_primary_cold_boot: .endif /* _secondary_cold_boot */ /* --------------------------------------------------------------------- * Perform any processor specific actions upon reset e.g. cache, TLB * invalidations etc. * --------------------------------------------------------------------- */ bl reset_handler el3_arch_init_common \_exception_vectors .if \_init_memory bl platform_mem_init .endif /* _init_memory */ /* --------------------------------------------------------------------- * Init C runtime environment: * - Zero-initialise the NOBITS sections. There are 2 of them: * - the .bss section; * - the coherent memory section (if any). * - Relocate the data section from ROM to RAM, if required. * --------------------------------------------------------------------- */ .if \_init_c_runtime ldr x0, =__BSS_START__ ldr x1, =__BSS_SIZE__ bl zeromem16 #if USE_COHERENT_MEM ldr x0, =__COHERENT_RAM_START__ ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__ bl zeromem16 #endif #if IMAGE_BL1 ldr x0, =__DATA_RAM_START__ ldr x1, =__DATA_ROM_START__ ldr x2, =__DATA_SIZE__ bl memcpy16 #endif .endif /* _init_c_runtime */ #if IMAGE_BL31 /* --------------------------------------------------------------------- * Use SP_EL0 for the C runtime stack. * --------------------------------------------------------------------- */ msr spsel, #0 #endif /* IMAGE_BL31 */ /* --------------------------------------------------------------------- * Allocate a stack whose memory will be marked as Normal-IS-WBWA when * the MMU is enabled. There is no risk of reading stale stack memory * after enabling the MMU as only the primary CPU is running at the * moment. * --------------------------------------------------------------------- */ bl plat_set_my_stack .endm #endif /* __EL3_COMMON_MACROS_S__ */