On Fri, Mar 06, 2026 at 05:01:09PM +0000, Mark Brown wrote:
> The primary register for identifying SME is ID_AA64PFR1_EL1.SME. This
> is hidden from guests unless SME is enabled by the VMM.
> When it is visible it is writable and can be used to control the
> availability of SME2.
>
> There is also a new register ID_AA64SMFR0_EL1 which we make writable,
> forcing it to all bits 0 if SME is disabled. This includes the field
> SMEver giving the SME version, userspace is responsible for ensuring
> the value is consistent with ID_AA64PFR1_EL1.SME. It also includes
> FA64, a separately enableable extension which provides the full FPSIMD
> and SVE instruction set including FFR in streaming mode. Userspace can
> control the availability of FA64 by writing to this field. The other
> features enumerated there only add new instructions, there are no
> architectural controls for these.
>
> There is a further identification register SMIDR_EL1 which provides a
> basic description of the SME microarchitecture, in a manner similar to
> MIDR_EL1 for the PE. It also describes support for priority management
> and a basic affinity description for shared SME units, plus some RES0
> space. We do not support priority management for guests so this is
> hidden from guests, along with any new fields.
>
> As for MIDR_EL1 and REVIDR_EL1 we expose the implementer and revision
> information to guests with the raw value from the CPU we are running on,
> this may present issues for asymmetric systems or for migration as it
> does for the existing registers.
>
> Signed-off-by: Mark Brown <[email protected]>
...
> +#define IMPLEMENTATION_ID_FILTERED(reg, mask, reg_visibility) { \
> + SYS_DESC(SYS_##reg), \
> + .access = access_imp_id_reg, \
> + .get_user = get_id_reg, \
> + .set_user = set_imp_id_reg, \
> + .reset = reset_imp_id_reg, \
> + .visibility = reg_visibility, \
nit: rogue backslash
> + .val = mask, \
> + }
> +
> static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
> {
> __vcpu_assign_sys_reg(vcpu, r->reg, vcpu->kvm->arch.nr_pmu_counters);
> @@ -3238,7 +3280,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> ID_AA64PFR1_EL1_MTE_frac |
> ID_AA64PFR1_EL1_NMI |
> ID_AA64PFR1_EL1_RNDR_trap |
> - ID_AA64PFR1_EL1_SME |
> ID_AA64PFR1_EL1_RES0 |
> ID_AA64PFR1_EL1_MPAM_frac |
> ID_AA64PFR1_EL1_MTE)),
> @@ -3248,7 +3289,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> ID_AA64PFR2_EL1_MTESTOREONLY),
> ID_UNALLOCATED(4,3),
> ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0),
> - ID_HIDDEN(ID_AA64SMFR0_EL1),
> + ID_WRITABLE(ID_AA64SMFR0_EL1, ~ID_AA64SMFR0_EL1_RES0),
> ID_UNALLOCATED(4,6),
> ID_WRITABLE(ID_AA64FPFR0_EL1, ~ID_AA64FPFR0_EL1_RES0),
>
> @@ -3454,6 +3495,13 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> { SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr },
> { SYS_DESC(SYS_CLIDR_EL1), access_clidr, reset_clidr, CLIDR_EL1,
> .set_user = set_clidr, .val = ~CLIDR_EL1_RES0 },
> + IMPLEMENTATION_ID_FILTERED(SMIDR_EL1,
> + (SMIDR_EL1_NSMC | SMIDR_EL1_HIP |
> + SMIDR_EL1_AFFINITY2 |
> + SMIDR_EL1_IMPLEMENTER |
> + SMIDR_EL1_REVISION | SMIDR_EL1_SH |
> + SMIDR_EL1_AFFINITY),
> + sme_visibility),
Shouldn't we sanitize the SMIDR value obtained in reset_imp_id_reg() and
add SMPS to this mask, if we're hiding everything from the guest?
Thanks,
Jean
> IMPLEMENTATION_ID(AIDR_EL1, GENMASK_ULL(63, 0)),
> { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 },
> ID_FILTERED(CTR_EL0, ctr_el0,
>
> --
> 2.47.3
>
>