Do not include v9-only features in "max-v8". Do not include the prohibited v8 features in "max-v9". In tcg mode, define "max" as "max-v9".
Signed-off-by: Richard Henderson <[email protected]> --- target/arm/internals.h | 2 +- target/arm/cpu-max.c | 2 +- target/arm/tcg/cpu64.c | 162 ++++++++++++++++++++++------------ target/arm/tcg/stubs32.c | 2 +- docs/system/arm/emulation.rst | 11 ++- 5 files changed, 120 insertions(+), 59 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index f6b4e173a5..95b201dac3 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1809,7 +1809,7 @@ void aarch64_cpu_sve_finalize(ARMCPU *cpu, Error **errp); void aarch64_cpu_sme_finalize(ARMCPU *cpu, Error **errp); void aarch64_cpu_pauth_finalize(ARMCPU *cpu, Error **errp); void aarch64_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp); -void aarch64_max_tcg_initfn(Object *obj); +void aarch64_max_v9_tcg_initfn(Object *obj); void aarch64_add_pauth_properties(Object *obj); void aarch64_add_sve_properties(Object *obj); void aarch64_add_sme_properties(Object *obj); diff --git a/target/arm/cpu-max.c b/target/arm/cpu-max.c index 8d968336a8..415142acfc 100644 --- a/target/arm/cpu-max.c +++ b/target/arm/cpu-max.c @@ -109,7 +109,7 @@ static void cpu_max_initfn(Object *obj) if (!aarch64_enabled) { aarch32_max_tcg_init(cpu); } else { - aarch64_max_tcg_initfn(obj); + aarch64_max_v9_tcg_initfn(obj); } return; } diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index a5cad987d9..d54d9b8399 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -1156,11 +1156,10 @@ static void aarch64_neoverse_n2_initfn(Object *obj) } /* - * -cpu max: a CPU with as many features enabled as our emulation supports. - * The version of '-cpu max' for qemu-system-arm is defined in cpu32.c; - * this only needs to handle 64 bits. + * -cpu max-v8: an ARMv8 CPU with as many features enabled as + * our emulation supports. */ -void aarch64_max_tcg_initfn(Object *obj) +static void aarch64_max_v8_tcg_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); ARMISARegisters *isar = &cpu->isar; @@ -1234,7 +1233,7 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); /* v8.0: FEAT_SHA1 */ t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* v8.1: FEAT_SHA512 */ t = FIELD_DP64(t, ID_AA64ISAR0, CRC32, 1); /* v8.0: FEAT_CRC32 */ - t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 3); /* v9.3: FEAT_LSE128 */ + t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 2); /* v8.0: FEAT_LSE */ t = FIELD_DP64(t, ID_AA64ISAR0, RDM, 1); /* v8.0: FEAT_RDM */ t = FIELD_DP64(t, ID_AA64ISAR0, SHA3, 1); /* v8.1: FEAT_SHA3 */ t = FIELD_DP64(t, ID_AA64ISAR0, SM3, 1); /* v8.1: FEAT_SM3 */ @@ -1267,16 +1266,10 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* v8.7: FEAT_MOPS */ t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* v8.7: FEAT_HBC */ t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2); /* v8.6: FEAT_WFxT */ - t = FIELD_DP64(t, ID_AA64ISAR2, CSSC, 2); /* v9.3: FEAT_CMPBR */ - t = FIELD_DP64(t, ID_AA64ISAR2, LUT, 1); /* v9.2: FEAT_LUT */ + t = FIELD_DP64(t, ID_AA64ISAR2, CSSC, 1); /* v8.7: FEAT_CSSC */ t = FIELD_DP64(t, ID_AA64ISAR2, ATS1A, 1); /* v8.8: FEAT_ATS1A */ SET_IDREG(isar, ID_AA64ISAR2, t); - t = GET_IDREG(isar, ID_AA64ISAR3); - t = FIELD_DP64(t, ID_AA64ISAR3, FAMINMAX, 1); /* v9.2: FEAT_FAMINMAX */ - t = FIELD_DP64(t, ID_AA64ISAR3, FPRCVT, 1); /* v9.5: FEAT_FPRCVT */ - SET_IDREG(isar, ID_AA64ISAR3, t); - t = GET_IDREG(isar, ID_AA64PFR0); t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); /* v8.2: FEAT_FP16 */ t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); /* v8.2: FEAT_FP16 */ @@ -1298,17 +1291,14 @@ void aarch64_max_tcg_initfn(Object *obj) */ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); /* v8.5: FEAT_MTE3 */ t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* v8.3: FEAT_DoubleFault */ - t = FIELD_DP64(t, ID_AA64PFR1, SME, 2); /* v9.2: FEAT_SME2 */ t = FIELD_DP64(t, ID_AA64PFR1, RNDR_TRAP, 1); /* v8.4: FEAT_RNG_TRAP */ t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* v8.0: FEAT_CSV2_3 */ t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* v8.7: FEAT_NMI */ - t = FIELD_DP64(t, ID_AA64PFR1, GCS, 1); /* v9.3: FEAT_GCS */ /* v8.7: FEAT_MTE_NO_ADDRESS_TAGS + FEAT_MTE_CANONICAL_TAGS */ t = FIELD_DP64(t, ID_AA64PFR1, MTEX, 1); SET_IDREG(isar, ID_AA64PFR1, t); t = GET_IDREG(isar, ID_AA64PFR2); - t = FIELD_DP64(t, ID_AA64PFR2, FPMR, 1); /* v9.2: FEAT_FPMR */ t = FIELD_DP64(t, ID_AA64PFR2, MTEFAR, 1); /* v8.7: FEAT_MTE_TAGGED_FAR */ t = FIELD_DP64(t, ID_AA64PFR2, MTESTOREONLY, 1); /* v8.7: FEAT_MTE_STORE_ONLY */ t = FIELD_DP64(t, ID_AA64PFR2, MTEPERM, 1); /* v8.7: FEAT_MTE_PERM */ @@ -1358,25 +1348,14 @@ void aarch64_max_tcg_initfn(Object *obj) t = GET_IDREG(isar, ID_AA64MMFR3); t = FIELD_DP64(t, ID_AA64MMFR3, TCRX, 1); /* v8.0: FEAT_TCR2 */ t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1); /* v8.0: FEAT_SCTLR2 */ - t = FIELD_DP64(t, ID_AA64MMFR3, MEC, 1); /* v9.2: FEAT_MEC */ t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* v8.2: FEAT_FPACC_SPEC */ t = FIELD_DP64(t, ID_AA64MMFR3, S1PIE, 1); /* v8.8: FEAT_S1PIE */ t = FIELD_DP64(t, ID_AA64MMFR3, S2PIE, 1); /* v8.8: FEAT_S2PIE */ t = FIELD_DP64(t, ID_AA64MMFR3, AIE, 1); /* v8.8: FEAT_AIE */ SET_IDREG(isar, ID_AA64MMFR3, t); - t = GET_IDREG(isar, ID_AA64MMFR4); - t = FIELD_DP64(t, ID_AA64MMFR4, ASID2, 1); /* v9.4: FEAT_ASID2 */ - SET_IDREG(isar, ID_AA64MMFR4, t); - t = GET_IDREG(isar, ID_AA64ZFR0); - t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 2); /* v9.2: FEAT_SVE2p1 */ - t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* v9.0: FEAT_SVE_PMULL128 */ - t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* v9.0: FEAT_SVE_BitPerm */ t = FIELD_DP64(t, ID_AA64ZFR0, BFLOAT16, 2); /* v8.2: FEAT_EBF16 */ - t = FIELD_DP64(t, ID_AA64ZFR0, B16B16, 1); /* v9.2: FEAT_SVE_B16B16 */ - t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1); /* v9.0: FEAT_SVE_SHA3 */ - t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1); /* v9.0: FEAT_SVE_SM4 */ t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); /* v8.1: FEAT_I8MM */ t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); /* v8.2: FEAT_F32MM */ t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); /* v8.2: FEAT_F64MM */ @@ -1388,6 +1367,106 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64DFR0, HPMN0, 1); /* v8.5: FEAT_HPMN0 */ SET_IDREG(isar, ID_AA64DFR0, t); + /* Replicate the same data to the 32-bit id registers. */ + aa32_max_features(cpu); + +#ifdef CONFIG_USER_ONLY + /* + * For usermode -cpu max we can use a larger and more efficient DCZ + * blocksize since we don't have to follow what the hardware does. + */ + cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ + set_dczid_bs(cpu, 7); /* 512 bytes */ +#endif + + /* v8.2: FEAT_SVE */ + cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ); + aarch64_add_sve_properties(OBJECT(cpu)); + object_property_add(OBJECT(cpu), "sve-max-vq", "uint32", + cpu_max_get_sve_max_vq, cpu_max_set_sve_max_vq, + NULL, NULL); + + /* v8.2: FEAT_PAuth2 */ + aarch64_add_pauth_properties(OBJECT(cpu)); + + /* v8.4: FEAT_MTE2 */ + cpu->gm_blocksize = 6; /* 256 bytes */ + + /* v8.6: FEAT_LPA2 */ + qdev_property_add_static(DEVICE(cpu), &arm_cpu_lpa2_property); +} + +/* + * -cpu max-v9: an ARMv9 CPU with as many features enabled as + * our emulation supports. + */ +void aarch64_max_v9_tcg_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + ARMISARegisters *isar = &cpu->isar; + uint64_t t; + + /* Armv9.0 is based on a minimum of Armv8.5. */ + aarch64_max_v8_tcg_initfn(obj); + + /* + * Armv9.0 does not support AArch32 except at EL0, + * therefore indicate EL1 through EL3 are AArch64-only. + */ + t = GET_IDREG(isar, ID_AA64PFR0); + t = FIELD_DP64(t, ID_AA64PFR0, EL1, 1); + t = FIELD_DP64(t, ID_AA64PFR0, EL2, 1); + t = FIELD_DP64(t, ID_AA64PFR0, EL3, 1); + SET_IDREG(isar, ID_AA64PFR0, t); + + /* v9.0 prohibits FEAT_DoubleLock. */ + FIELD_DP64_IDREG(isar, ID_AA64DFR0, DOUBLELOCK, -1); + FIELD_DP64_IDREG(isar, ID_AA64PFR0, RAS, 1); + isar->dbgdevid = FIELD_DP32(isar->dbgdevid, DBGDEVID, DOUBLELOCK, 0); + + /* + * Below, note the revision from which the feature is OPTIONAL. + */ + t = GET_IDREG(isar, ID_AA64ISAR0); + t = FIELD_DP64(t, ID_AA64ISAR0, ATOMIC, 3); /* v9.3: FEAT_LSE128 */ + SET_IDREG(isar, ID_AA64ISAR0, t); + + t = GET_IDREG(isar, ID_AA64ISAR2); + t = FIELD_DP64(t, ID_AA64ISAR2, CSSC, 2); /* v9.3: FEAT_CMPBR */ + t = FIELD_DP64(t, ID_AA64ISAR2, LUT, 1); /* v9.2: FEAT_LUT */ + SET_IDREG(isar, ID_AA64ISAR2, t); + + t = GET_IDREG(isar, ID_AA64ISAR3); + t = FIELD_DP64(t, ID_AA64ISAR3, FAMINMAX, 1); /* v9.2: FEAT_FAMINMAX */ + t = FIELD_DP64(t, ID_AA64ISAR3, FPRCVT, 1); /* v9.5: FEAT_FPRCVT */ + SET_IDREG(isar, ID_AA64ISAR3, t); + + t = GET_IDREG(isar, ID_AA64PFR1); + t = FIELD_DP64(t, ID_AA64PFR1, SME, 2); /* v9.2: FEAT_SME2 */ + t = FIELD_DP64(t, ID_AA64PFR1, GCS, 1); /* v9.3: FEAT_GCS */ + SET_IDREG(isar, ID_AA64PFR1, t); + + t = GET_IDREG(isar, ID_AA64PFR2); + t = FIELD_DP64(t, ID_AA64PFR2, FPMR, 1); /* v9.2: FEAT_FPMR */ + SET_IDREG(isar, ID_AA64PFR2, t); + + t = GET_IDREG(isar, ID_AA64MMFR3); + t = FIELD_DP64(t, ID_AA64MMFR3, MEC, 1); /* v9.2: FEAT_MEC */ + SET_IDREG(isar, ID_AA64MMFR3, t); + + t = GET_IDREG(isar, ID_AA64MMFR4); + t = FIELD_DP64(t, ID_AA64MMFR4, ASID2, 1); /* v9.4: FEAT_ASID2 */ + SET_IDREG(isar, ID_AA64MMFR4, t); + + t = GET_IDREG(isar, ID_AA64ZFR0); + t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 2); /* v9.2: FEAT_SVE2p1 */ + t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* v9.0: FEAT_SVE_PMULL128 */ + t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); /* v9.0: FEAT_SVE_BitPerm */ + t = FIELD_DP64(t, ID_AA64ZFR0, B16B16, 1); /* v9.2: FEAT_SVE_B16B16 */ + t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1); /* v9.0: FEAT_SVE_SHA3 */ + t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1); /* v9.0: FEAT_SVE_SM4 */ + SET_IDREG(isar, ID_AA64ZFR0, t); + t = GET_IDREG(isar, ID_AA64SMFR0); t = FIELD_DP64(t, ID_AA64SMFR0, SMOP4, 1); /* v9.4: FEAT_SME_MOP4 */ t = FIELD_DP64(t, ID_AA64SMFR0, STMOP, 1); /* v9.4: FEAT_SME_TMOP */ @@ -1424,43 +1503,16 @@ void aarch64_max_tcg_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64FPFR0, F8CVT, 1); /* v9.2: FEAT_FP8 */ SET_IDREG(isar, ID_AA64FPFR0, t); - /* Replicate the same data to the 32-bit id registers. */ - aa32_max_features(cpu); - -#ifdef CONFIG_USER_ONLY - /* - * For usermode -cpu max we can use a larger and more efficient DCZ - * blocksize since we don't have to follow what the hardware does. - */ - cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */ - set_dczid_bs(cpu, 7); /* 512 bytes */ -#endif - - /* v8.4: FEAT_MTE2 */ - cpu->gm_blocksize = 6; /* 256 bytes */ - - /* v8.2: FEAT_SVE */ - cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ); - aarch64_add_sve_properties(obj); - object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, - cpu_max_set_sve_max_vq, NULL, NULL); - /* v9.2: FEAT_SME */ cpu->sme_vq.supported = SVE_VQ_POW2_MAP; aarch64_add_sme_properties(obj); - /* v8.2: FEAT_PAuth2 */ - aarch64_add_pauth_properties(obj); - /* v9.1: FEAT_RME */ object_property_add_bool(obj, "x-rme", cpu_arm_get_rme, cpu_arm_set_rme); /* v9.4: FEAT_RME_GPC2 */ object_property_add(obj, "x-l0gptsz", "uint32", cpu_max_get_l0gptsz, cpu_max_set_l0gptsz, NULL, NULL); - - /* v8.6: FEAT_LPA2 */ - qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property); } static const ARMCPUInfo aarch64_cpus[] = { @@ -1478,8 +1530,8 @@ static const ARMCPUInfo aarch64_cpus[] = { { .name = "neoverse-n1", .initfn = aarch64_neoverse_n1_initfn }, { .name = "neoverse-v1", .initfn = aarch64_neoverse_v1_initfn }, { .name = "neoverse-n2", .initfn = aarch64_neoverse_n2_initfn }, - { .name = "max-v8", .initfn = aarch64_max_tcg_initfn }, - { .name = "max-v9", .initfn = aarch64_max_tcg_initfn }, + { .name = "max-v8", .initfn = aarch64_max_v8_tcg_initfn }, + { .name = "max-v9", .initfn = aarch64_max_v9_tcg_initfn }, }; static void aarch64_cpu_register_types(void) diff --git a/target/arm/tcg/stubs32.c b/target/arm/tcg/stubs32.c index 78f819ef6f..939cea7189 100644 --- a/target/arm/tcg/stubs32.c +++ b/target/arm/tcg/stubs32.c @@ -28,7 +28,7 @@ void aarch64_host_initfn(Object *obj) g_assert_not_reached(); } -void aarch64_max_tcg_initfn(Object *obj) +void aarch64_max_v9_tcg_initfn(Object *obj) { g_assert_not_reached(); } diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index cc42db9e0b..0a1a5bec93 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -230,7 +230,16 @@ to the `Arm Architecture Reference Manual for A-profile architecture When a specific named CPU is being emulated, only those features which are present in hardware for that CPU are emulated. (If a feature is not in the list above then it is not supported, even if the real -hardware should have it.) The ``max`` CPU enables all features. +hardware should have it.) + +The ``max-v8`` CPU enables all of the listed Armv8-A architecture +extensions but none of the Armv9-A architecture extensions. + +The ``max-v9`` CPU enables all of the listed extensions except for +those that are prohibited by the Armv9-A architecture: FEAT_AA32EL1, +FEAT_AA32EL2, FEAT_AA32EL3, and FEAT_DoubleLock. + +The ``max`` CPU is an alias for ``max-v9`` under TCG emulation. R-profile CPU architecture support ================================== -- 2.43.0
