[PATCH 12/20] KVM: arm64: Add RESx_WHEN_E2Hx constraints as configuration flags

Marc Zyngier maz at kernel.org
Mon Jan 26 04:16:46 PST 2026


"Thanks" to VHE, SCTLR_EL2 radically changes shape depending on the
value of HCR_EL2.E2H, as a lot of the bits that didn't have much
meaning with E2H=0 start impacting EL0 with E2H=1.

This has a direct impact on the RESx behaviour of these bits, and
we need a way to express them.

For this purpose, introduce a set of 4 new constaints that, when
the controlling feature is not present, force the RESx value to
be either 0 or 1 depending on the value of E2H.

This allows diverging RESx values depending on the value of E2H,
something that is required by a bunch of SCTLR_EL2 bits.

Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 arch/arm64/kvm/config.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 1990cebc77c66..7063fffc22799 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -26,6 +26,10 @@ struct reg_bits_to_feat_map {
 #define	MASKS_POINTER	BIT(3)	/* Pointer to fgt_masks struct instead of bits */
 #define	AS_RES1		BIT(4)	/* RES1 when not supported */
 #define	REQUIRES_E2H1	BIT(5)	/* Add HCR_EL2.E2H RES1 as a pre-condition */
+#define	RES0_WHEN_E2H0	BIT(6)	/* RES0 when E2H=0 and not supported */
+#define	RES0_WHEN_E2H1	BIT(7)	/* RES0 when E2H=1 and not supported */
+#define	RES1_WHEN_E2H0	BIT(8)	/* RES1 when E2H=0 and not supported */
+#define	RES1_WHEN_E2H1	BIT(9)	/* RES1 when E2H=1 and not supported */
 
 	unsigned long	flags;
 
@@ -1298,10 +1302,24 @@ struct resx compute_resx_bits(struct kvm *kvm,
 			match &= !e2h0;
 		
 		if (!match) {
+			u64 bits = reg_feat_map_bits(&map[i]);
+
+			if (e2h0) {
+				if      (map[i].flags & RES1_WHEN_E2H0)
+					resx.res1 |= bits;
+				else if (map[i].flags & RES0_WHEN_E2H0)
+					resx.res0 |= bits;
+			} else {
+				if      (map[i].flags & RES1_WHEN_E2H1)
+					resx.res1 |= bits;
+				else if (map[i].flags & RES0_WHEN_E2H1)
+					resx.res0 |= bits;
+			}
+
 			if (map[i].flags & AS_RES1)
- 				resx.res1 |= reg_feat_map_bits(&map[i]);
-			else
-				resx.res0 |= reg_feat_map_bits(&map[i]);
+				resx.res1 |= bits;
+			else if (!(resx.res1 & bits))
+				resx.res0 |= bits;
 		}
 	}
 
-- 
2.47.3




More information about the linux-arm-kernel mailing list