In our handling of the boolean 'sme' CPU property, we write this 0/1 value directly to ID_AA64PFR1_EL1.SME. This worked when the only valid values in that field were 0 (for no SME) and 1 (for SME1). However, with the addition of SME2 the SME field can now also read 2. This means that "-cpu max,sme=on" will result in an inconsistent set of ID registers, where ID_AA64PFR1_EL1.SME claims SME1 but ID_AA64SMFR0_EL1.SMEver claims SME2p1. This isn't a valid thing to report, and confuses Linux into reporting SME2 to userspace but not actually enabling userspace access for it.
Fix this bug by having arm_cpu_sme_finalize() fix up the ID_AA64PFR1_EL1.SME field to match ID_AA64SMFR0.SMEver. This means the "sme" property's semantics are "off" for "no SME" and "on" for "enable at whatever the default SME version this CPU provides is". Update the documentation to clarify what 'sve=on' and 'sme=on' do. (We don't have the equivalent bug for 'sve=on' because ID_AA64PFR0_EL1.SVE only has 0 and 1 as valid values, but the semantics of the property are the same.) Cc: [email protected] Signed-off-by: Peter Maydell <[email protected]> --- docs/system/arm/cpu-features.rst | 10 ++++++++++ target/arm/cpu64.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index 37d5dfd15b..024119449c 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -318,6 +318,11 @@ SVE CPU Property Parsing Semantics provided an error will be generated. To avoid this error, one must enable at least one vector length prior to enabling SVE. + 10) Enabling SVE (with ``sve=on`` or by default) enables all the SVE + sub-features that the CPU supports (for example, it may also + enable SVE2). There are not generally any lower-level controls + for disabling specific SVE sub-features. + SVE CPU Property Examples ------------------------- @@ -430,6 +435,11 @@ and all vector lengths must be powers of 2. The maximum vector length supported by qemu is 2048 bits. Otherwise, there are no additional constraints on the set of vector lengths supported by SME. +As with SVE, ``sme=on`` enables all the SME sub-features the CPU +supports (for example, it may also enable SME2), and there are +no lower-level controls for fine-grained disabling of specific +SME sub-features. + SME User-mode Default Vector Length Property -------------------------------------------- diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 4dfc03973e..26873a39b4 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -363,6 +363,16 @@ void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp) cpu->sme_vq.map = vq_map; cpu->sme_max_vq = 32 - clz32(vq_map); + + /* + * The "sme" property setter writes a bool value into ID_AA64PFR1_EL1.SME + * (and at this point we know it's not 0). Correct that value to report + * the same SME version as ID_AA64SMFR0_EL1.SMEver. + */ + if (FIELD_EX64_IDREG(&cpu->isar, ID_AA64SMFR0, SMEVER) != 0) { + /* SME2 or better */ + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, 2); + } } static bool cpu_arm_get_sme(Object *obj, Error **errp) @@ -375,6 +385,11 @@ static void cpu_arm_set_sme(Object *obj, bool value, Error **errp) { ARMCPU *cpu = ARM_CPU(obj); + /* + * For now, write 0 for "off" and 1 for "on" into the PFR1 field. + * We will correct this value to report the right SME + * level (SME vs SME2) in arm_cpu_sme_finalize() later. + */ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR1, SME, value); } -- 2.43.0
