[PATCH v2] armv8: Handle EL2 Host mode

On implementations that support VHE, the layout of the CPTR_EL2 register depends on whether HCR_EL2.E2H is set. Check this bit and and set the aprropriate bits to enable access to the FP/SIMD registers. This allows U-Boot to run on systems that pass control to U-Boot in EL2 with EL2 Host mode enabled such as machine with Apple's M1 SoC.
Signed-off-by: Mark Kettenis kettenis@openbsd.org ---
v2: rename label
arch/arm/cpu/armv8/start.S | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 662449156b..979dcfef35 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -133,9 +133,15 @@ pie_fixup_done: #endif b 0f 2: set_vbar vbar_el2, x0 + mrs x0, hcr_el2 + tbnz x0, #34, el2_vhe /* HCR_EL2.E2H */ mov x0, #0x33ff msr cptr_el2, x0 /* Enable FP/SIMD */ b 0f +el2_vhe: + mov x0, #3 << 20 + msr cptr_el2, x0 /* Enable FP/SIMD */ + b 0f 1: set_vbar vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */

On Sat, 30 Jan 2021 22:31:06 +0100 Mark Kettenis kettenis@openbsd.org wrote:
Hi,
On implementations that support VHE, the layout of the CPTR_EL2 register depends on whether HCR_EL2.E2H is set. Check this bit and and set the aprropriate bits to enable access to the FP/SIMD registers. This allows U-Boot to run on systems that pass control to U-Boot in EL2 with EL2 Host mode enabled such as machine with Apple's M1 SoC.
Signed-off-by: Mark Kettenis kettenis@openbsd.org
Reviewed-by: Andre Przywara andre.przywara@arm.com
So architecturally this is correct, but I was wondering why you would actually need this? I gave this a quick spin in QEMU (-cpu max), hacking E2H to 1 very early in start.S. However loading and executing the Linux kernel was fine even without this patch, so did you observe an actual problem? Any kernel entered in EL2 would probably take care of the E2H bit and CPTR itself (Linux sets E2H, FreeBSD clears it), so is (your?) U-Boot actually using SIMD or VFP instructions itself?
Cheers, Andre.
v2: rename label
arch/arm/cpu/armv8/start.S | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 662449156b..979dcfef35 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -133,9 +133,15 @@ pie_fixup_done: #endif b 0f 2: set_vbar vbar_el2, x0
- mrs x0, hcr_el2
- tbnz x0, #34, el2_vhe /* HCR_EL2.E2H */ mov x0, #0x33ff msr cptr_el2, x0 /* Enable FP/SIMD */ b 0f
+el2_vhe:
- mov x0, #3 << 20
- msr cptr_el2, x0 /* Enable FP/SIMD */
- b 0f
1: set_vbar vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */

Date: Sun, 31 Jan 2021 16:29:21 +0000 From: Andre Przywara andre.przywara@arm.com
On Sat, 30 Jan 2021 22:31:06 +0100 Mark Kettenis kettenis@openbsd.org wrote:
Hi,
On implementations that support VHE, the layout of the CPTR_EL2 register depends on whether HCR_EL2.E2H is set. Check this bit and and set the aprropriate bits to enable access to the FP/SIMD registers. This allows U-Boot to run on systems that pass control to U-Boot in EL2 with EL2 Host mode enabled such as machine with Apple's M1 SoC.
Signed-off-by: Mark Kettenis kettenis@openbsd.org
Reviewed-by: Andre Przywara andre.przywara@arm.com
So architecturally this is correct, but I was wondering why you would actually need this? I gave this a quick spin in QEMU (-cpu max), hacking E2H to 1 very early in start.S. However loading and executing the Linux kernel was fine even without this patch, so did you observe an actual problem? Any kernel entered in EL2 would probably take care of the E2H bit and CPTR itself (Linux sets E2H, FreeBSD clears it), so is (your?) U-Boot actually using SIMD or VFP instructions itself?
Not explicitly. The problem I ran into was that snprintf() was trying to save q0-q7 to the stack. Compiling with -mgeneral-regs-only fixed that issue, but since armv8/start.S explicitly enables the FPU I concluded that someone deliberately chose to allow for SIMD and VFP in U-Boot.
If we were to revisit that decision, we could save a few bytes I guess...
Cheers,
Mark
v2: rename label
arch/arm/cpu/armv8/start.S | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 662449156b..979dcfef35 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -133,9 +133,15 @@ pie_fixup_done: #endif b 0f 2: set_vbar vbar_el2, x0
- mrs x0, hcr_el2
- tbnz x0, #34, el2_vhe /* HCR_EL2.E2H */ mov x0, #0x33ff msr cptr_el2, x0 /* Enable FP/SIMD */ b 0f
+el2_vhe:
- mov x0, #3 << 20
- msr cptr_el2, x0 /* Enable FP/SIMD */
- b 0f
1: set_vbar vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */
participants (3)
-
Andre Przywara
-
Mark Kettenis
-
Mark Kettenis