diff options
author | Julius Werner <jwerner@chromium.org> | 2015-10-12 16:45:21 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2015-11-16 21:53:43 +0100 |
commit | 66a476ad5f29553ad7c46e58eb35faa7a059a5af (patch) | |
tree | 2fcb80dc3cc7f578d20d04952641192dcccf4ad1 /src/arch/arm64/armv8/cpu.S | |
parent | 29016ea3b4350d8c9ed5fad8dff7707ecbb21127 (diff) |
arm64: Implement generic stage transitions for non-Tegra SoCs
The existing arm64 architecture code has been developed for the Tegra132
and Tegra210 SoCs, which only start their ARM64 cores in ramstage. It
interweaves the stage entry point with code that initializes a CPU (and
should not be run again if that CPU already ran a previous stage). It
also still contains some vestiges of SMP/secmon support (such as setting
up stacks in the BSS instead of using the stage-peristent one from
memlayout).
This patch splits those functions apart and makes the code layout
similar to how things work on ARM32. The default stage_entry() symbol is
a no-op wrapper that just calls main() for the current stage, for the
normal case where a stage ran on the same core as the last one. It can
be overridden by SoC code to support special cases like Tegra.
The CPU initialization code is split out into armv8/cpu.S (similar to
what arm_init_caches() does for ARM32) and called by the default
bootblock entry code. SoCs where a CPU starts up in a later stage can
call the same code from a stage_entry() override instead.
The Tegra132 and Tegra210 code is not touched by this patch to make it
easier to review and validate. A follow-up patch will bring those SoCs
in line with the model.
BRANCH=None
BUG=None
TEST=Booted Oak with a single mmu_init()/mmu_enable(). Built Ryu and
Smaug.
Change-Id: I28302a6ace47e8ab7a736e089f64922cef1a2f93
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: http://review.coreboot.org/12077
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/arch/arm64/armv8/cpu.S')
-rw-r--r-- | src/arch/arm64/armv8/cpu.S | 62 |
1 files changed, 27 insertions, 35 deletions
diff --git a/src/arch/arm64/armv8/cpu.S b/src/arch/arm64/armv8/cpu.S index c248cb3a81..4713ca59f9 100644 --- a/src/arch/arm64/armv8/cpu.S +++ b/src/arch/arm64/armv8/cpu.S @@ -19,27 +19,40 @@ /* * Bring an ARMv8 processor we just gained control of (e.g. from IROM) into a - * known state regarding caches/SCTLR. Completely cleans and invalidates + * known state regarding caches/SCTLR/PSTATE. Completely cleans and invalidates * icache/dcache, disables MMU and dcache (if active), and enables unaligned - * accesses, icache and branch prediction (if inactive). Clobbers x4 and x5. + * accesses, icache and branch prediction (if inactive). Clobbers R22 and R23. */ -ENTRY(arm_init_caches) - /* w4: SCTLR, return address: x8 (stay valid for the whole function) */ - mov x8, x30 - /* XXX: Assume that we always start running at EL3 */ - mrs x4, sctlr_el3 +ENTRY(arm64_init_cpu) + /* Initialize PSTATE (unmask all exceptions, select SP_EL0). */ + msr SPSel, #0 + msr DAIFClr, #0xf - /* FIXME: How to enable branch prediction on ARMv8? */ + /* TODO: This is where we'd put non-boot CPUs into WFI if needed. */ + + /* x22: SCTLR, return address: x23 (callee-saved by subroutine) */ + mov x23, x30 + /* TODO: Assert that we always start running at EL3 */ + mrs x22, sctlr_el3 + + /* Activate ICache (12) already for speed during cache flush below. */ + orr x22, x22, #(1 << 12) + msr sctlr_el3, x22 + isb /* Flush and invalidate dcache */ mov x0, #DCCISW bl flush_dcache_all /* Deactivate MMU (0), Alignment Check (1) and DCache (2) */ - and x4, x4, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2) - /* Activate ICache (12) already for speed */ - orr x4, x4, #(1 << 12) - msr sctlr_el3, x4 + and x22, x22, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2) + /* Activate Stack Alignment (3) because why not */ + orr x22, x22, #(1 << 3) + /* Set to little-endian (25) */ + and x22, x22, # ~(1 << 25) + /* Deactivate write-xor-execute enforcement (19) */ + and x22, x22, # ~(1 << 19) + msr sctlr_el3, x22 /* Invalidate icache and TLB for good measure */ ic iallu @@ -47,26 +60,5 @@ ENTRY(arm_init_caches) dsb sy isb - ret x8 -ENDPROC(arm_init_caches) - -/* Based on u-boot transition.S */ -ENTRY(switch_el3_to_el2) - mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */ - msr scr_el3, x0 - msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */ - mov x0, #0x33ff - msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ - - /* Return to the EL2_SP2 mode from EL3 */ - mov x0, sp - msr sp_el2, x0 /* Migrate SP */ - mrs x0, vbar_el3 - msr vbar_el2, x0 /* Migrate VBAR */ - mrs x0, sctlr_el3 - msr sctlr_el2, x0 /* Migrate SCTLR */ - mov x0, #0x3c9 - msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */ - msr elr_el3, x30 - eret -ENDPROC(switch_el3_to_el2) + ret x23 +ENDPROC(arm64_init_cpu) |