KVM: arm64: Handle effective RES0 behaviour of undefined registers
Marc Zyngier
maintainerv2 cover KVM: arm64: Handle effective RES0 behaviour of undefined registers
[After yesterday's blunder, I'm reposting this, with proper commit
messages, and having taken Oliver's feedback into account.]
When a feature is removed from a guest, we ensure that the trap and control bits for that particular feature are made RES0.
For example, SCTLR2_EL2 contains a large number of bits. For any feature FEAT_FOO that is controlled by a bit FOO in SCTLR2_EL2, we make sure that SCTLR2_EL2.FOO is RES0 if FEAT_FOO is not visible to the guest.
However, nothing makes SCTLR2_EL2 RES0 if FEAT_SCTLR2 is not visible.
This series aims at solving this sort of situations. It is still quite incomplete, but aims at bridging a couple of other series:
- [email protected] which wants to make EL2-related fields writable to allow migration
- [email protected] which wants to align the NV support with the rest of the kernel
Hopefully this helps getting to a point where we everything is sanitised according to the architecture, EL2 on the same footing as EL1, and everything migrating in every possible case.
And winning the lottery.
* From v1:
- Commit messages!
- Simplified declaration macros
- Added helpful comments (or so I hope)
- Changed type names according to Oliver's suggestion
Marc Zyngier (10):
KVM: arm64: Remove duplicate FEAT_{SYSREG128,MTE2} descriptions
KVM: arm64: Add reg_feat_map_desc to describe full register dependency
KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers
KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2
KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits()
KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2}
KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2
KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits()
KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
arch/arm64/kvm/config.c | 357 +++++++++++++++++++++++++--------------- 1 file changed, 227 insertions(+), 130 deletions(-)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 1/10 KVM: arm64: Remove duplicate FEAT_{SYSREG128,MTE2} descriptions
Turns out I'm rather bad at noticing that the description of features has already been added. Remove superflusous definitions for SYSREG128 and MTE2.
--- arch/arm64/kvm/config.c | 2 -- 1 file changed, 2 deletions(-)
arch/arm64/kvm/config.c +0 -2
@@ -131,7 +131,6 @@ struct reg_bits_to_feat_map {#define FEAT_SPMU ID_AA64DFR1_EL1, SPMU, IMP#define FEAT_SPE_nVM ID_AA64DFR2_EL1, SPE_nVM, IMP#define FEAT_STEP2 ID_AA64DFR2_EL1, STEP, IMP -#define FEAT_SYSREG128 ID_AA64ISAR2_EL1, SYSREG_128, IMP#define FEAT_CPA2 ID_AA64ISAR3_EL1, CPA, CPA2#define FEAT_ASID2 ID_AA64MMFR4_EL1, ASID2, IMP#define FEAT_MEC ID_AA64MMFR3_EL1, MEC, IMP
@@ -143,7 +142,6 @@ struct reg_bits_to_feat_map {#define FEAT_LSMAOC ID_AA64MMFR2_EL1, LSM, IMP#define FEAT_MixedEnd ID_AA64MMFR0_EL1, BIGEND, IMP#define FEAT_MixedEndEL0 ID_AA64MMFR0_EL1, BIGENDEL0, IMP -#define FEAT_MTE2 ID_AA64PFR1_EL1, MTE, MTE2#define FEAT_MTE_ASYNC ID_AA64PFR1_EL1, MTE_frac, ASYNC#define FEAT_MTE_STORE_ONLY ID_AA64PFR2_EL1, MTESTOREONLY, IMP#define FEAT_PAN ID_AA64MMFR1_EL1, PAN, IMP
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 2/10 KVM: arm64: Add reg_feat_map_desc to describe full register dependency
In reply to Marc Zyngierstruct reg_bits_to_feat_map is great to describe bit-to-feature dependency, but not so much to describe register-to-feature dependency. Yet both need to exist.
Add a new reg_feat_map_desc structure to describe this.
Extra complexity is added by the need to source the RES0 bits from the runtime-computed FGT masks, for which we need an extra flag and extra complexity. Oh well.
--- arch/arm64/kvm/config.c | 81 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 9 deletions(-)
arch/arm64/kvm/config.c +72 -9
@@ -7,12 +7,22 @@#include <linux/kvm_host.h> #include <asm/sysreg.h> +/* +* Describes the dependencies between a set of bits (or the negation +* of a set of RES0 bits) and a feature. The flags indicate how the +* data is interpreted. +*/ 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 +38,27 @@ struct reg_bits_to_feat_map { }; }; -#define __NEEDS_FEAT_3 (m, f, id, fld, lim) \ +/* +* Describes the dependencies for a given register: +* +* @feat_map describes the dependency for the whole register. If the +* features the register depends on are not present, the whole +* register is effectively RES0. +* +* @bit_feat_map describes the dependencies for a set of bits in that +* register. If the features these bits depend on are not present, the +* bits are effectively RES0. +*/ +struct reg_feat_map_desc { +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 +67,63 @@ 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__) +/* +* Declare the dependency between a set of bits and a set of features, +* generating a struct reg_bit_to_feat_map. +*/ #define NEEDS_FEAT (m, ...) NEEDS_FEAT_FLAG(m, 0, __VA_ARGS__) +/* +* Declare the dependency between a non-FGT register, a set of +* feature, and the set of individual bits it contains. This generates +* a struct reg_feat_map_desc. +*/ +#define DECLARE_FEAT_MAP (n, r, m, f) \ + struct reg_feat_map_desc n = { \ + .name = #r, \ + .feat_map = NEEDS_FEAT(~r##_RES0, f), \ + .bit_feat_map = m, \ + .bit_feat_map_sz = ARRAY_SIZE(m), \ + } + +/* +* Specialised version of the above for FGT registers that have their +* RES0 masks described as struct fgt_masks. +*/ +#define DECLARE_FEAT_MAP_FGT (n, msk, m, f) \ + struct reg_feat_map_desc n = { \ + .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
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 3/10 KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
In reply to Marc ZyngierAs we want to enforce FGT registers behaving as RES0 when FEAT_FGT is not exposed to the guest, We move a bumch of things that are so far passed as parameter into a structure that points to the bit description.
--- arch/arm64/kvm/config.c | 126 ++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 49 deletions(-)
arch/arm64/kvm/config.c +77 -49
@@ -458,6 +458,10 @@ static const struct reg_bits_to_feat_map hfgrtr_feat_map[] = { NEVER_FGU, FEAT_AA64EL1), }; + +static const DECLARE_FEAT_MAP_FGT(hfgrtr_desc, hfgrtr_masks, + hfgrtr_feat_map, FEAT_FGT); +static const struct reg_bits_to_feat_map hfgwtr_feat_map[] = { NEEDS_FEAT(HFGWTR_EL2_nAMAIR2_EL1 | HFGWTR_EL2_nMAIR2_EL1,
@@ -522,6 +526,9 @@ static const struct reg_bits_to_feat_map hfgwtr_feat_map[] = { NEVER_FGU, FEAT_AA64EL1), }; +static const DECLARE_FEAT_MAP_FGT(hfgwtr_desc, hfgwtr_masks, + hfgwtr_feat_map, FEAT_FGT); +static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = { NEEDS_FEAT(HDFGRTR_EL2_PMBIDR_EL1 | HDFGRTR_EL2_PMSLATFR_EL1 |
@@ -589,6 +596,9 @@ static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = { NEVER_FGU, FEAT_AA64EL1) }; +static const DECLARE_FEAT_MAP_FGT(hdfgrtr_desc, hdfgrtr_masks, + hdfgrtr_feat_map, FEAT_FGT); +static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = { NEEDS_FEAT(HDFGWTR_EL2_PMSLATFR_EL1 | HDFGWTR_EL2_PMSIRR_EL1 |
@@ -649,6 +659,8 @@ static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = { NEEDS_FEAT(HDFGWTR_EL2_TRFCR_EL1, FEAT_TRF), }; +static const DECLARE_FEAT_MAP_FGT(hdfgwtr_desc, hdfgwtr_masks, + hdfgwtr_feat_map, FEAT_FGT);static const struct reg_bits_to_feat_map hfgitr_feat_map[] = {NEEDS_FEAT (HFGITR_EL2_PSBCSYNC , FEAT_SPEv1p5),
@@ -723,6 +735,9 @@ static const struct reg_bits_to_feat_map hfgitr_feat_map[] = { NEVER_FGU, FEAT_AA64EL1), }; +static const DECLARE_FEAT_MAP_FGT(hfgitr_desc, hfgitr_masks, + hfgitr_feat_map, FEAT_FGT); +static const struct reg_bits_to_feat_map hafgrtr_feat_map[] = { NEEDS_FEAT(HAFGRTR_EL2_AMEVTYPER115_EL0 | HAFGRTR_EL2_AMEVTYPER114_EL0 |
@@ -765,6 +780,9 @@ static const struct reg_bits_to_feat_map hafgrtr_feat_map[] = { FEAT_AMUv1), }; +static const DECLARE_FEAT_MAP_FGT(hafgrtr_desc, hafgrtr_masks, + hafgrtr_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)
@@ -1122,20 +1140,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_desc (const struct reg_feat_map_desc *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_desc (&hfgrtr_desc); +check_reg_desc (&hfgwtr_desc); +check_reg_desc (&hfgitr_desc); +check_reg_desc (&hdfgrtr_desc); +check_reg_desc (&hdfgwtr_desc); +check_reg_desc (&hafgrtr_desc);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),
@@ -1190,7 +1213,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;
@@ -1206,6 +1229,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_feat_map_desc *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,
@@ -1223,30 +1269,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_desc, +0 ,NEVER_FGU ); + val |=compute_reg_res0_bits (kvm, &hfgwtr_desc, +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_desc, +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_desc, +0 ,NEVER_FGU ); + val |=compute_reg_res0_bits (kvm, &hdfgwtr_desc, +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_desc, +0 ,NEVER_FGU );break ;case HFGRTR2_GROUP : val |= compute_res0_bits(kvm, hfgrtr2_feat_map,
@@ -1282,39 +1322,27 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *rswitch (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_desc,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_desc,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_desc,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_desc,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_desc,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_desc,0 ,0 ); *res1 =HAFGRTR_EL2_RES1 ;break ;case HFGRTR2_EL2 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 4/10 KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers
In reply to Marc ZyngierSimilarly to the FEAT_FGT registers, add the dependency between the registers and the controlling feature.
WHile we're at it, add the missing checks for the RES0 vs valid bit overlap.
--- arch/arm64/kvm/config.c | 67 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 30 deletions(-)
arch/arm64/kvm/config.c +37 -30
@@ -212,6 +212,7 @@ struct reg_feat_map_desc {#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, IMPstatic bool not_feat_aa64el3 (struct kvm *kvm)
@@ -788,6 +789,9 @@ static const struct reg_bits_to_feat_map hfgitr2_feat_map[] = {NEEDS_FEAT (HFGITR2_EL2_TSBCSYNC , FEAT_TRBEv1p1) }; +static const DECLARE_FEAT_MAP_FGT(hfgitr2_desc, hfgitr2_masks, + hfgitr2_feat_map, FEAT_FGT2); +static const struct reg_bits_to_feat_map hfgrtr2_feat_map[] = {NEEDS_FEAT (HFGRTR2_EL2_nPFAR_EL1,FEAT_PFAR ),NEEDS_FEAT (HFGRTR2_EL2_nERXGSR_EL1, FEAT_RASv2),
@@ -807,6 +811,9 @@ static const struct reg_bits_to_feat_map hfgrtr2_feat_map[] = { NEEDS_FEAT(HFGRTR2_EL2_nRCWSMASK_EL1, FEAT_THE), }; +static const DECLARE_FEAT_MAP_FGT(hfgrtr2_desc, hfgrtr2_masks, + hfgrtr2_feat_map, FEAT_FGT2); +static const struct reg_bits_to_feat_map hfgwtr2_feat_map[] = {NEEDS_FEAT (HFGWTR2_EL2_nPFAR_EL1,FEAT_PFAR ), NEEDS_FEAT(HFGWTR2_EL2_nACTLRALIAS_EL1 |
@@ -825,6 +832,9 @@ static const struct reg_bits_to_feat_map hfgwtr2_feat_map[] = { NEEDS_FEAT(HFGWTR2_EL2_nRCWSMASK_EL1, FEAT_THE), }; +static const DECLARE_FEAT_MAP_FGT(hfgwtr2_desc, hfgwtr2_masks, + hfgwtr2_feat_map, FEAT_FGT2); +static const struct reg_bits_to_feat_map hdfgrtr2_feat_map[] = {NEEDS_FEAT (HDFGRTR2_EL2_nMDSELR_EL1, FEAT_Debugv8p9),NEEDS_FEAT (HDFGRTR2_EL2_nPMECR_EL1, feat_ebep_pmuv3_ss),
@@ -855,6 +865,9 @@ static const struct reg_bits_to_feat_map hdfgrtr2_feat_map[] = { NEEDS_FEAT(HDFGRTR2_EL2_nTRBMPAM_EL1, feat_trbe_mpam), }; +static const DECLARE_FEAT_MAP_FGT(hdfgrtr2_desc, hdfgrtr2_masks, + hdfgrtr2_feat_map, FEAT_FGT2); +static const struct reg_bits_to_feat_map hdfgwtr2_feat_map[] = {NEEDS_FEAT (HDFGWTR2_EL2_nMDSELR_EL1, FEAT_Debugv8p9),NEEDS_FEAT (HDFGWTR2_EL2_nPMECR_EL1, feat_ebep_pmuv3_ss),
@@ -883,6 +896,10 @@ static const struct reg_bits_to_feat_map hdfgwtr2_feat_map[] = { NEEDS_FEAT(HDFGWTR2_EL2_nTRBMPAM_EL1, feat_trbe_mpam), }; +static const DECLARE_FEAT_MAP_FGT(hdfgwtr2_desc, hdfgwtr2_masks, + hdfgwtr2_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 ),
@@ -1159,6 +1176,11 @@ void __init check_feature_map(void)check_reg_desc (&hdfgrtr_desc);check_reg_desc (&hdfgwtr_desc);check_reg_desc (&hafgrtr_desc); +check_reg_desc (&hfgrtr2_desc); +check_reg_desc (&hfgwtr2_desc); +check_reg_desc (&hfgitr2_desc); +check_reg_desc (&hdfgrtr2_desc); +check_reg_desc (&hdfgwtr2_desc);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),
@@ -1289,25 +1311,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_desc, +0 ,NEVER_FGU ); + val |=compute_reg_res0_bits (kvm, &hfgwtr2_desc, +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_desc, +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_desc, +0 ,NEVER_FGU ); + val |=compute_reg_res0_bits (kvm, &hdfgwtr2_desc, +0 ,NEVER_FGU );break ;default :BUG ();
@@ -1346,33 +1363,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_desc,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_desc,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_desc,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_desc,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_desc,0 ,0 ); *res1 =HDFGWTR2_EL2_RES1 ;break ;case HCRX_EL2 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 5/10 KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2
In reply to Marc ZyngierAdd the dependency between the HCRX_EL2 register and FEAT_HCX.
--- arch/arm64/kvm/config.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
arch/arm64/kvm/config.c +7 -5
@@ -214,6 +214,7 @@ struct reg_feat_map_desc {#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, IMPstatic bool not_feat_aa64el3 (struct kvm *kvm) {
@@ -929,6 +930,10 @@ static const struct reg_bits_to_feat_map hcrx_feat_map[] = { NEEDS_FEAT(HCRX_EL2_EnAS0, FEAT_LS64_ACCDATA), }; + +static const DECLARE_FEAT_MAP(hcrx_desc, __HCRX_EL2, + hcrx_feat_map, FEAT_HCX); +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),
@@ -1181,8 +1186,7 @@ void __init check_feature_map(void)check_reg_desc (&hfgitr2_desc);check_reg_desc (&hdfgrtr2_desc);check_reg_desc (&hdfgwtr2_desc); -check_feat_map (hcrx_feat_map,ARRAY_SIZE (hcrx_feat_map), - __HCRX_EL2_RES0,"HCRX_EL2" ); +check_reg_desc (&hcrx_desc);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),
@@ -1383,9 +1387,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_desc,0 ,0 ); *res1 = __HCRX_EL2_RES1;break ;case HCR_EL2 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 6/10 KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits()
In reply to Marc ZyngierWhile HCR_EL2 is unlikely to ever be RES0 (at least when NV is on), but consistency doesn't hurt, and it can be described in the same way as the other registers.
Convert it over to the new RES0-computing infrastructure.
--- arch/arm64/kvm/config.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-)
arch/arm64/kvm/config.c +14 -16
@@ -136,6 +136,7 @@ struct reg_feat_map_desc {#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
@@ -1005,6 +1006,9 @@ static const struct reg_bits_to_feat_map hcr_feat_map[] = { NEEDS_FEAT_FIXED(HCR_EL2_E2H, compute_hcr_e2h), }; +static const DECLARE_FEAT_MAP(hcr_desc, HCR_EL2, + hcr_feat_map, FEAT_AA64EL2); +static const struct reg_bits_to_feat_map sctlr2_feat_map[] = { NEEDS_FEAT(SCTLR2_EL1_NMEA | SCTLR2_EL1_EASE,
@@ -1187,8 +1191,7 @@ void __init check_feature_map(void)check_reg_desc (&hdfgrtr2_desc);check_reg_desc (&hdfgwtr2_desc);check_reg_desc (&hcrx_desc); -check_feat_map (hcr_feat_map,ARRAY_SIZE (hcr_feat_map), -HCR_EL2_RES0 ,"HCR_EL2" ); +check_reg_desc (&hcr_desc);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),
@@ -1278,15 +1281,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_feat_map_desc *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)
@@ -1391,12 +1392,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_desc, &fixed,0 ,0 ); + *res0 =compute_reg_res0_bits (kvm, &hcr_desc,0 ,0 ); + *res0 |= (mask & ~fixed); *res1 =HCR_EL2_RES1 | (mask & fixed);break ;case SCTLR2_EL1 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 7/10 KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2}
In reply to Marc ZyngierEnforce that SCTLR2_EL{1,2} are RES0 when FEAT_SCTLR2 isn't present.
--- arch/arm64/kvm/config.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm64/kvm/config.c +5 -5
@@ -1026,6 +1026,9 @@ static const struct reg_bits_to_feat_map sctlr2_feat_map[] = { FEAT_CPA2), }; +static const DECLARE_FEAT_MAP(sctlr2_desc, SCTLR2_EL1, + sctlr2_feat_map, FEAT_SCTLR2); +static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = { NEEDS_FEAT(TCR2_EL2_FNG1 | TCR2_EL2_FNG0 |
@@ -1192,8 +1195,7 @@ void __init check_feature_map(void)check_reg_desc (&hdfgwtr2_desc);check_reg_desc (&hcrx_desc);check_reg_desc (&hcr_desc); -check_feat_map (sctlr2_feat_map,ARRAY_SIZE (sctlr2_feat_map), -SCTLR2_EL1_RES0 ,"SCTLR2_EL1" ); +check_reg_desc (&sctlr2_desc);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),
@@ -1399,9 +1401,7 @@ void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *rbreak ;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_desc,0 ,0 ); *res1 =SCTLR2_EL1_RES1 ;break ;case TCR2_EL2 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 8/10 KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2
In reply to Marc ZyngierEnforce that TCR2_EL2 are RES0 when FEAT_TCR2 isn't present.
--- arch/arm64/kvm/config.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm64/kvm/config.c +5 -5
@@ -1051,6 +1051,9 @@ static const struct reg_bits_to_feat_map tcr2_el2_feat_map[] = { NEEDS_FEAT(TCR2_EL2_PIE, FEAT_S1PIE), }; +static const DECLARE_FEAT_MAP(tcr2_el2_desc, TCR2_EL2, + tcr2_el2_feat_map, FEAT_TCR2); +static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = { NEEDS_FEAT(SCTLR_EL1_CP15BEN | SCTLR_EL1_ITD |
@@ -1196,8 +1199,7 @@ void __init check_feature_map(void)check_reg_desc (&hcrx_desc);check_reg_desc (&hcr_desc);check_reg_desc (&sctlr2_desc); -check_feat_map (tcr2_el2_feat_map,ARRAY_SIZE (tcr2_el2_feat_map), -TCR2_EL2_RES0 ,"TCR2_EL2" ); +check_reg_desc (&tcr2_el2_desc);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),
@@ -1405,9 +1407,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_desc,0 ,0 ); *res1 =TCR2_EL2_RES1 ;break ;case SCTLR_EL1 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 9/10 KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits()
In reply to Marc ZyngierWhile SCTLR_EL1 cannot be RES0, convert it to the same infrastructure anyway, as it make things cleaner.
--- arch/arm64/kvm/config.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
arch/arm64/kvm/config.c +5 -5
@@ -1128,6 +1128,9 @@ static const struct reg_bits_to_feat_map sctlr_el1_feat_map[] = { FEAT_AA64EL1), }; +static const DECLARE_FEAT_MAP(sctlr_el1_desc, SCTLR_EL1, + sctlr_el1_feat_map, FEAT_AA64EL1); +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),
@@ -1200,8 +1203,7 @@ void __init check_feature_map(void)check_reg_desc (&hcr_desc);check_reg_desc (&sctlr2_desc);check_reg_desc (&tcr2_el2_desc); -check_feat_map (sctlr_el1_feat_map,ARRAY_SIZE (sctlr_el1_feat_map), -SCTLR_EL1_RES0 ,"SCTLR_EL1" ); +check_reg_desc (&sctlr_el1_desc);check_feat_map (mdcr_el2_feat_map,ARRAY_SIZE (mdcr_el2_feat_map),MDCR_EL2_RES0 ,"MDCR_EL2" ); }
@@ -1411,9 +1413,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_desc,0 ,0 ); *res1 =SCTLR_EL1_RES1 ;break ;case MDCR_EL2 :
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v2 10/10 KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
In reply to Marc ZyngierWhile MDCR_EL2 cannot be RES0, convert it to the same infrastructure anyway, as it make things cleaner.
--- arch/arm64/kvm/config.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/arm64/kvm/config.c +5 -4
@@ -1162,6 +1162,9 @@ static const struct reg_bits_to_feat_map mdcr_el2_feat_map[] = { FEAT_AA64EL1), }; +static const DECLARE_FEAT_MAP(mdcr_el2_desc, MDCR_EL2, + mdcr_el2_feat_map, FEAT_AA64EL2); +static void __init check_feat_map (const struct reg_bits_to_feat_map *map,int map_size,u64 res0,const char *str) {
@@ -1204,8 +1207,7 @@ void __init check_feature_map(void)check_reg_desc (&sctlr2_desc);check_reg_desc (&tcr2_el2_desc);check_reg_desc (&sctlr_el1_desc); -check_feat_map (mdcr_el2_feat_map,ARRAY_SIZE (mdcr_el2_feat_map), -MDCR_EL2_RES0 ,"MDCR_EL2" ); +check_reg_desc (&mdcr_el2_desc); }static bool idreg_feat_match (struct kvm *kvm,const struct reg_bits_to_feat_map *map)
@@ -1417,8 +1419,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_desc,0 ,0 ); *res0 |=MDCR_EL2_RES0 ; *res1 =MDCR_EL2_RES1 ;break ;
Signature · 1 line
2.39.2
Re: [PATCH v2 10/10] KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
Hi Marc,
Quoted 12 lines · Marc Zyngier
While
MDCR_EL2cannot be RES0, convert it to the same infrastructure anyway, as it make things cleaner.Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/kvm/config.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)arch/arm64/kvm/config.c +0
-0
[...]
arch/arm64/kvm/config.c void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r · line 1425
Quoted 10 lines
arch/arm64/kvm/config.c +1
-2@@ -1417,8 +1419,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_desc,0 ,0 ); *res0 |=MDCR_EL2_RES0 ; *res1 =MDCR_EL2_RES1 ;break ;
The patch itself looks fine to me but I am confused as to why MDCR_EL2 is the only switch case where we have:
*res0 |= <reg>_RES0;
Should this not be present in the other cases?
Thanks,
Ben
Marc Zyngier
maintainerRe: [PATCH v2 10/10] KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
Hi Ben,
Quoted 31 lines · Ben Horgan
Hi Marc,
Quoted 12 lines · Marc Zyngier
While
MDCR_EL2cannot be RES0, convert it to the same infrastructure anyway, as it make things cleaner.Signed-off-by Marc Zyngier <[email protected]>--- arch/arm64/kvm/config.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)arch/arm64/kvm/config.c +0
-0[...]
arch/arm64/kvm/config.c void get_reg_fixed_bits(struct kvm *kvm, enum vcpu_sysreg reg, u64 *res0, u64 *r · line 1425
Quoted 10 lines
arch/arm64/kvm/config.c +1
-2@@ -1417,8 +1419,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_desc,0 ,0 ); *res0 |=MDCR_EL2_RES0 ; *res1 =MDCR_EL2_RES1 ;break ;The patch itself looks fine to me but I am confused as to why
MDCR_EL2is the only switch case where we have:
Quoted 3 lines
*res0 |= <reg>_RES0;
Should this not be present in the other cases?
No, the RES0 bits should already be factored in from compute_reg_res0_bits(), and this line is only a benign leftover. I'll fix this before merging the series.
Thanks for the heads up,
M.
Signature · 1 line
Jazz isn't dead. It just smells funny.
Quoted 19 lines · Marc Zyngier
[After yesterday's blunder, I'm reposting this, with proper commit
messages, and having taken Oliver's feedback into account.]When a feature is removed from a guest, we ensure that the trap and control bits for that particular feature are made RES0.
For example,
SCTLR2_EL2contains a large number of bits. For any featureFEAT_FOOthat is controlled by a bit FOO inSCTLR2_EL2, we make sure that SCTLR2_EL2.FOO is RES0 ifFEAT_FOOis not visible to the guest.However, nothing makes
SCTLR2_EL2RES0 ifFEAT_SCTLR2is not visible.This series aims at solving this sort of situations. It is still quite incomplete, but aims at bridging a couple of other series:
- [email protected] which wants to make EL2-related fields writable to allow migration
Quoted 6 lines
- [email protected] which wants to align the NV support with the rest of the kernel
Hopefully this helps getting to a point where we everything is sanitised according to the architecture, EL2 on the same footing as EL1, and everything migrating in every possible case.
Looks good, let it rip!
Thanks,
Oliver
Quoted 6 lines · Marc Zyngier
[After yesterday's blunder, I'm reposting this, with proper commit
messages, and having taken Oliver's feedback into account.]When a feature is removed from a guest, we ensure that the trap and control bits for that particular feature are made RES0.
Quoted 6 lines
For example,
SCTLR2_EL2contains a large number of bits. For any featureFEAT_FOOthat is controlled by a bit FOO inSCTLR2_EL2, we make sure that SCTLR2_EL2.FOO is RES0 ifFEAT_FOOis not visible to the guest.[...]
Applied to next, thanks!
[01/10] KVM: arm64: Remove duplicate FEAT_{SYSREG128,MTE2} descriptions
commit: c3b3bbd160d2014a638d40bda17909a0afd85d09
[02/10] KVM: arm64: Add reg_feat_map_desc to describe full register dependency
commit: 559442afea8812814135ec6fa33bc62c9d09f5c4
[03/10] KVM: arm64: Enforce absence of FEAT_FGT on FGT registers
commit: 7d3a4d048925d52e5511d82e479cbdcf7354aa7c
[04/10] KVM: arm64: Enforce absence of FEAT_FGT2 on FGT2 registers
commit: 338a41e83c3dab81573ac33bc30f0f36bd29cd78
[05/10] KVM: arm64: Enforce absence of FEAT_HCX on HCRX_EL2
commit: c99d62771f63116ffe54636980414fc74ab3471c
[06/10] KVM: arm64: Convert HCR_EL2 RES0 handling to compute_reg_res0_bits()
commit: efe5406c55fb3203028507555c7da2bb417a397c
[07/10] KVM: arm64: Enforce absence of FEAT_SCTLR2 on SCTLR2_EL{1,2}
commit: f89763efe86cc05f8465c7eea85a76183f218c56
[08/10] KVM: arm64: Enforce absence of FEAT_TCR2 on TCR2_EL2
commit: 4870a8c1d18897681b6f6a50288d0b6dd5e21e24
[09/10] KVM: arm64: Convert SCTLR_EL1 RES0 handling to compute_reg_res0_bits()
commit: d2a1d78ce5962b01500d09b15e2a854768552d44
[10/10] KVM: arm64: Convert MDCR_EL2 RES0 handling to compute_reg_res0_bits()
commit: ac53365990a19e808fde2758074ee31be65d1015Cheers,
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.