Skip to content

Commit ca88ecd

Browse files
author
Marc Zyngier
committed
arm64: Revamp HCR_EL2.E2H RES1 detection
We currently have two ways to identify CPUs that only implement FEAT_VHE and not FEAT_E2H0: - either they advertise it via ID_AA64MMFR4_EL1.E2H0, - or the HCR_EL2.E2H bit is RAO/WI However, there is a third category of "cpus" that fall between these two cases: on CPUs that do not implement FEAT_FGT, it is IMPDEF whether an access to ID_AA64MMFR4_EL1 can trap to EL2 when the register value is zero. A consequence of this is that on systems such as Neoverse V2, a NV guest cannot reliably detect that it is in a VHE-only configuration (E2H is writable, and ID_AA64MMFR0_EL1 is 0), despite the hypervisor's best effort to repaint the id register. Replace the RAO/WI test by a sequence that makes use of the VHE register remnapping between EL1 and EL2 to detect this situation, and work out whether we get the VHE behaviour even after having set HCR_EL2.E2H to 0. This solves the NV problem, and provides a more reliable acid test for CPUs that do not completely follow the letter of the architecture while providing a RES1 behaviour for HCR_EL2.E2H. Suggested-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Tested-by: Jan Kotas <jank@cadence.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/15A85F2B-1A0C-4FA7-9FE4-EEC2203CC09E@global.cadence.com
1 parent e0b5a79 commit ca88ecd

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

arch/arm64/include/asm/el2_setup.h

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,48 @@
2424
* ID_AA64MMFR4_EL1.E2H0 < 0. On such CPUs HCR_EL2.E2H is RES1, but it
2525
* can reset into an UNKNOWN state and might not read as 1 until it has
2626
* been initialized explicitly.
27-
*
28-
* Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but
29-
* don't advertise it (they predate this relaxation).
30-
*
3127
* Initalize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H
3228
* indicating whether the CPU is running in E2H mode.
3329
*/
3430
mrs_s x1, SYS_ID_AA64MMFR4_EL1
3531
sbfx x1, x1, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH
3632
cmp x1, #0
37-
b.ge .LnVHE_\@
33+
b.lt .LnE2H0_\@
3834

35+
/*
36+
* Unfortunately, HCR_EL2.E2H can be RES1 even if not advertised
37+
* as such via ID_AA64MMFR4_EL1.E2H0:
38+
*
39+
* - Fruity CPUs predate the !FEAT_E2H0 relaxation, and seem to
40+
* have HCR_EL2.E2H implemented as RAO/WI.
41+
*
42+
* - On CPUs that lack FEAT_FGT, a hypervisor can't trap guest
43+
* reads of ID_AA64MMFR4_EL1 to advertise !FEAT_E2H0. NV
44+
* guests on these hosts can write to HCR_EL2.E2H without
45+
* trapping to the hypervisor, but these writes have no
46+
* functional effect.
47+
*
48+
* Handle both cases by checking for an essential VHE property
49+
* (system register remapping) to decide whether we're
50+
* effectively VHE-only or not.
51+
*/
52+
msr_hcr_el2 x0 // Setup HCR_EL2 as nVHE
53+
isb
54+
mov x1, #1 // Write something to FAR_EL1
55+
msr far_el1, x1
56+
isb
57+
mov x1, #2 // Try to overwrite it via FAR_EL2
58+
msr far_el2, x1
59+
isb
60+
mrs x1, far_el1 // If we see the latest write in FAR_EL1,
61+
cmp x1, #2 // we can safely assume we are VHE only.
62+
b.ne .LnVHE_\@ // Otherwise, we know that nVHE works.
63+
64+
.LnE2H0_\@:
3965
orr x0, x0, #HCR_E2H
40-
.LnVHE_\@:
4166
msr_hcr_el2 x0
4267
isb
68+
.LnVHE_\@:
4369
.endm
4470

4571
.macro __init_el2_sctlr

0 commit comments

Comments
 (0)