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 <peter.maydell@linaro.org>
---
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