* [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9
@ 2026-08-25 21:29 Richard Henderson
2026-08-25 21:29 ` [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn Richard Henderson
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Richard Henderson @ 2026-08-25 21:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This is something that we've talked about for quite some time,
having separate "max" cpu types for Armv{8,9}, because Armv9
prohibits some deprecated Armv8 features. Retaining all features
simultaneously has the potential to cause confusion.
Changes for v3:
- Several patches merged.
- max-v8 is also present for qemu-{system-}arm.
I realize the registration of -cpu max-v8 will need adjustment
for single-binary, but in the short term I've used an ifdef.
r~
Richard Henderson (4):
target/arm: Rename and adjust aarch32_max_v8_tcg_initfn
target/arm: Introduce cpu types max-v8 and max-v9
target/arm: Use -cpu max-v8 with aarch64=off
target/arm: Separate cpu types max-v8 and max-v9
target/arm/internals.h | 4 +-
hw/arm/sbsa-ref.c | 2 +
hw/arm/virt.c | 2 +
target/arm/cpu-max.c | 4 +-
target/arm/tcg/cpu32.c | 8 +-
target/arm/tcg/cpu64.c | 160 ++++++++++++------
target/arm/tcg/stubs32.c | 2 +-
tests/qtest/arm-cpu-features.c | 4 +-
docs/system/arm/emulation.rst | 13 +-
.../aarch64/test_virt_aarch64_off.py | 4 +-
10 files changed, 139 insertions(+), 64 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn
2026-08-25 21:29 [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
@ 2026-08-25 21:29 ` Richard Henderson
2026-08-25 21:39 ` Philippe Mathieu-Daudé
2026-08-25 21:29 ` [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2026-08-25 21:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Rename from aarch32_max_tcg_init and take an Object pointer,
in preparation from being used with TypeInit.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 2 +-
target/arm/cpu-max.c | 2 +-
target/arm/tcg/cpu32.c | 4 +++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index f6b4e173a54..fc7d5ad6f2c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1838,7 +1838,7 @@ uint32_t *arm_v7m_get_sp_ptr(CPUARMState *env, bool secure,
bool el_is_in_host(CPUARMState *env, int el);
void aa32_max_features(ARMCPU *cpu);
-void aarch32_max_tcg_init(ARMCPU *cpu);
+void aarch32_max_v8_tcg_initfn(Object *obj);
int exception_target_el(CPUARMState *env);
bool arm_singlestep_active(CPUARMState *env);
bool arm_generate_debug_exceptions(CPUARMState *env);
diff --git a/target/arm/cpu-max.c b/target/arm/cpu-max.c
index 4df52bcb08e..9ed45c8764f 100644
--- a/target/arm/cpu-max.c
+++ b/target/arm/cpu-max.c
@@ -108,7 +108,7 @@ static void cpu_max_initfn(Object *obj)
if (tcg_enabled()) {
if (!aarch64_enabled) {
- aarch32_max_tcg_init(cpu);
+ aarch32_max_v8_tcg_initfn(obj);
} else {
aarch64_max_tcg_initfn(obj);
}
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index bc07e33877a..8397f26a864 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -855,8 +855,10 @@ void aa32_max_features(ARMCPU *cpu)
FIELD_DP32_IDREG(isar, ID_DFR1, HPMN0, 1); /* FEAT_HPMN0 */
}
-void aarch32_max_tcg_init(ARMCPU *cpu)
+void aarch32_max_v8_tcg_initfn(Object *obj)
{
+ ARMCPU *cpu = ARM_CPU(obj);
+
aarch64_aa32_a57_init(cpu, false);
aa32_max_features(cpu);
#ifdef CONFIG_USER_ONLY
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9
2026-08-25 21:29 [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
2026-08-25 21:29 ` [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn Richard Henderson
@ 2026-08-25 21:29 ` Richard Henderson
2026-08-25 21:39 ` Philippe Mathieu-Daudé
2026-08-25 21:29 ` [PATCH v3 3/4] target/arm: Use -cpu max-v8 with aarch64=off Richard Henderson
2026-08-25 21:30 ` [PATCH v3 4/4] target/arm: Separate cpu types max-v8 and max-v9 Richard Henderson
3 siblings, 1 reply; 7+ messages in thread
From: Richard Henderson @ 2026-08-25 21:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Introduce the names and allow them with the virt and sbsa-ref
machine types. So far, the cpu types both exactly match "max".
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
hw/arm/sbsa-ref.c | 2 ++
hw/arm/virt.c | 2 ++
target/arm/tcg/cpu32.c | 4 ++++
target/arm/tcg/cpu64.c | 2 ++
4 files changed, 10 insertions(+)
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 484b90053e8..56d08f605c8 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -913,6 +913,8 @@ static void sbsa_ref_class_init(ObjectClass *oc, const void *data)
ARM_CPU_TYPE_NAME("neoverse-v1"),
ARM_CPU_TYPE_NAME("neoverse-n2"),
ARM_CPU_TYPE_NAME("max"),
+ ARM_CPU_TYPE_NAME("max-v8"),
+ ARM_CPU_TYPE_NAME("max-v9"),
NULL,
};
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e7a56e37f73..d738b95c726 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -4132,6 +4132,7 @@ static GPtrArray *virt_get_valid_cpu_types(const MachineState *ms)
if (tcg_enabled()) {
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a7")));
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a15")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("max-v8")));
}
if (tcg_enabled() && target_aarch64()) {
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a35")));
@@ -4143,6 +4144,7 @@ static GPtrArray *virt_get_valid_cpu_types(const MachineState *ms)
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-n1")));
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-v1")));
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("neoverse-n2")));
+ g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("max-v9")));
}
if (target_aarch64()) {
g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a53")));
diff --git a/target/arm/tcg/cpu32.c b/target/arm/tcg/cpu32.c
index 8397f26a864..12e70ded9c1 100644
--- a/target/arm/tcg/cpu32.c
+++ b/target/arm/tcg/cpu32.c
@@ -744,6 +744,10 @@ static const ARMCPUInfo arm_tcg_cpus[] = {
{ .name = "ti925t", .initfn = ti925t_initfn },
{ .name = "sa1100", .initfn = sa1100_initfn },
{ .name = "sa1110", .initfn = sa1110_initfn },
+#ifndef TARGET_AARCH64
+ /* For aarch64, max-v8 is defined in cpu64.c */
+ { .name = "max-v8", .initfn = aarch32_max_v8_tcg_initfn },
+#endif
};
static void arm_tcg_cpu_register_types(void)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index b38c61ba623..4f5375deb25 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1488,6 +1488,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 },
};
static void aarch64_cpu_register_types(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/4] target/arm: Use -cpu max-v8 with aarch64=off
2026-08-25 21:29 [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
2026-08-25 21:29 ` [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn Richard Henderson
2026-08-25 21:29 ` [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
@ 2026-08-25 21:29 ` Richard Henderson
2026-08-25 21:30 ` [PATCH v3 4/4] target/arm: Separate cpu types max-v8 and max-v9 Richard Henderson
3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2026-08-25 21:29 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm, Philippe Mathieu-Daudé
Armv9 does not support privileged aarch32 execution, so
aarch64 cannot be disabled. These tests must use Armv8.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/qtest/arm-cpu-features.c | 4 ++--
tests/functional/aarch64/test_virt_aarch64_off.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index cb4d01fd46a..7348fb8d28b 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -493,8 +493,8 @@ static void test_query_cpu_model_expansion(const void *data)
sve_tests_default(qts, "max");
pauth_tests_default(qts, "max");
- /* TCG allows us to turn off AArch64 on the 'max' CPU type */
- assert_set_feature(qts, "max", "aarch64", false);
+ /* TCG allows us to turn off AArch64 on the 'max-v8' CPU type */
+ assert_set_feature(qts, "max-v8", "aarch64", false);
}
qtest_quit(qts);
diff --git a/tests/functional/aarch64/test_virt_aarch64_off.py b/tests/functional/aarch64/test_virt_aarch64_off.py
index 13d8b73b0d7..73c9a4109c0 100755
--- a/tests/functional/aarch64/test_virt_aarch64_off.py
+++ b/tests/functional/aarch64/test_virt_aarch64_off.py
@@ -18,9 +18,9 @@ class ArmVirtMachine(LinuxKernelTest):
def test_arm_virt(self):
self.set_machine('virt')
# KVM aarch64=off requires a host CPU that supports it, so
- # restrict the test to TCG only
+ # restrict the test to TCG ARMv8.
self.require_accelerator('tcg')
- self.vm.add_args('-cpu', 'max,aarch64=off')
+ self.vm.add_args('-cpu', 'max-v8,aarch64=off')
kernel_path = self.ASSET_KERNEL.fetch()
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 4/4] target/arm: Separate cpu types max-v8 and max-v9
2026-08-25 21:29 [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
` (2 preceding siblings ...)
2026-08-25 21:29 ` [PATCH v3 3/4] target/arm: Use -cpu max-v8 with aarch64=off Richard Henderson
@ 2026-08-25 21:30 ` Richard Henderson
3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2026-08-25 21:30 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
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 <richard.henderson@linaro.org>
---
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 | 13 ++-
5 files changed, 122 insertions(+), 59 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index fc7d5ad6f2c..be32a8c531f 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 9ed45c8764f..739500a04fc 100644
--- a/target/arm/cpu-max.c
+++ b/target/arm/cpu-max.c
@@ -110,7 +110,7 @@ static void cpu_max_initfn(Object *obj)
if (!aarch64_enabled) {
aarch32_max_v8_tcg_initfn(obj);
} 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 4f5375deb25..4ef412a6575 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1166,11 +1166,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;
@@ -1244,7 +1243,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 */
@@ -1277,16 +1276,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 */
@@ -1308,17 +1301,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 */
@@ -1368,25 +1358,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 */
@@ -1398,6 +1377,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 */
@@ -1434,43 +1513,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[] = {
@@ -1488,8 +1540,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 78f819ef6ff..939cea71892 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 cc42db9e0b7..ff02435975b 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -230,7 +230,18 @@ 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 AArch64 TCG emulation,
+an alias for ``max-v8`` under AArch32 TCG emulation, or an alias
+for ``host`` under hardware virtualization.
R-profile CPU architecture support
==================================
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn
2026-08-25 21:29 ` [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn Richard Henderson
@ 2026-08-25 21:39 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-25 21:39 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 25/8/26 23:29, Richard Henderson wrote:
> Rename from aarch32_max_tcg_init and take an Object pointer,
> in preparation from being used with TypeInit.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 2 +-
> target/arm/cpu-max.c | 2 +-
> target/arm/tcg/cpu32.c | 4 +++-
> 3 files changed, 5 insertions(+), 3 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9
2026-08-25 21:29 ` [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
@ 2026-08-25 21:39 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-25 21:39 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 25/8/26 23:29, Richard Henderson wrote:
> Introduce the names and allow them with the virt and sbsa-ref
> machine types. So far, the cpu types both exactly match "max".
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> hw/arm/sbsa-ref.c | 2 ++
> hw/arm/virt.c | 2 ++
> target/arm/tcg/cpu32.c | 4 ++++
> target/arm/tcg/cpu64.c | 2 ++
> 4 files changed, 10 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-25 21:41 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 21:29 [PATCH v3 0/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
2026-08-25 21:29 ` [PATCH v3 1/4] target/arm: Rename and adjust aarch32_max_v8_tcg_initfn Richard Henderson
2026-08-25 21:39 ` Philippe Mathieu-Daudé
2026-08-25 21:29 ` [PATCH v3 2/4] target/arm: Introduce cpu types max-v8 and max-v9 Richard Henderson
2026-08-25 21:39 ` Philippe Mathieu-Daudé
2026-08-25 21:29 ` [PATCH v3 3/4] target/arm: Use -cpu max-v8 with aarch64=off Richard Henderson
2026-08-25 21:30 ` [PATCH v3 4/4] target/arm: Separate cpu types max-v8 and max-v9 Richard Henderson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.