summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2026-02-02 18:43:21 +0000
committerMarc Zyngier <maz@kernel.org>2026-02-05 09:02:12 +0000
commitd406fcb2030e3efe2c5a7f043028cb3727f522d8 (patch)
tree818bb8f14fcfed0f017e890b3058248cb1a10dde
parentad90512f12fef5506d1f72cdfbd720eb701eab8c (diff)
KVM: arm64: Add RES1_WHEN_E2Hx constraints as configuration flags
"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 two new constaints that, when the controlling feature is not present, force the field to RES1 depending on the value of E2H. Note that RES0 is still implicit, This allows diverging RESx values depending on the value of E2H, something that is required by a bunch of SCTLR_EL2 bits. Reviewed-by: Fuad Tabba <tabba@google.com> Tested-by: Fuad Tabba <tabba@google.com> Link: https://patch.msgid.link/20260202184329.2724080-13-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--arch/arm64/kvm/config.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 84c577672e97..7e8e42c1cee4 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -26,6 +26,8 @@ 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 RES1_WHEN_E2H0 BIT(6) /* RES1 when E2H=0 and not supported */
+#define RES1_WHEN_E2H1 BIT(7) /* RES1 when E2H=1 and not supported */
unsigned long flags;
@@ -1297,10 +1299,14 @@ static struct resx compute_resx_bits(struct kvm *kvm,
match &= !e2h0;
if (!match) {
- if (map[i].flags & AS_RES1)
- resx.res1 |= reg_feat_map_bits(&map[i]);
+ u64 bits = reg_feat_map_bits(&map[i]);
+
+ if ((map[i].flags & AS_RES1) ||
+ (e2h0 && (map[i].flags & RES1_WHEN_E2H0)) ||
+ (!e2h0 && (map[i].flags & RES1_WHEN_E2H1)))
+ resx.res1 |= bits;
else
- resx.res0 |= reg_feat_map_bits(&map[i]);
+ resx.res0 |= bits;
}
}