The ID register ID_AA64ZFR0_EL1's fields are not all for SVE exclusive features; some are also used to describe SME on an SME-only CPU:
SVE-only fields: * F64MM, F32MM, F16MM, SM4, B16B16, SVEVer Fields used for SVE and SME (in some cases there is also a field for SME in ID_AA64SMFR0_EL1, but it is just a "present or absent" single bit flag and the ZFR0 field then tells you what level of support is present): * I8MM, SHA3, BF16, BitPerm, EltPerm, AES Currently we zero the whole ID_AA64ZFR0_EL1 register in arm_cpu_sve_finalize() if SVE is not present, which wipes also the fields we need for SME. Only clear the fields which are SVE-specific here, and clear the rest in arm_cpu_sme_finalize() if we have neither SME nor SVE. This requires us to update our ID_AA64ZFR0 field definitions to match the rev M.a.a Arm ARM, as the F16MM SVE-only field is not one we had a definition for previously. Signed-off-by: Peter Maydell <[email protected]> --- target/arm/cpu-features.h | 2 ++ target/arm/cpu64.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 1bcf28ab08..e0b7a45b7b 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -367,12 +367,14 @@ FIELD(ID_AA64DFR0, HPMN0, 60, 4) FIELD(ID_AA64ZFR0, SVEVER, 0, 4) FIELD(ID_AA64ZFR0, AES, 4, 4) +FIELD(ID_AA64ZFR0, ELTPERM, 12, 4) FIELD(ID_AA64ZFR0, BITPERM, 16, 4) FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4) FIELD(ID_AA64ZFR0, B16B16, 24, 4) FIELD(ID_AA64ZFR0, SHA3, 32, 4) FIELD(ID_AA64ZFR0, SM4, 40, 4) FIELD(ID_AA64ZFR0, I8MM, 44, 4) +FIELD(ID_AA64ZFR0, F16MM, 48, 4) FIELD(ID_AA64ZFR0, F32MM, 52, 4) FIELD(ID_AA64ZFR0, F64MM, 56, 4) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 26873a39b4..a9c1e60c95 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -133,9 +133,17 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) if (!cpu_isar_feature(aa64_sve, cpu)) { /* * SVE is disabled and so are all vector lengths. Good. - * Disable all SVE extensions as well. + * Disable all SVE extensions as well. Note that some ZFR0 + * fields are used also by SME so must not be wiped in + * an SME-no-SVE config. We will clear the rest in + * arm_cpu_sme_finalize() if necessary. */ - SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F64MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F32MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, F16MM, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, SM4, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, B16B16, 0); + FIELD_DP64_IDREG(&cpu->isar, ID_AA64ZFR0, SVEVER, 0); return; } @@ -335,6 +343,10 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) if (vq_map == 0) { if (!cpu_isar_feature(aa64_sme, cpu)) { SET_IDREG(&cpu->isar, ID_AA64SMFR0, 0); + if (!cpu_isar_feature(aa64_sve, cpu)) { + /* This clears the "SVE or SME" fields in ZFR0 */ + SET_IDREG(&cpu->isar, ID_AA64ZFR0, 0); + } return; } -- 2.43.0
