[boot-wrapper PATCH v2 8/8] aarch64: Introduce EL2 boot code for Armv8-R AArch64
Jaxson Han
jaxson.han at arm.com
Fri May 21 03:48:07 PDT 2021
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.
Signed-off-by: Jaxson Han <jaxson.han at arm.com>
---
arch/aarch64/boot.S | 87 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 85 insertions(+), 2 deletions(-)
diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S
index 14fd9cf..0339e19 100644
--- a/arch/aarch64/boot.S
+++ b/arch/aarch64/boot.S
@@ -25,16 +25,24 @@ _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
- beq 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]
@@ -127,6 +135,80 @@ 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, goto keep_el.
+ */
+ 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. */
+ bne 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
+
+ mrs x1, id_aa64pfr0_el1
+ ubfx x2, x1, #56, 4
+ cmp x2, 0x2
+ bne 1f
+ /*
+ * Disable trap when accessing SCTXNUM_EL0 or SCTXNUM_EL1
+ * if FEAT_CSV2.
+ */
+ orr x0, x0, #(1 << 53) // EnSCXT
+
+1: ubfx x2, x1, #28, 4
+ cmp x2, 0x2
+ bne 1f
+ /* Disable trap when accessing ERXPFGCDN_EL1 if FEAT_RASv1p1. */
+ orr x0, x0, #(1 << 47) // 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) // APK
+ orr x0, x0, #(1 << 41) // 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, =CNTFRQ
msr cntfrq_el0, x0
@@ -136,6 +218,7 @@ el_max_init:
b start_el_max
err_invalid_id:
+err_invalid_arch:
b .
/*
--
2.25.1
More information about the linux-arm-kernel
mailing list