diff options
Diffstat (limited to 'meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch')
-rw-r--r-- | meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch new file mode 100644 index 0000000000..aaacc72945 --- /dev/null +++ b/meta-arm/meta-arm-bsp/recipes-bsp/boot-wrapper-aarch64/files/fvp-baser-aemv8r64/0006-aarch64-Introduce-EL2-boot-code-for-Armv8-R-AArch64.patch @@ -0,0 +1,182 @@ +From 81df76f8d94cb6c31c01739b078a72bdb8497441 Mon Sep 17 00:00:00 2001 +From: Jaxson Han <jaxson.han@arm.com> +Date: Tue, 25 May 2021 07:25:00 +0100 +Subject: [PATCH] aarch64: Introduce EL2 boot code for Armv8-R AArch64 + +The Armv8-R AArch64 profile does not support the EL3 exception level. +The Armv8-R AArch64 profile allows for an (optional) VMSAv8-64 MMU +at EL1, which allows to run off-the-shelf Linux. However EL2 only +supports a PMSA, which is not supported by Linux, so we need to drop +into EL1 before entering the kernel. + +We add a new err_invalid_arch symbol as a dead loop. If we detect the +current Armv8-R aarch64 only supports with PMSA, meaning we cannot boot +Linux anymore, then we jump to err_invalid_arch. + +During Armv8-R aarch64 init, to make sure nothing unexpected traps into +EL2, we auto-detect and config FIEN and EnSCXT in HCR_EL2. + +The boot sequence is: +If CurrentEL == EL3, then goto EL3 initialisation and drop to lower EL + before entering the kernel. +If CurrentEL == EL2 && id_aa64mmfr0_el1.MSA == 0xf (Armv8-R aarch64), + if id_aa64mmfr0_el1.MSA_frac == 0x2, + then goto Armv8-R AArch64 initialisation and drop to EL1 before + entering the kernel. + else, which means VMSA unsupported and cannot boot Linux, + goto err_invalid_arch (dead loop). +Else, no initialisation and keep the current EL before entering the + kernel. + +Upstream-Status: Pending +Signed-off-by: Jaxson Han <jaxson.han@arm.com> +--- + arch/aarch64/boot.S | 92 +++++++++++++++++++++++++++++++++- + arch/aarch64/include/asm/cpu.h | 2 + + 2 files changed, 92 insertions(+), 2 deletions(-) + +diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S +index 908764a..def9192 100644 +--- a/arch/aarch64/boot.S ++++ b/arch/aarch64/boot.S +@@ -24,16 +24,24 @@ ASM_FUNC(_start) + * Boot sequence + * If CurrentEL == EL3, then goto EL3 initialisation and drop to + * lower EL before entering the kernel. ++ * If CurrentEL == EL2 && id_aa64mmfr0_el1.MSA == 0xf, then ++ * If id_aa64mmfr0_el1.MSA_frac == 0x2, then goto ++ * Armv8-R AArch64 initialisation and drop to EL1 before ++ * entering the kernel. ++ * Else, which means VMSA unsupported and cannot boot Linux, ++ * goto err_invalid_arch (dead loop). + * Else, no initialisation and keep the current EL before + * entering the kernel. + */ + mrs x0, CurrentEL +- cmp x0, #CURRENTEL_EL3 +- b.eq el3_init ++ cmp x0, #CURRENTEL_EL2 ++ bgt el3_init ++ beq el2_init + + /* + * We stay in the current EL for entering the kernel + */ ++keep_el: + mov w0, #1 + ldr x1, =flag_keep_el + str w0, [x1] +@@ -139,6 +147,85 @@ el3_init: + str w0, [x1] + b el_max_init + ++ /* ++ * EL2 Armv8-R AArch64 initialisation ++ */ ++el2_init: ++ /* Detect Armv8-R AArch64 */ ++ mrs x1, id_aa64mmfr0_el1 ++ /* ++ * Check MSA, bits [51:48]: ++ * 0xf means Armv8-R AArch64. ++ * If not 0xf, proceed in Armv8-A EL2. ++ */ ++ ubfx x0, x1, #48, #4 // MSA ++ cmp x0, 0xf ++ bne keep_el ++ /* ++ * Check MSA_frac, bits [55:52]: ++ * 0x2 means EL1&0 translation regime also supports VMSAv8-64. ++ */ ++ ubfx x0, x1, #52, #4 // MSA_frac ++ cmp x0, 0x2 ++ /* ++ * If not 0x2, no VMSA, so cannot boot Linux and dead loop. ++ * Also, since the architecture guarantees that those CPUID ++ * fields never lose features when the value in a field ++ * increases, we use blt to cover it. ++ */ ++ blt err_invalid_arch ++ ++ mrs x0, midr_el1 ++ msr vpidr_el2, x0 ++ ++ mrs x0, mpidr_el1 ++ msr vmpidr_el2, x0 ++ ++ mov x0, #(1 << 31) // VTCR_MSA: VMSAv8-64 support ++ msr vtcr_el2, x0 ++ ++ /* Init HCR_EL2 */ ++ mov x0, #(1 << 31) // RES1: Armv8-R aarch64 only ++ ++ mrs x1, id_aa64pfr0_el1 ++ ubfx x2, x1, #56, 4 // ID_AA64PFR0_EL1.CSV2 ++ cmp x2, 0x2 ++ b.lt 1f ++ /* ++ * Disable trap when accessing SCTXNUM_EL0 or SCTXNUM_EL1 ++ * if FEAT_CSV2. ++ */ ++ orr x0, x0, #(1 << 53) // HCR_EL2.EnSCXT ++ ++1: ubfx x2, x1, #28, 4 // ID_AA64PFR0_EL1.RAS ++ cmp x2, 0x2 ++ b.lt 1f ++ /* Disable trap when accessing ERXPFGCDN_EL1 if FEAT_RASv1p1. */ ++ orr x0, x0, #(1 << 47) // HCR_EL2.FIEN ++ ++ /* Enable pointer authentication if present */ ++1: mrs x1, id_aa64isar1_el1 ++ /* ++ * If ID_AA64ISAR1_EL1.{GPI, GPA, API, APA} == {0000, 0000, 0000, 0000} ++ * then HCR_EL2.APK and HCR_EL2.API are RES 0. ++ * Else ++ * set HCR_EL2.APK and HCR_EL2.API. ++ */ ++ ldr x2, =(((0xff) << 24) | (0xff << 4)) ++ and x1, x1, x2 ++ cbz x1, 1f ++ ++ orr x0, x0, #(1 << 40) // HCR_EL2.APK ++ orr x0, x0, #(1 << 41) // HCR_EL2.API ++ ++1: msr hcr_el2, x0 ++ isb ++ ++ mov w0, #SPSR_KERNEL_EL1 ++ ldr x1, =spsr_to_elx ++ str w0, [x1] ++ // fall through ++ + el_max_init: + ldr x0, =COUNTER_FREQ + msr cntfrq_el0, x0 +@@ -148,6 +235,7 @@ el_max_init: + b start_el_max + + err_invalid_id: ++err_invalid_arch: + b . + + /* +diff --git a/arch/aarch64/include/asm/cpu.h b/arch/aarch64/include/asm/cpu.h +index b1003f4..91f803c 100644 +--- a/arch/aarch64/include/asm/cpu.h ++++ b/arch/aarch64/include/asm/cpu.h +@@ -25,6 +25,7 @@ + #define SPSR_I (1 << 7) /* IRQ masked */ + #define SPSR_F (1 << 6) /* FIQ masked */ + #define SPSR_T (1 << 5) /* Thumb */ ++#define SPSR_EL1H (5 << 0) /* EL1 Handler mode */ + #define SPSR_EL2H (9 << 0) /* EL2 Handler mode */ + #define SPSR_HYP (0x1a << 0) /* M[3:0] = hyp, M[4] = AArch32 */ + +@@ -43,6 +44,7 @@ + #else + #define SCTLR_EL1_KERNEL SCTLR_EL1_RES1 + #define SPSR_KERNEL (SPSR_A | SPSR_D | SPSR_I | SPSR_F | SPSR_EL2H) ++#define SPSR_KERNEL_EL1 (SPSR_A | SPSR_D | SPSR_I | SPSR_F | SPSR_EL1H) + #endif + + #ifndef __ASSEMBLY__ |