Hi Eric,
> On 16 Oct 2026, at 5:37 PM, Eric Auger <[email protected]> wrote:
>
> !-------------------------------------------------------------------|
> CAUTION: External Email
>
> |-------------------------------------------------------------------!
>
> Hi Khushit,
>
> On 9/21/26 2:32 PM, Khushit Shah wrote:
>> Add a KVM-only named CPU model for the Armv9.0-A baseline, following
>> DDI0487 revision M.c. The property list is the architecture-mandated
>> ID-register field view.
>>
>> Pointer authentication is omitted because a v9.0-A core may implement
>> any PAuth algorithm.
>>
>> Named models start from a zeroed ID-register view, so features whose
>> "not implemented" encoding is non-zero (for example TGran64=0xF,
>> DoubleLock=0xF) are set explicitly.
>>
>> The model is not realizable on its own; implementation-defined fields
>> such as CTR_EL0.{CWG,ERG} and ID_AA64DFR0_EL1.CTX_CMPs still have to be
>> supplied on the command line. However, this provides a useful baseline
>> for upcoming reference core models.
>>
>> Final ID register state requested from KVM for "arm-v9.0-a-v1":
>> [ 0] AIDR_EL1 = 0x0000000000000000
>> [ 1] CLIDR_EL1 = 0x0000000000000000
>> [ 2] CTR_EL0 = 0x0000000080008000
>> [ 3] DCZID_EL0 = 0x0000000000000000
>> [ 4] GMID_EL1 = 0x0000000000000000
>> [ 5] ID_AA64AFR0_EL1 = 0x0000000000000000
>> [ 6] ID_AA64AFR1_EL1 = 0x0000000000000000
>> [ 7] ID_AA64DFR0_EL1 = 0x000000f000000009
>> [ 8] ID_AA64DFR1_EL1 = 0x0000000000000000
>> [ 9] ID_AA64DFR2_EL1 = 0x0000000000000000
>> [ 10] ID_AA64FPFR0_EL1 = 0x0000000000000000
>> [ 11] ID_AA64ISAR0_EL1 = 0x0221100010210000
>> [ 12] ID_AA64ISAR1_EL1 = 0x0000011100211002
>> [ 13] ID_AA64ISAR2_EL1 = 0x0000000000000000
>> [ 14] ID_AA64ISAR3_EL1 = 0x0000000000000000
>> [ 15] ID_AA64MMFR0_EL1 = 0x000001110f000000
>> [ 16] ID_AA64MMFR1_EL1 = 0x0000000000211000
>> [ 17] ID_AA64MMFR2_EL1 = 0x1001001100000011
>> [ 18] ID_AA64MMFR3_EL1 = 0x0000000000000000
>> [ 19] ID_AA64MMFR4_EL1 = 0x000000000f000000
>> [ 20] ID_AA64PFR0_EL1 = 0x1101000010110011
>> [ 21] ID_AA64PFR1_EL1 = 0x0000000000000001
>> [ 22] ID_AA64PFR2_EL1 = 0x0000000000000000
>> [ 23] ID_AA64SMFR0_EL1 = 0x0000000000000000
>> [ 24] ID_AA64ZFR0_EL1 = 0x0000000000000000
>> [ 25] ID_AFR0_EL1 = 0x0000000000000000
>> [ 26] ID_DFR0_EL1 = 0x0000000000000000
>> [ 27] ID_DFR1_EL1 = 0x0000000000000000
>> [ 28] ID_ISAR0_EL1 = 0x0000000000000000
>> [ 29] ID_ISAR1_EL1 = 0x0000000000000000
>> [ 30] ID_ISAR2_EL1 = 0x0000000000000000
>> [ 31] ID_ISAR3_EL1 = 0x0000000000000000
>> [ 32] ID_ISAR4_EL1 = 0x0000000000000000
>> [ 33] ID_ISAR5_EL1 = 0x0000000000000000
>> [ 34] ID_ISAR6_EL1 = 0x0000000000000000
>> [ 35] ID_MMFR0_EL1 = 0x0000000000000000
>> [ 36] ID_MMFR1_EL1 = 0x0000000000000000
>> [ 37] ID_MMFR2_EL1 = 0x0000000000000000
>> [ 38] ID_MMFR3_EL1 = 0x0000000000000000
>> [ 39] ID_MMFR4_EL1 = 0x0000000000000000
>> [ 40] ID_MMFR5_EL1 = 0x0000000000000000
>> [ 41] ID_PFR0_EL1 = 0x0000000000000000
>> [ 42] ID_PFR1_EL1 = 0x0000000000000000
>> [ 43] ID_PFR2_EL1 = 0x0000000000000000
>> [ 44] MIDR_EL1 = 0x0000000000000000
>> [ 45] MPIDR_EL1 = 0x0000000080000000
>> [ 46] MVFR0_EL1 = 0x0000000000000000
>> [ 47] MVFR1_EL1 = 0x0000000000000000
>> [ 48] MVFR2_EL1 = 0x0000000000000000
>> [ 49] REVIDR_EL1 = 0x0000000000000000
>> [ 50] SMIDR_EL1 = 0x0000000000000000
>>
>> Signed-off-by: Khushit Shah <[email protected]>
>> ---
>> hw/arm/virt.c | 3 ++
>> target/arm/cpu-models.c | 75 +++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 78 insertions(+)
>>
>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>> index e7a56e37f7..01381ab5e7 100644
>> --- a/hw/arm/virt.c
>> +++ b/hw/arm/virt.c
>> @@ -4144,6 +4144,9 @@ static GPtrArray *virt_get_valid_cpu_types(const
>> MachineState *ms)
>> 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")));
>> }
>> + if (kvm_enabled() && target_aarch64()) {
>> + g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("arm-v9.0-a-v1")));
>> + }
>> if (target_aarch64()) {
>> g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a53")));
>> g_ptr_array_add(vct, g_strdup(ARM_CPU_TYPE_NAME("cortex-a57")));
>> diff --git a/target/arm/cpu-models.c b/target/arm/cpu-models.c
>> index 153ee10ae6..7394dd358e 100644
>> --- a/target/arm/cpu-models.c
>> +++ b/target/arm/cpu-models.c
>> @@ -39,7 +39,82 @@
>> /* Maximum parent-chain depth for named CPU models. */
>> #define ARM_NAMED_CPU_MODEL_MAX_DEPTH 16
>>
>> +/* Arm-v9.0-a mandatory features. */
>> +static const ArmModelPropValue arm_v9_0_a_v1_props[] = {
>> + /* ID_AA64PFR0_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_EL0", NUM, 1), /* only FEAT_AA64EL0
>> (Armv9.0) */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_EL1", NUM, 1), /* only FEAT_AA64EL1
>> (Armv9.0) */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_RAS", NUM, 1), /* FEAT_RAS (Armv8.2)
>> */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_DIT", NUM, 1), /* FEAT_DIT (Armv8.4)
>> */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_CSV2", NUM, 1), /* FEAT_CSV2
>> (Armv8.5) */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_CSV3", NUM, 1), /* FEAT_CSV3
>> (Armv8.5) */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_FP", NUM, 1), /* FEAT_FP16 */
>> + MODEL_PROP("SYSREG_ID_AA64PFR0_EL1_AdvSIMD", NUM, 1), /* FEAT_FP16 */
> I have not found that FP+AdvSIMD (ie FEAT_FP16) were mandated by v9.0
> amybe you want this model to implement FP16 but it does not seems
> strictly mandated in v9.0
> so it might be distinguished from other settings that are truly mandated.
>
>> +
>> + /* ID_AA64PFR1_EL1 */
>> + /* KVM zeroes out these field when MTE is not enabled. */
>> + MODEL_PROP("SYSREG_ID_AA64PFR1_EL1_MTE_frac", NUM, 0),
> useless as default is 0, no?
Sure, removed.
>> + MODEL_PROP("SYSREG_ID_AA64PFR1_EL1_BT", NUM, 1), /* FEAT_BTI (Armv8.5)
>> */
>> +
>> + /* ID_AA64MMFR0_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR0_EL1_TGran64", NUM, 0xF), /* not
>> mandatory */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR0_EL1_TGran4", NUM, 0), /* 4K granular
>> support */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR0_EL1_TGran16_2", NUM, 1), /* not
>> mandatory */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR0_EL1_TGran64_2", NUM, 1), /* not
>> mandatory */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR0_EL1_TGran4_2", NUM, 1), /* not
>> mandatory */
> so the top comment, ie.
>
> +/* Arm-v9.0-a mandatory features. */
>
> should really be updated accordingly. None of that is mandated by v9.0
> spec, right?
>
Correct, will update the comment based on below discussion.
>> +
>> + /* ID_AA64DFR0_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64DFR0_EL1_DebugVer", NUM, 9), /*
>> FEAT_Debugv8p4 (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64DFR0_EL1_DoubleLock", NUM, 0xF), /* not
>> implemented */
> I understand this is mandated by v9.0, ie v9Ap0 ==> (!FEAT_DoubleLock)
>> + /* no PMU for named models */
>> + MODEL_PROP("SYSREG_ID_AA64DFR0_EL1_PMUVer", NUM, 0),
> not needed?
I kept it to signify that PMU is not supported with named models for now.
But, this can be removed from here as PMU is not mandatory for ARMv9.0.
>
>> +
>> + /* CTR_EL0 */
>> + MODEL_PROP("SYSREG_CTR_EL0_L1Ip", NUM, 2), /* FEAT_IVIPT: VIPT cache
>> impl. */
> ARMv8.0
Done.
>> +
>> + /* ID_AA64MMFR4_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR4_EL1_E2H0", NUM, 0xF), /* FEAT_E2H0 not
>> mandatory */
> not mandatory. All the non mandatory settings might rather go in the
> neoverse child, no? That way it is easier to understand the role of this
> parent which enforce mandatory features only
Sorry, for the confusing comments. As Peter already mentioned, these FEATs are
not mandatory
and their not-impl. field value are not 0, hence the need to set them here.
I will fix the comments.
>> +
>> + /* ID_AA64ISAR0_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_CRC32", NUM, 1), /* FEAT_CRC32
>> (Armv8.1) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_Atomic", NUM, 2), /* FEAT_LSE
>> (Armv8.1) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_TS", NUM, 2), /* FEAT_FlagM2
>> (Armv9.0 & FP) */
> this is required because FP was opt-in. Otherwise v9.0 does not require
> 2. As far as I understand there is no v9Ap0 ==> FEAT_FP
>
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_TLB", NUM, 2), /* FEAT_TLBIRANGE
>> (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_RDM", NUM, 1), /* FEAT_RDM (Armv9.0
>> & FP) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_DP", NUM, 1), /* FEAT_DotProd
>> (Armv9.0 & FP) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR0_EL1_FHM", NUM, 1), /* FEAT_FHM (Armv9.0
>> & FP) */
>> +
>> + /* ID_AA64ISAR1_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_LRCPC", NUM, 2), /* FEAT_LRCPC2
>> (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_FRINTTS", NUM, 1), /* FEAT_FRINTTS
>> (v9.0 & FP) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_FCMA", NUM, 1), /* FEAT_FCMA
>> (Armv9.0 & FP) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_JSCVT", NUM, 1), /* FEAT_JSCVT
>> (Armv9.0 & FP) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_DPB", NUM, 2), /* FEAT_DPB2
>> (Armv8.5) */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_SB", NUM, 1), /* FEAT_SB (Armv8.5)
>> */
>> + MODEL_PROP("SYSREG_ID_AA64ISAR1_EL1_SPECRES", NUM, 1), /* FEAT_SPECRES
>> (Armv8.5) */
>
> For readability please groups all fields that are mandated if v9.0 + FP
> + AdvSIMD. This is still arguable if this shall be part of this model
> though
>> + /*
>> + * FEAT_PAuth is mandated by Armv8.3 but is excluded here as reference
>> + * core can choose to implement any PAuth algorithm (APA/API/APA3).
> Can you set a default value then? GPI/API <= 1 or GPA3/APA3. This mens
> the child will need to override.
> Without that you cannot claim this model to ve v9.0 compliant.
I think it is better to not set any defaults for either PAuth or
supported granule size, as those are the choices that the core
must take.
> I guess you need to document all named vcpu models in either
> docs/system/arm/cpu-features.rst
> There is also docs/system/qemu-cpu-models.rst
Done.
>> + */
>> +
>> + /* ID_AA64MMFR1_EL1 */
> nit reorder after AA64_MFR0. All values below look good to me
Done.
Thanks,
Khushit
>> + MODEL_PROP("SYSREG_ID_AA64MMFR1_EL1_HPDS", NUM, 1), /* FEAT_HPDS
>> (Armv8.1) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR1_EL1_LO", NUM, 1), /* FEAT_LOR (Armv8.1)
>> */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR1_EL1_PAN", NUM, 2), /* FEAT_PAN2
>> (Armv8.2) */
>> +
>> + /* ID_AA64MMFR2_EL1 */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_UAO", NUM, 1), /* FEAT_UAO
>> (Armv8.2) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_CnP", NUM, 1), /* FEAT_TTCNP
>> (Armv8.2) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_TTL", NUM, 1), /* FEAT_TTL
>> (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_AT", NUM, 1), /* FEAT_LSE2
>> (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_IDS", NUM, 1), /* FEAT_IDST
>> (Armv8.4) */
>> + MODEL_PROP("SYSREG_ID_AA64MMFR2_EL1_E0PD", NUM, 1), /* FEAT_E0PD
>> (Armv8.5) */
>> +
>> + MODEL_PROP_END,
>> +};
>> +
>> static const ArmNamedCpuModel arm_cpu_models[] = {
>> + {"arm-v9.0-a-v1", NULL, arm_v9_0_a_v1_props},
>> {NULL, NULL, NULL}
>> };
>>
> Thanks
>
> Eric