* [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-18 6:07 ` Oliver Upton
2025-09-17 16:58 ` [PATCH 2/8] KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers Marc Zyngier
` (6 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 201 +++++++++++++++++++++++++++-------------
1 file changed, 137 insertions(+), 64 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index da66c4a147752..42b834c82a20d 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -8,11 +8,16 @@
#include <asm/sysreg.h>
struct reg_bits_to_feat_map {
- u64 bits;
+ union {
+ u64 bits;
+ u64 *res0p;
+ };
#define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
#define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
#define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
+#define RES0_POINTER BIT(3) /* Pointer to RES0 value instead of bits */
+
unsigned long flags;
union {
@@ -28,9 +33,16 @@ struct reg_bits_to_feat_map {
};
};
-#define __NEEDS_FEAT_3(m, f, id, fld, lim) \
+struct reg_to_feat_map {
+ const char *name;
+ const struct reg_bits_to_feat_map feat_map;
+ const struct reg_bits_to_feat_map *bit_feat_map;
+ const unsigned int bit_feat_map_sz;
+};
+
+#define __NEEDS_FEAT_3(m, f, w, id, fld, lim) \
{ \
- .bits = (m), \
+ .w = (m), \
.flags = (f), \
.regidx = IDREG_IDX(SYS_ ## id), \
.shift = id ##_## fld ## _SHIFT, \
@@ -39,28 +51,50 @@ struct reg_bits_to_feat_map {
.lo_lim = id ##_## fld ##_## lim \
}
-#define __NEEDS_FEAT_2(m, f, fun, dummy) \
+#define __NEEDS_FEAT_2(m, f, w, fun, dummy) \
{ \
- .bits = (m), \
+ .w = (m), \
.flags = (f) | CALL_FUNC, \
.fval = (fun), \
}
-#define __NEEDS_FEAT_1(m, f, fun) \
+#define __NEEDS_FEAT_1(m, f, w, fun) \
{ \
- .bits = (m), \
+ .w = (m), \
.flags = (f) | CALL_FUNC, \
.match = (fun), \
}
+#define __NEEDS_FEAT_FLAG(m, f, w, ...) \
+ CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, w, __VA_ARGS__)
+
#define NEEDS_FEAT_FLAG(m, f, ...) \
- CONCATENATE(__NEEDS_FEAT_, COUNT_ARGS(__VA_ARGS__))(m, f, __VA_ARGS__)
+ __NEEDS_FEAT_FLAG(m, f, bits, __VA_ARGS__)
#define NEEDS_FEAT_FIXED(m, ...) \
- NEEDS_FEAT_FLAG(m, FIXED_VALUE, __VA_ARGS__, 0)
+ __NEEDS_FEAT_FLAG(m, FIXED_VALUE, bits, __VA_ARGS__, 0)
+
+#define NEEDS_FEAT_RES0(p, ...) \
+ __NEEDS_FEAT_FLAG(p, RES0_POINTER, res0p, __VA_ARGS__)
#define NEEDS_FEAT(m, ...) NEEDS_FEAT_FLAG(m, 0, __VA_ARGS__)
+#define FEAT_MAP(r, f, m) \
+ { \
+ .name = #r, \
+ .feat_map = NEEDS_FEAT(~r##_RES0, f), \
+ .bit_feat_map = m, \
+ .bit_feat_map_sz = ARRAY_SIZE(m), \
+ }
+
+#define FEAT_MAP_FGT(msk, m, f) \
+ { \
+ .name = #msk, \
+ .feat_map = NEEDS_FEAT_RES0(&msk.res0, f),\
+ .bit_feat_map = m, \
+ .bit_feat_map_sz = ARRAY_SIZE(m), \
+ }
+
#define FEAT_SPE ID_AA64DFR0_EL1, PMSVer, IMP
#define FEAT_SPE_FnE ID_AA64DFR0_EL1, PMSVer, V1P2
#define FEAT_BRBE ID_AA64DFR0_EL1, BRBE, IMP
@@ -320,7 +354,7 @@ static bool compute_hcr_e2h(struct kvm *kvm, u64 *bits)
return true;
}
-static const struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
+static const struct reg_bits_to_feat_map hfgrtr_bit_feat_map[] = {
NEEDS_FEAT(HFGRTR_EL2_nAMAIR2_EL1 |
HFGRTR_EL2_nMAIR2_EL1,
FEAT_AIE),
@@ -397,7 +431,12 @@ static const struct reg_bits_to_feat_map hfgrtr_feat_map[] = {
NEVER_FGU, FEAT_AA64EL1),
};
-static const struct reg_bits_to_feat_map hfgwtr_feat_map[] = {
+static const
+struct reg_to_feat_map hfgrtr_feat_map = FEAT_MAP_FGT(hfgrtr_masks,
+ hfgrtr_bit_feat_map,
+ FEAT_FGT);
+
+static const struct reg_bits_to_feat_map hfgwtr_bit_feat_map[] = {
NEEDS_FEAT(HFGWTR_EL2_nAMAIR2_EL1 |
HFGWTR_EL2_nMAIR2_EL1,
FEAT_AIE),
@@ -461,7 +500,12 @@ static const struct reg_bits_to_feat_map hfgwtr_feat_map[] = {
NEVER_FGU, FEAT_AA64EL1),
};
-static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = {
+static const
+struct reg_to_feat_map hfgwtr_feat_map = FEAT_MAP_FGT(hfgwtr_masks,
+ hfgwtr_bit_feat_map,
+ FEAT_FGT);
+
+static const struct reg_bits_to_feat_map hdfgrtr_bit_feat_map[] = {
NEEDS_FEAT(HDFGRTR_EL2_PMBIDR_EL1 |
HDFGRTR_EL2_PMSLATFR_EL1 |
HDFGRTR_EL2_PMSIRR_EL1 |
@@ -528,7 +572,12 @@ static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = {
NEVER_FGU, FEAT_AA64EL1)
};
-static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = {
+static const
+struct reg_to_feat_map hdfgrtr_feat_map = FEAT_MAP_FGT(hdfgrtr_masks,
+ hdfgrtr_bit_feat_map,
+ FEAT_FGT);
+
+static const struct reg_bits_to_feat_map hdfgwtr_bit_feat_map[] = {
NEEDS_FEAT(HDFGWTR_EL2_PMSLATFR_EL1 |
HDFGWTR_EL2_PMSIRR_EL1 |
HDFGWTR_EL2_PMSICR_EL1 |
@@ -588,8 +637,12 @@ static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = {
NEEDS_FEAT(HDFGWTR_EL2_TRFCR_EL1, FEAT_TRF),
};
+static const
+struct reg_to_feat_map hdfgwtr_feat_map = FEAT_MAP_FGT(hdfgwtr_masks,
+ hdfgwtr_bit_feat_map,
+ FEAT_FGT);
-static const struct reg_bits_to_feat_map hfgitr_feat_map[] = {
+static const struct reg_bits_to_feat_map hfgitr_bit_feat_map[] = {
NEEDS_FEAT(HFGITR_EL2_PSBCSYNC, FEAT_SPEv1p5),
NEEDS_FEAT(HFGITR_EL2_ATS1E1A, FEAT_ATS1A),
NEEDS_FEAT(HFGITR_EL2_COSPRCTX, FEAT_SPECRES2),
@@ -662,7 +715,12 @@ static const struct reg_bits_to_feat_map hfgitr_feat_map[] = {
NEVER_FGU, FEAT_AA64EL1),
};
-static const struct reg_bits_to_feat_map hafgrtr_feat_map[] = {
+static const
+struct reg_to_feat_map hfgitr_feat_map = FEAT_MAP_FGT(hfgitr_masks,
+ hfgitr_bit_feat_map,
+ FEAT_FGT);
+
+static const struct reg_bits_to_feat_map hafgrtr_bit_feat_map[] = {
NEEDS_FEAT(HAFGRTR_EL2_AMEVTYPER115_EL0 |
HAFGRTR_EL2_AMEVTYPER114_EL0 |
HAFGRTR_EL2_AMEVTYPER113_EL0 |
@@ -704,6 +762,11 @@ static const struct reg_bits_to_feat_map hafgrtr_feat_map[] = {
FEAT_AMUv1),
};
+static const
+struct reg_to_feat_map hafgrtr_feat_map = FEAT_MAP_FGT(hafgrtr_masks,
+ hafgrtr_bit_feat_map,
+ FEAT_FGT);
+
static const struct reg_bits_to_feat_map hfgitr2_feat_map[] = {
NEEDS_FEAT(HFGITR2_EL2_nDCCIVAPS, FEAT_PoPS),
NEEDS_FEAT(HFGITR2_EL2_TSBCSYNC, FEAT_TRBEv1p1)
@@ -1061,20 +1124,25 @@ static void __init check_feat_map(const struct reg_bits_to_feat_map *map,
str, mask ^ ~res0);
}
+static u64 reg_feat_map_bits(const struct reg_bits_to_feat_map *map)
+{
+ return map->flags & RES0_POINTER ? ~(*map->res0p) : map->bits;
+}
+
+static void __init check_reg_feat_map(const struct reg_to_feat_map *r)
+{
+ check_feat_map(r->bit_feat_map, r->bit_feat_map_sz,
+ ~reg_feat_map_bits(&r->feat_map), r->name);
+}
+
void __init check_feature_map(void)
{
- check_feat_map(hfgrtr_feat_map, ARRAY_SIZE(hfgrtr_feat_map),
- hfgrtr_masks.res0, hfgrtr_masks.str);
- check_feat_map(hfgwtr_feat_map, ARRAY_SIZE(hfgwtr_feat_map),
- hfgwtr_masks.res0, hfgwtr_masks.str);
- check_feat_map(hfgitr_feat_map, ARRAY_SIZE(hfgitr_feat_map),
- hfgitr_masks.res0, hfgitr_masks.str);
- check_feat_map(hdfgrtr_feat_map, ARRAY_SIZE(hdfgrtr_feat_map),
- hdfgrtr_masks.res0, hdfgrtr_masks.str);
- check_feat_map(hdfgwtr_feat_map, ARRAY_SIZE(hdfgwtr_feat_map),
- hdfgwtr_masks.res0, hdfgwtr_masks.str);
- check_feat_map(hafgrtr_feat_map, ARRAY_SIZE(hafgrtr_feat_map),
- hafgrtr_masks.res0, hafgrtr_masks.str);
+ check_reg_feat_map(&hfgrtr_feat_map);
+ check_reg_feat_map(&hfgwtr_feat_map);
+ check_reg_feat_map(&hfgitr_feat_map);
+ check_reg_feat_map(&hdfgrtr_feat_map);
+ check_reg_feat_map(&hdfgwtr_feat_map);
+ check_reg_feat_map(&hafgrtr_feat_map);
check_feat_map(hcrx_feat_map, ARRAY_SIZE(hcrx_feat_map),
__HCRX_EL2_RES0, "HCRX_EL2");
check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
@@ -1129,7 +1197,7 @@ static u64 __compute_fixed_bits(struct kvm *kvm,
match = idreg_feat_match(kvm, &map[i]);
if (!match || (map[i].flags & FIXED_VALUE))
- val |= map[i].bits;
+ val |= reg_feat_map_bits(&map[i]);
}
return val;
@@ -1145,6 +1213,29 @@ static u64 compute_res0_bits(struct kvm *kvm,
require, exclude | FIXED_VALUE);
}
+static u64 compute_reg_res0_bits(struct kvm *kvm,
+ const struct reg_to_feat_map *r,
+ unsigned long require, unsigned long exclude)
+
+{
+ u64 res0;
+
+ res0 = compute_res0_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
+ require, exclude);
+
+ /*
+ * If computing FGUs, don't take RES0 or register existence
+ * into account -- we're not computing bits for the register
+ * itself.
+ */
+ if (!(exclude & NEVER_FGU)) {
+ res0 |= compute_res0_bits(kvm, &r->feat_map, 1, require, exclude);
+ res0 |= ~reg_feat_map_bits(&r->feat_map);
+ }
+
+ return res0;
+}
+
static u64 compute_fixed_bits(struct kvm *kvm,
const struct reg_bits_to_feat_map *map,
int map_size,
@@ -1162,30 +1253,24 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
switch (fgt) {
case HFGRTR_GROUP:
- val |= compute_res0_bits(kvm, hfgrtr_feat_map,
- ARRAY_SIZE(hfgrtr_feat_map),
- 0, NEVER_FGU);
- val |= compute_res0_bits(kvm, hfgwtr_feat_map,
- ARRAY_SIZE(hfgwtr_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgrtr_feat_map,
+ 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgwtr_feat_map,
+ 0, NEVER_FGU);
break;
case HFGITR_GROUP:
- val |= compute_res0_bits(kvm, hfgitr_feat_map,
- ARRAY_SIZE(hfgitr_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgitr_feat_map,
+ 0, NEVER_FGU);
break;
case HDFGRTR_GROUP:
- val |= compute_res0_bits(kvm, hdfgrtr_feat_map,
- ARRAY_SIZE(hdfgrtr_feat_map),
- 0, NEVER_FGU);
- val |= compute_res0_bits(kvm, hdfgwtr_feat_map,
- ARRAY_SIZE(hdfgwtr_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hdfgrtr_feat_map,
+ 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hdfgwtr_feat_map,
+ 0, NEVER_FGU);
break;
case HAFGRTR_GROUP:
- val |= compute_res0_bits(kvm, hafgrtr_feat_map,
- ARRAY_SIZE(hafgrtr_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hafgrtr_feat_map,
+ 0, NEVER_FGU);
break;
case HFGRTR2_GROUP:
val |= compute_res0_bits(kvm, hfgrtr2_feat_map,
@@ -1221,39 +1306,27 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
switch (reg) {
case HFGRTR_EL2:
- *res0 = compute_res0_bits(kvm, hfgrtr_feat_map,
- ARRAY_SIZE(hfgrtr_feat_map), 0, 0);
- *res0 |= hfgrtr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgrtr_feat_map, 0, 0);
*res1 = HFGRTR_EL2_RES1;
break;
case HFGWTR_EL2:
- *res0 = compute_res0_bits(kvm, hfgwtr_feat_map,
- ARRAY_SIZE(hfgwtr_feat_map), 0, 0);
- *res0 |= hfgwtr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgwtr_feat_map, 0, 0);
*res1 = HFGWTR_EL2_RES1;
break;
case HFGITR_EL2:
- *res0 = compute_res0_bits(kvm, hfgitr_feat_map,
- ARRAY_SIZE(hfgitr_feat_map), 0, 0);
- *res0 |= hfgitr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgitr_feat_map, 0, 0);
*res1 = HFGITR_EL2_RES1;
break;
case HDFGRTR_EL2:
- *res0 = compute_res0_bits(kvm, hdfgrtr_feat_map,
- ARRAY_SIZE(hdfgrtr_feat_map), 0, 0);
- *res0 |= hdfgrtr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hdfgrtr_feat_map, 0, 0);
*res1 = HDFGRTR_EL2_RES1;
break;
case HDFGWTR_EL2:
- *res0 = compute_res0_bits(kvm, hdfgwtr_feat_map,
- ARRAY_SIZE(hdfgwtr_feat_map), 0, 0);
- *res0 |= hdfgwtr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hdfgwtr_feat_map, 0, 0);
*res1 = HDFGWTR_EL2_RES1;
break;
case HAFGRTR_EL2:
- *res0 = compute_res0_bits(kvm, hafgrtr_feat_map,
- ARRAY_SIZE(hafgrtr_feat_map), 0, 0);
- *res0 |= hafgrtr_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hafgrtr_feat_map, 0, 0);
*res1 = HAFGRTR_EL2_RES1;
break;
case HFGRTR2_EL2:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
2025-09-17 16:58 ` [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers Marc Zyngier
@ 2025-09-18 6:07 ` Oliver Upton
2025-09-18 9:53 ` Marc Zyngier
0 siblings, 1 reply; 11+ messages in thread
From: Oliver Upton @ 2025-09-18 6:07 UTC (permalink / raw)
To: Marc Zyngier
Cc: kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Jinqian Yang
Hey,
On Wed, Sep 17, 2025 at 05:58:33PM +0100, Marc Zyngier wrote:
Did you mean to add changelogs to these patches?
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
> arch/arm64/kvm/config.c | 201 +++++++++++++++++++++++++++-------------
> 1 file changed, 137 insertions(+), 64 deletions(-)
>
> diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> index da66c4a147752..42b834c82a20d 100644
> --- a/arch/arm64/kvm/config.c
> +++ b/arch/arm64/kvm/config.c
> @@ -8,11 +8,16 @@
> #include <asm/sysreg.h>
>
> struct reg_bits_to_feat_map {
> - u64 bits;
> + union {
> + u64 bits;
> + u64 *res0p;
> + };
>
> #define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
> #define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
> #define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
> +#define RES0_POINTER BIT(3) /* Pointer to RES0 value instead of bits */
> +
> unsigned long flags;
>
> union {
> @@ -28,9 +33,16 @@ struct reg_bits_to_feat_map {
> };
> };
>
> -#define __NEEDS_FEAT_3(m, f, id, fld, lim) \
> +struct reg_to_feat_map {
> + const char *name;
> + const struct reg_bits_to_feat_map feat_map;
Some documentation might help with confusion between this and
bit_feat_map. IIUC you're using a single NEEDS_FEAT() expression to RES0
the whole sucker based on whether or not the FEAT_XXX for the EL2
register is present?
> + const struct reg_bits_to_feat_map *bit_feat_map;
> + const unsigned int bit_feat_map_sz;
> +};
Ok, differentiating "reg_to_feat_map" and "reg_bits_to_feat_map" is a
bit hard on the reader... Could this maybe be called "reg_feat_map_desc"
or similar?
This refactoring could also be done as a separate patch.
Thanks,
Oliver
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
2025-09-18 6:07 ` Oliver Upton
@ 2025-09-18 9:53 ` Marc Zyngier
0 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-18 9:53 UTC (permalink / raw)
To: Oliver Upton
Cc: kvmarm, linux-arm-kernel, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Jinqian Yang
On Thu, 18 Sep 2025 07:07:26 +0100,
Oliver Upton <oliver.upton@linux.dev> wrote:
>
> Hey,
>
> On Wed, Sep 17, 2025 at 05:58:33PM +0100, Marc Zyngier wrote:
>
> Did you mean to add changelogs to these patches?
I actually meant to send a *different* series. Pushed out the wrong
branch and sent crap. Apologies for the noise.
>
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/kvm/config.c | 201 +++++++++++++++++++++++++++-------------
> > 1 file changed, 137 insertions(+), 64 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> > index da66c4a147752..42b834c82a20d 100644
> > --- a/arch/arm64/kvm/config.c
> > +++ b/arch/arm64/kvm/config.c
> > @@ -8,11 +8,16 @@
> > #include <asm/sysreg.h>
> >
> > struct reg_bits_to_feat_map {
> > - u64 bits;
> > + union {
> > + u64 bits;
> > + u64 *res0p;
> > + };
> >
> > #define NEVER_FGU BIT(0) /* Can trap, but never UNDEF */
> > #define CALL_FUNC BIT(1) /* Needs to evaluate tons of crap */
> > #define FIXED_VALUE BIT(2) /* RAZ/WI or RAO/WI in KVM */
> > +#define RES0_POINTER BIT(3) /* Pointer to RES0 value instead of bits */
> > +
> > unsigned long flags;
> >
> > union {
> > @@ -28,9 +33,16 @@ struct reg_bits_to_feat_map {
> > };
> > };
> >
> > -#define __NEEDS_FEAT_3(m, f, id, fld, lim) \
> > +struct reg_to_feat_map {
> > + const char *name;
> > + const struct reg_bits_to_feat_map feat_map;
>
> Some documentation might help with confusion between this and
> bit_feat_map. IIUC you're using a single NEEDS_FEAT() expression to RES0
> the whole sucker based on whether or not the FEAT_XXX for the EL2
> register is present?
>
> > + const struct reg_bits_to_feat_map *bit_feat_map;
> > + const unsigned int bit_feat_map_sz;
> > +};
>
> Ok, differentiating "reg_to_feat_map" and "reg_bits_to_feat_map" is a
> bit hard on the reader... Could this maybe be called "reg_feat_map_desc"
> or similar?
Sure thing. Things will be a bit noisier, but hey...
> This refactoring could also be done as a separate patch.
Yup, that's what I already have in the series I was suppose to send...
I'll respin this shortly.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/8] KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
2025-09-17 16:58 ` [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 3/8] KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2 Marc Zyngier
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 86 ++++++++++++++++++++++++-----------------
1 file changed, 51 insertions(+), 35 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 42b834c82a20d..05be2b917c8c0 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -185,6 +185,7 @@ struct reg_to_feat_map {
#define FEAT_SSBS ID_AA64PFR1_EL1, SSBS, IMP
#define FEAT_TIDCP1 ID_AA64MMFR1_EL1, TIDCP1, IMP
#define FEAT_FGT ID_AA64MMFR0_EL1, FGT, IMP
+#define FEAT_FGT2 ID_AA64MMFR0_EL1, FGT, FGT2
#define FEAT_MTPMU ID_AA64DFR0_EL1, MTPMU, IMP
static bool not_feat_aa64el3(struct kvm *kvm)
@@ -767,12 +768,17 @@ struct reg_to_feat_map hafgrtr_feat_map = FEAT_MAP_FGT(hafgrtr_masks,
hafgrtr_bit_feat_map,
FEAT_FGT);
-static const struct reg_bits_to_feat_map hfgitr2_feat_map[] = {
+static const struct reg_bits_to_feat_map hfgitr2_bit_feat_map[] = {
NEEDS_FEAT(HFGITR2_EL2_nDCCIVAPS, FEAT_PoPS),
NEEDS_FEAT(HFGITR2_EL2_TSBCSYNC, FEAT_TRBEv1p1)
};
-static const struct reg_bits_to_feat_map hfgrtr2_feat_map[] = {
+static const
+struct reg_to_feat_map hfgitr2_feat_map = FEAT_MAP_FGT(hfgitr2_masks,
+ hfgitr2_bit_feat_map,
+ FEAT_FGT2);
+
+static const struct reg_bits_to_feat_map hfgrtr2_bit_feat_map[] = {
NEEDS_FEAT(HFGRTR2_EL2_nPFAR_EL1, FEAT_PFAR),
NEEDS_FEAT(HFGRTR2_EL2_nERXGSR_EL1, FEAT_RASv2),
NEEDS_FEAT(HFGRTR2_EL2_nACTLRALIAS_EL1 |
@@ -791,7 +797,12 @@ static const struct reg_bits_to_feat_map hfgrtr2_feat_map[] = {
NEEDS_FEAT(HFGRTR2_EL2_nRCWSMASK_EL1, FEAT_THE),
};
-static const struct reg_bits_to_feat_map hfgwtr2_feat_map[] = {
+static const
+struct reg_to_feat_map hfgrtr2_feat_map = FEAT_MAP_FGT(hfgrtr2_masks,
+ hfgrtr2_bit_feat_map,
+ FEAT_FGT2);
+
+static const struct reg_bits_to_feat_map hfgwtr2_bit_feat_map[] = {
NEEDS_FEAT(HFGWTR2_EL2_nPFAR_EL1, FEAT_PFAR),
NEEDS_FEAT(HFGWTR2_EL2_nACTLRALIAS_EL1 |
HFGWTR2_EL2_nACTLRMASK_EL1 |
@@ -809,7 +820,12 @@ static const struct reg_bits_to_feat_map hfgwtr2_feat_map[] = {
NEEDS_FEAT(HFGWTR2_EL2_nRCWSMASK_EL1, FEAT_THE),
};
-static const struct reg_bits_to_feat_map hdfgrtr2_feat_map[] = {
+static const
+struct reg_to_feat_map hfgwtr2_feat_map = FEAT_MAP_FGT(hfgwtr2_masks,
+ hfgwtr2_bit_feat_map,
+ FEAT_FGT2);
+
+static const struct reg_bits_to_feat_map hdfgrtr2_bit_feat_map[] = {
NEEDS_FEAT(HDFGRTR2_EL2_nMDSELR_EL1, FEAT_Debugv8p9),
NEEDS_FEAT(HDFGRTR2_EL2_nPMECR_EL1, feat_ebep_pmuv3_ss),
NEEDS_FEAT(HDFGRTR2_EL2_nTRCITECR_EL1, FEAT_ITE),
@@ -839,7 +855,12 @@ static const struct reg_bits_to_feat_map hdfgrtr2_feat_map[] = {
NEEDS_FEAT(HDFGRTR2_EL2_nTRBMPAM_EL1, feat_trbe_mpam),
};
-static const struct reg_bits_to_feat_map hdfgwtr2_feat_map[] = {
+static const
+struct reg_to_feat_map hdfgrtr2_feat_map = FEAT_MAP_FGT(hdfgrtr2_masks,
+ hdfgrtr2_bit_feat_map,
+ FEAT_FGT2);
+
+static const struct reg_bits_to_feat_map hdfgwtr2_bit_feat_map[] = {
NEEDS_FEAT(HDFGWTR2_EL2_nMDSELR_EL1, FEAT_Debugv8p9),
NEEDS_FEAT(HDFGWTR2_EL2_nPMECR_EL1, feat_ebep_pmuv3_ss),
NEEDS_FEAT(HDFGWTR2_EL2_nTRCITECR_EL1, FEAT_ITE),
@@ -867,6 +888,11 @@ static const struct reg_bits_to_feat_map hdfgwtr2_feat_map[] = {
NEEDS_FEAT(HDFGWTR2_EL2_nTRBMPAM_EL1, feat_trbe_mpam),
};
+static const
+struct reg_to_feat_map hdfgwtr2_feat_map = FEAT_MAP_FGT(hdfgwtr2_masks,
+ hdfgwtr2_bit_feat_map,
+ FEAT_FGT2);
+
static const struct reg_bits_to_feat_map hcrx_feat_map[] = {
NEEDS_FEAT(HCRX_EL2_PACMEn, feat_pauth_lr),
NEEDS_FEAT(HCRX_EL2_EnFPM, FEAT_FPMR),
@@ -1143,6 +1169,11 @@ void __init check_feature_map(void)
check_reg_feat_map(&hdfgrtr_feat_map);
check_reg_feat_map(&hdfgwtr_feat_map);
check_reg_feat_map(&hafgrtr_feat_map);
+ check_reg_feat_map(&hfgrtr2_feat_map);
+ check_reg_feat_map(&hfgwtr2_feat_map);
+ check_reg_feat_map(&hfgitr2_feat_map);
+ check_reg_feat_map(&hdfgrtr2_feat_map);
+ check_reg_feat_map(&hdfgwtr2_feat_map);
check_feat_map(hcrx_feat_map, ARRAY_SIZE(hcrx_feat_map),
__HCRX_EL2_RES0, "HCRX_EL2");
check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
@@ -1273,25 +1304,20 @@ void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
0, NEVER_FGU);
break;
case HFGRTR2_GROUP:
- val |= compute_res0_bits(kvm, hfgrtr2_feat_map,
- ARRAY_SIZE(hfgrtr2_feat_map),
- 0, NEVER_FGU);
- val |= compute_res0_bits(kvm, hfgwtr2_feat_map,
- ARRAY_SIZE(hfgwtr2_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgrtr2_feat_map,
+ 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgwtr2_feat_map,
+ 0, NEVER_FGU);
break;
case HFGITR2_GROUP:
- val |= compute_res0_bits(kvm, hfgitr2_feat_map,
- ARRAY_SIZE(hfgitr2_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hfgitr2_feat_map,
+ 0, NEVER_FGU);
break;
case HDFGRTR2_GROUP:
- val |= compute_res0_bits(kvm, hdfgrtr2_feat_map,
- ARRAY_SIZE(hdfgrtr2_feat_map),
- 0, NEVER_FGU);
- val |= compute_res0_bits(kvm, hdfgwtr2_feat_map,
- ARRAY_SIZE(hdfgwtr2_feat_map),
- 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hdfgrtr2_feat_map,
+ 0, NEVER_FGU);
+ val |= compute_reg_res0_bits(kvm, &hdfgwtr2_feat_map,
+ 0, NEVER_FGU);
break;
default:
BUG();
@@ -1330,33 +1356,23 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = HAFGRTR_EL2_RES1;
break;
case HFGRTR2_EL2:
- *res0 = compute_res0_bits(kvm, hfgrtr2_feat_map,
- ARRAY_SIZE(hfgrtr2_feat_map), 0, 0);
- *res0 |= hfgrtr2_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgrtr2_feat_map, 0, 0);
*res1 = HFGRTR2_EL2_RES1;
break;
case HFGWTR2_EL2:
- *res0 = compute_res0_bits(kvm, hfgwtr2_feat_map,
- ARRAY_SIZE(hfgwtr2_feat_map), 0, 0);
- *res0 |= hfgwtr2_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgwtr2_feat_map, 0, 0);
*res1 = HFGWTR2_EL2_RES1;
break;
case HFGITR2_EL2:
- *res0 = compute_res0_bits(kvm, hfgitr2_feat_map,
- ARRAY_SIZE(hfgitr2_feat_map), 0, 0);
- *res0 |= hfgitr2_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hfgitr2_feat_map, 0, 0);
*res1 = HFGITR2_EL2_RES1;
break;
case HDFGRTR2_EL2:
- *res0 = compute_res0_bits(kvm, hdfgrtr2_feat_map,
- ARRAY_SIZE(hdfgrtr2_feat_map), 0, 0);
- *res0 |= hdfgrtr2_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hdfgrtr2_feat_map, 0, 0);
*res1 = HDFGRTR2_EL2_RES1;
break;
case HDFGWTR2_EL2:
- *res0 = compute_res0_bits(kvm, hdfgwtr2_feat_map,
- ARRAY_SIZE(hdfgwtr2_feat_map), 0, 0);
- *res0 |= hdfgwtr2_masks.res0;
+ *res0 = compute_reg_res0_bits(kvm, &hdfgwtr2_feat_map, 0, 0);
*res1 = HDFGWTR2_EL2_RES1;
break;
case HCRX_EL2:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 3/8] KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
2025-09-17 16:58 ` [PATCH 1/8] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers Marc Zyngier
2025-09-17 16:58 ` [PATCH 2/8] KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 4/8] KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits() Marc Zyngier
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 05be2b917c8c0..f8e9cfa844266 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -187,6 +187,7 @@ struct reg_to_feat_map {
#define FEAT_FGT ID_AA64MMFR0_EL1, FGT, IMP
#define FEAT_FGT2 ID_AA64MMFR0_EL1, FGT, FGT2
#define FEAT_MTPMU ID_AA64DFR0_EL1, MTPMU, IMP
+#define FEAT_HCX ID_AA64MMFR1_EL1, HCX, IMP
static bool not_feat_aa64el3(struct kvm *kvm)
{
@@ -893,7 +894,7 @@ struct reg_to_feat_map hdfgwtr2_feat_map = FEAT_MAP_FGT(hdfgwtr2_masks,
hdfgwtr2_bit_feat_map,
FEAT_FGT2);
-static const struct reg_bits_to_feat_map hcrx_feat_map[] = {
+static const struct reg_bits_to_feat_map hcrx_bit_feat_map[] = {
NEEDS_FEAT(HCRX_EL2_PACMEn, feat_pauth_lr),
NEEDS_FEAT(HCRX_EL2_EnFPM, FEAT_FPMR),
NEEDS_FEAT(HCRX_EL2_GCSEn, FEAT_GCS),
@@ -922,6 +923,10 @@ static const struct reg_bits_to_feat_map hcrx_feat_map[] = {
NEEDS_FEAT(HCRX_EL2_EnAS0, FEAT_LS64_ACCDATA),
};
+static const
+struct reg_to_feat_map hcrx_feat_map = FEAT_MAP(__HCRX_EL2, FEAT_HCX,
+ hcrx_bit_feat_map);
+
static const struct reg_bits_to_feat_map hcr_feat_map[] = {
NEEDS_FEAT(HCR_EL2_TID0, FEAT_AA32EL0),
NEEDS_FEAT_FIXED(HCR_EL2_RW, compute_hcr_rw),
@@ -1174,8 +1179,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&hfgitr2_feat_map);
check_reg_feat_map(&hdfgrtr2_feat_map);
check_reg_feat_map(&hdfgwtr2_feat_map);
- check_feat_map(hcrx_feat_map, ARRAY_SIZE(hcrx_feat_map),
- __HCRX_EL2_RES0, "HCRX_EL2");
+ check_reg_feat_map(&hcrx_feat_map);
check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
HCR_EL2_RES0, "HCR_EL2");
check_feat_map(sctlr2_feat_map, ARRAY_SIZE(sctlr2_feat_map),
@@ -1376,9 +1380,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = HDFGWTR2_EL2_RES1;
break;
case HCRX_EL2:
- *res0 = compute_res0_bits(kvm, hcrx_feat_map,
- ARRAY_SIZE(hcrx_feat_map), 0, 0);
- *res0 |= __HCRX_EL2_RES0;
+ *res0 = compute_reg_res0_bits(kvm, &hcrx_feat_map, 0, 0);
*res1 = __HCRX_EL2_RES1;
break;
case HCR_EL2:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 4/8] KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits()
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
` (2 preceding siblings ...)
2025-09-17 16:58 ` [PATCH 3/8] KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2 Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 5/8] KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2} Marc Zyngier
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index f8e9cfa844266..c064c31effee9 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -107,6 +107,7 @@ struct reg_to_feat_map {
#define FEAT_AA32EL0 ID_AA64PFR0_EL1, EL0, AARCH32
#define FEAT_AA32EL1 ID_AA64PFR0_EL1, EL1, AARCH32
#define FEAT_AA64EL1 ID_AA64PFR0_EL1, EL1, IMP
+#define FEAT_AA64EL2 ID_AA64PFR0_EL1, EL2, IMP
#define FEAT_AA64EL3 ID_AA64PFR0_EL1, EL3, IMP
#define FEAT_AIE ID_AA64MMFR3_EL1, AIE, IMP
#define FEAT_S2POE ID_AA64MMFR3_EL1, S2POE, IMP
@@ -927,7 +928,7 @@ static const
struct reg_to_feat_map hcrx_feat_map = FEAT_MAP(__HCRX_EL2, FEAT_HCX,
hcrx_bit_feat_map);
-static const struct reg_bits_to_feat_map hcr_feat_map[] = {
+static const struct reg_bits_to_feat_map hcr_bit_feat_map[] = {
NEEDS_FEAT(HCR_EL2_TID0, FEAT_AA32EL0),
NEEDS_FEAT_FIXED(HCR_EL2_RW, compute_hcr_rw),
NEEDS_FEAT(HCR_EL2_HCD, not_feat_aa64el3),
@@ -998,6 +999,10 @@ static const struct reg_bits_to_feat_map hcr_feat_map[] = {
NEEDS_FEAT_FIXED(HCR_EL2_E2H, compute_hcr_e2h),
};
+static const
+struct reg_to_feat_map hcr_feat_map = FEAT_MAP(HCR_EL2, FEAT_AA64EL2,
+ hcr_bit_feat_map);
+
static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
NEEDS_FEAT(SCTLR2_EL1_NMEA |
SCTLR2_EL1_EASE,
@@ -1180,8 +1185,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&hdfgrtr2_feat_map);
check_reg_feat_map(&hdfgwtr2_feat_map);
check_reg_feat_map(&hcrx_feat_map);
- check_feat_map(hcr_feat_map, ARRAY_SIZE(hcr_feat_map),
- HCR_EL2_RES0, "HCR_EL2");
+ check_reg_feat_map(&hcr_feat_map);
check_feat_map(sctlr2_feat_map, ARRAY_SIZE(sctlr2_feat_map),
SCTLR2_EL1_RES0, "SCTLR2_EL1");
check_feat_map(tcr2_el2_feat_map, ARRAY_SIZE(tcr2_el2_feat_map),
@@ -1271,15 +1275,13 @@ static u64 compute_reg_res0_bits(struct kvm *kvm,
return res0;
}
-static u64 compute_fixed_bits(struct kvm *kvm,
- const struct reg_bits_to_feat_map *map,
- int map_size,
- u64 *fixed_bits,
- unsigned long require,
- unsigned long exclude)
+static u64 compute_reg_fixed_bits(struct kvm *kvm,
+ const struct reg_to_feat_map *r,
+ u64 *fixed_bits, unsigned long require,
+ unsigned long exclude)
{
- return __compute_fixed_bits(kvm, map, map_size, fixed_bits,
- require | FIXED_VALUE, exclude);
+ return __compute_fixed_bits(kvm, r->bit_feat_map, r->bit_feat_map_sz,
+ fixed_bits, require | FIXED_VALUE, exclude);
}
void compute_fgu(struct kvm *kvm, enum fgt_group_id fgt)
@@ -1384,12 +1386,9 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = __HCRX_EL2_RES1;
break;
case HCR_EL2:
- mask = compute_fixed_bits(kvm, hcr_feat_map,
- ARRAY_SIZE(hcr_feat_map), &fixed,
- 0, 0);
- *res0 = compute_res0_bits(kvm, hcr_feat_map,
- ARRAY_SIZE(hcr_feat_map), 0, 0);
- *res0 |= HCR_EL2_RES0 | (mask & ~fixed);
+ mask = compute_reg_fixed_bits(kvm, &hcr_feat_map, &fixed, 0, 0);
+ *res0 = compute_reg_res0_bits(kvm, &hcr_feat_map, 0, 0);
+ *res0 |= (mask & ~fixed);
*res1 = HCR_EL2_RES1 | (mask & fixed);
break;
case SCTLR2_EL1:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 5/8] KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2}
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
` (3 preceding siblings ...)
2025-09-17 16:58 ` [PATCH 4/8] KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits() Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 6/8] KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2 Marc Zyngier
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index c064c31effee9..b008551fcf7e9 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1003,7 +1003,7 @@ static const
struct reg_to_feat_map hcr_feat_map = FEAT_MAP(HCR_EL2, FEAT_AA64EL2,
hcr_bit_feat_map);
-static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
+static const struct reg_bits_to_feat_map sctlr2_bit_feat_map[] = {
NEEDS_FEAT(SCTLR2_EL1_NMEA |
SCTLR2_EL1_EASE,
FEAT_DoubleFault2),
@@ -1020,6 +1020,10 @@ static const struct reg_bits_to_feat_map sctlr2_feat_map[] = {
FEAT_CPA2),
};
+static const
+struct reg_to_feat_map sctlr2_feat_map = FEAT_MAP(SCTLR2_EL1, FEAT_SCTLR2,
+ sctlr2_bit_feat_map);
+
static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
NEEDS_FEAT(TCR2_EL2_FNG1 |
TCR2_EL2_FNG0 |
@@ -1186,8 +1190,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&hdfgwtr2_feat_map);
check_reg_feat_map(&hcrx_feat_map);
check_reg_feat_map(&hcr_feat_map);
- check_feat_map(sctlr2_feat_map, ARRAY_SIZE(sctlr2_feat_map),
- SCTLR2_EL1_RES0, "SCTLR2_EL1");
+ check_reg_feat_map(&sctlr2_feat_map);
check_feat_map(tcr2_el2_feat_map, ARRAY_SIZE(tcr2_el2_feat_map),
TCR2_EL2_RES0, "TCR2_EL2");
check_feat_map(sctlr_el1_feat_map, ARRAY_SIZE(sctlr_el1_feat_map),
@@ -1393,9 +1396,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
break;
case SCTLR2_EL1:
case SCTLR2_EL2:
- *res0 = compute_res0_bits(kvm, sctlr2_feat_map,
- ARRAY_SIZE(sctlr2_feat_map), 0, 0);
- *res0 |= SCTLR2_EL1_RES0;
+ *res0 = compute_reg_res0_bits(kvm, &sctlr2_feat_map, 0, 0);
*res1 = SCTLR2_EL1_RES1;
break;
case TCR2_EL2:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 6/8] KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
` (4 preceding siblings ...)
2025-09-17 16:58 ` [PATCH 5/8] KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2} Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 7/8] KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits() Marc Zyngier
2025-09-17 16:58 ` [PATCH 8/8] KVM: arm64: Convert MDCR_EL2 " Marc Zyngier
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index b008551fcf7e9..0e6723bd75775 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1024,7 +1024,7 @@ static const
struct reg_to_feat_map sctlr2_feat_map = FEAT_MAP(SCTLR2_EL1, FEAT_SCTLR2,
sctlr2_bit_feat_map);
-static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
+static const struct reg_bits_to_feat_map tcr2_el2_bit_feat_map[] = {
NEEDS_FEAT(TCR2_EL2_FNG1 |
TCR2_EL2_FNG0 |
TCR2_EL2_A2,
@@ -1046,6 +1046,10 @@ static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = {
NEEDS_FEAT(TCR2_EL2_PIE, FEAT_S1PIE),
};
+static const
+struct reg_to_feat_map tcr2_el2_feat_map = FEAT_MAP(TCR2_EL2, FEAT_TCR2,
+ tcr2_el2_bit_feat_map);
+
static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
NEEDS_FEAT(SCTLR_EL1_CP15BEN |
SCTLR_EL1_ITD |
@@ -1191,8 +1195,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&hcrx_feat_map);
check_reg_feat_map(&hcr_feat_map);
check_reg_feat_map(&sctlr2_feat_map);
- check_feat_map(tcr2_el2_feat_map, ARRAY_SIZE(tcr2_el2_feat_map),
- TCR2_EL2_RES0, "TCR2_EL2");
+ check_reg_feat_map(&tcr2_el2_feat_map);
check_feat_map(sctlr_el1_feat_map, ARRAY_SIZE(sctlr_el1_feat_map),
SCTLR_EL1_RES0, "SCTLR_EL1");
check_feat_map(mdcr_el2_feat_map, ARRAY_SIZE(mdcr_el2_feat_map),
@@ -1400,9 +1403,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = SCTLR2_EL1_RES1;
break;
case TCR2_EL2:
- *res0 = compute_res0_bits(kvm, tcr2_el2_feat_map,
- ARRAY_SIZE(tcr2_el2_feat_map), 0, 0);
- *res0 |= TCR2_EL2_RES0;
+ *res0 = compute_reg_res0_bits(kvm, &tcr2_el2_feat_map, 0, 0);
*res1 = TCR2_EL2_RES1;
break;
case SCTLR_EL1:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 7/8] KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits()
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
` (5 preceding siblings ...)
2025-09-17 16:58 ` [PATCH 6/8] KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2 Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
2025-09-17 16:58 ` [PATCH 8/8] KVM: arm64: Convert MDCR_EL2 " Marc Zyngier
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 0e6723bd75775..09af46e16ac30 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1050,7 +1050,7 @@ static const
struct reg_to_feat_map tcr2_el2_feat_map = FEAT_MAP(TCR2_EL2, FEAT_TCR2,
tcr2_el2_bit_feat_map);
-static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
+static const struct reg_bits_to_feat_map sctlr_el1_bit_feat_map[] = {
NEEDS_FEAT(SCTLR_EL1_CP15BEN |
SCTLR_EL1_ITD |
SCTLR_EL1_SED,
@@ -1124,6 +1124,10 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = {
FEAT_AA64EL1),
};
+static const
+struct reg_to_feat_map sctlr_el1_feat_map = FEAT_MAP(SCTLR_EL1, FEAT_AA64EL1,
+ sctlr_el1_bit_feat_map);
+
static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
NEEDS_FEAT(MDCR_EL2_EBWE, FEAT_Debugv8p9),
NEEDS_FEAT(MDCR_EL2_TDOSA, FEAT_DoubleLock),
@@ -1196,8 +1200,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&hcr_feat_map);
check_reg_feat_map(&sctlr2_feat_map);
check_reg_feat_map(&tcr2_el2_feat_map);
- check_feat_map(sctlr_el1_feat_map, ARRAY_SIZE(sctlr_el1_feat_map),
- SCTLR_EL1_RES0, "SCTLR_EL1");
+ check_reg_feat_map(&sctlr_el1_feat_map);
check_feat_map(mdcr_el2_feat_map, ARRAY_SIZE(mdcr_el2_feat_map),
MDCR_EL2_RES0, "MDCR_EL2");
}
@@ -1407,9 +1410,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = TCR2_EL2_RES1;
break;
case SCTLR_EL1:
- *res0 = compute_res0_bits(kvm, sctlr_el1_feat_map,
- ARRAY_SIZE(sctlr_el1_feat_map), 0, 0);
- *res0 |= SCTLR_EL1_RES0;
+ *res0 = compute_reg_res0_bits(kvm, &sctlr_el1_feat_map, 0, 0);
*res1 = SCTLR_EL1_RES1;
break;
case MDCR_EL2:
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 8/8] KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
2025-09-17 16:58 [PATCH 0/8] KVM: arm64: Handle effective RES0 behaviour of undefined registers Marc Zyngier
` (6 preceding siblings ...)
2025-09-17 16:58 ` [PATCH 7/8] KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits() Marc Zyngier
@ 2025-09-17 16:58 ` Marc Zyngier
7 siblings, 0 replies; 11+ messages in thread
From: Marc Zyngier @ 2025-09-17 16:58 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel
Cc: Joey Gouly, Suzuki K Poulose, Oliver Upton, Zenghui Yu,
Jinqian Yang
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/kvm/config.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 09af46e16ac30..91e235cfdbffd 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1128,7 +1128,7 @@ static const
struct reg_to_feat_map sctlr_el1_feat_map = FEAT_MAP(SCTLR_EL1, FEAT_AA64EL1,
sctlr_el1_bit_feat_map);
-static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
+static const struct reg_bits_to_feat_map mdcr_el2_bit_feat_map[] = {
NEEDS_FEAT(MDCR_EL2_EBWE, FEAT_Debugv8p9),
NEEDS_FEAT(MDCR_EL2_TDOSA, FEAT_DoubleLock),
NEEDS_FEAT(MDCR_EL2_PMEE, FEAT_EBEP),
@@ -1159,6 +1159,10 @@ static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = {
FEAT_AA64EL1),
};
+static const
+struct reg_to_feat_map mdcr_el2_feat_map = FEAT_MAP(MDCR_EL2, FEAT_AA64EL2,
+ mdcr_el2_bit_feat_map);
+
static void __init check_feat_map(const struct reg_bits_to_feat_map *map,
int map_size, u64 res0, const char *str)
{
@@ -1201,8 +1205,7 @@ void __init check_feature_map(void)
check_reg_feat_map(&sctlr2_feat_map);
check_reg_feat_map(&tcr2_el2_feat_map);
check_reg_feat_map(&sctlr_el1_feat_map);
- check_feat_map(mdcr_el2_feat_map, ARRAY_SIZE(mdcr_el2_feat_map),
- MDCR_EL2_RES0, "MDCR_EL2");
+ check_reg_feat_map(&mdcr_el2_feat_map);
}
static bool idreg_feat_match(struct kvm *kvm, const struct reg_bits_to_feat_map *map)
@@ -1414,8 +1417,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r
*res1 = SCTLR_EL1_RES1;
break;
case MDCR_EL2:
- *res0 = compute_res0_bits(kvm, mdcr_el2_feat_map,
- ARRAY_SIZE(mdcr_el2_feat_map), 0, 0);
+ *res0 = compute_reg_res0_bits(kvm, &mdcr_el2_feat_map, 0, 0);
*res0 |= MDCR_EL2_RES0;
*res1 = MDCR_EL2_RES1;
break;
--
2.39.2
^ permalink raw reply related [flat|nested] 11+ messages in thread