zephyr/arch/arm64/core/reset.S
Yong Cong Sin bbe5e1e6eb build: namespace the generated headers with zephyr/
Namespaced the generated headers with `zephyr` to prevent
potential conflict with other headers.

Introduce a temporary Kconfig `LEGACY_GENERATED_INCLUDE_PATH`
that is enabled by default. This allows the developers to
continue the use of the old include paths for the time being
until it is deprecated and eventually removed. The Kconfig will
generate a build-time warning message, similar to the
`CONFIG_TIMER_RANDOM_GENERATOR`.

Updated the includes path of in-tree sources accordingly.

Most of the changes here are scripted, check the PR for more
info.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
2024-05-28 22:03:55 +02:00

256 lines
5 KiB
ArmAsm

/*
* Copyright (c) 2019 Carlo Caione <ccaione@baylibre.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/offsets.h>
#include "boot.h"
#include "macro_priv.inc"
_ASM_FILE_PROLOGUE
/*
* Platform specific pre-C init code
*
* Note: - Stack is not yet available
* - x23, x24 and x25 must be preserved
*/
WTEXT(z_arm64_el3_plat_prep_c)
SECTION_FUNC(TEXT,z_arm64_el3_plat_prep_c)
ret
WTEXT(z_arm64_el2_plat_prep_c)
SECTION_FUNC(TEXT,z_arm64_el2_plat_prep_c)
ret
WTEXT(z_arm64_el1_plat_prep_c)
SECTION_FUNC(TEXT,z_arm64_el1_plat_prep_c)
ret
/*
* Set the minimum necessary to safely call C code
*/
GTEXT(__reset_prep_c)
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset_prep_c)
/* return address: x23 */
mov x23, lr
switch_el x0, 3f, 2f, 1f
3:
#if !defined(CONFIG_ARMV8_R)
/* Reinitialize SCTLR from scratch in EL3 */
ldr w0, =(SCTLR_EL3_RES1 | SCTLR_I_BIT | SCTLR_SA_BIT)
msr sctlr_el3, x0
isb
/* Custom plat prep_c init */
bl z_arm64_el3_plat_prep_c
/* Set SP_EL1 */
msr sp_el1, x24
b out
#endif /* CONFIG_ARMV8_R */
2:
/* Disable alignment fault checking */
mrs x0, sctlr_el2
bic x0, x0, SCTLR_A_BIT
msr sctlr_el2, x0
isb
/* Custom plat prep_c init */
bl z_arm64_el2_plat_prep_c
/* Set SP_EL1 */
msr sp_el1, x24
b out
1:
/* Disable alignment fault checking */
mrs x0, sctlr_el1
bic x0, x0, SCTLR_A_BIT
msr sctlr_el1, x0
isb
/* Custom plat prep_c init */
bl z_arm64_el1_plat_prep_c
/* Set SP_EL1. We cannot use sp_el1 at EL1 */
msr SPSel, #1
mov sp, x24
out:
isb
/* Select SP_EL0 */
msr SPSel, #0
/* Initialize stack */
mov sp, x24
/* fp = NULL */
mov fp, xzr
ret x23
/*
* Reset vector
*
* Ran when the system comes out of reset. The processor is in thread mode with
* privileged level. At this point, neither SP_EL0 nor SP_ELx point to a valid
* area in SRAM.
*/
GTEXT(__reset)
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset)
GTEXT(__start)
SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
#ifdef CONFIG_WAIT_AT_RESET_VECTOR
resetwait:
wfe
b resetwait
#endif
/* Mask all exceptions */
msr DAIFSet, #0xf
#if CONFIG_MP_MAX_NUM_CPUS > 1
/*
* Deal with multi core booting simultaneously to race for being the primary core.
* Use voting lock[1] with reasonable but minimal requirements on the memory system
* to make sure only one core wins at last.
*
* [1] kernel.org/doc/html/next/arch/arm/vlocks.html
*/
ldr x0, =arm64_cpu_boot_params
/*
* Get the "logic" id defined by cpu_node_list statically for voting lock self-identify.
* It is worth noting that this is NOT the final logic id (arch_curr_cpu()->id)
*/
get_cpu_logic_id x1, x2, x3, x4 //x1: MPID, x2: logic id
add x4, x0, #BOOT_PARAM_VOTING_OFFSET
/* signal our desire to vote */
mov w5, #1
strb w5, [x4, x2]
ldr x3, [x0, #BOOT_PARAM_MPID_OFFSET]
cmn x3, #1
beq 1f
/* some core already won, release */
strb wzr, [x4, x2]
b secondary_core
/* suggest current core then release */
1: str x1, [x0, #BOOT_PARAM_MPID_OFFSET]
strb wzr, [x4, x2]
dmb ish
/* then wait until every core else is done voting */
mov x5, #0
2: ldrb w3, [x4, x5]
tst w3, #255
/* wait */
bne 2b
add x5, x5, #1
cmp x5, #CONFIG_MP_MAX_NUM_CPUS
bne 2b
/* check if current core won */
dmb ish
ldr x3, [x0, #BOOT_PARAM_MPID_OFFSET]
cmp x3, x1
beq primary_core
/* fallthrough secondary */
/* loop until our turn comes */
secondary_core:
dmb ish
ldr x2, [x0, #BOOT_PARAM_MPID_OFFSET]
cmp x1, x2
bne secondary_core
/* we can now load our stack pointer value and move on */
ldr x24, [x0, #BOOT_PARAM_SP_OFFSET]
ldr x25, =z_arm64_secondary_prep_c
b boot
primary_core:
#endif
/* load primary stack and entry point */
ldr x24, =(z_interrupt_stacks + __z_interrupt_stack_SIZEOF)
ldr x25, =z_prep_c
boot:
/* Prepare for calling C code */
bl __reset_prep_c
/*
* Initialize the interrupt stack with 0xaa so stack utilization
* can be measured. This needs to be done before using the stack
* so that we don't clobber any data.
*/
#ifdef CONFIG_INIT_STACKS
mov_imm x0, CONFIG_ISR_STACK_SIZE
sub x0, sp, x0
sub x9, sp, #8
mov x10, 0xaaaaaaaaaaaaaaaa
stack_init_loop:
cmp x0, x9
beq stack_init_done
str x10, [x0], #8
b stack_init_loop
stack_init_done:
#endif
/* Platform hook for highest EL */
bl z_arm64_el_highest_init
switch_el:
switch_el x0, 3f, 2f, 1f
3:
#if !defined(CONFIG_ARMV8_R)
/* EL3 init */
bl z_arm64_el3_init
/* Get next EL */
adr x0, switch_el
bl z_arm64_el3_get_next_el
eret
#endif /* CONFIG_ARMV8_R */
2:
/* EL2 init */
bl z_arm64_el2_init
/* Move to EL1 with all exceptions masked */
mov_imm x0, (SPSR_DAIF_MASK | SPSR_MODE_EL1T)
msr spsr_el2, x0
adr x0, 1f
msr elr_el2, x0
eret
1:
/* EL1 init */
bl z_arm64_el1_init
/* We want to use SP_ELx from now on */
msr SPSel, #1
/* Enable SError interrupts */
msr DAIFClr, #(DAIFCLR_ABT_BIT)
isb
ret x25 /* either z_prep_c or z_arm64_secondary_prep_c */