From: Eric Auger <eric.auger@redhat.com>
To: Khushit Shah <khushit.shah@nutanix.com>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
"qemu-arm@nongnu.org" <qemu-arm@nongnu.org>,
"kvmarm@lists.linux.dev" <kvmarm@lists.linux.dev>,
"cohuck@redhat.com" <cohuck@redhat.com>,
"peter.maydell@linaro.org" <peter.maydell@linaro.org>,
"richard.henderson@linaro.org" <richard.henderson@linaro.org>,
"maz@kernel.org" <maz@kernel.org>,
"oliver.upton@linux.dev" <oliver.upton@linux.dev>,
"berrange@redhat.com" <berrange@redhat.com>,
"abologna@redhat.com" <abologna@redhat.com>,
"jdenemar@redhat.com" <jdenemar@redhat.com>,
"gshan@redhat.com" <gshan@redhat.com>,
"skolothumtho@nvidia.com" <skolothumtho@nvidia.com>,
"sebott@redhat.com" <sebott@redhat.com>,
"armbru@redhat.com" <armbru@redhat.com>,
"philmd@linaro.org" <philmd@linaro.org>,
"yangjinqian1@huawei.com" <yangjinqian1@huawei.com>,
Shaju Abraham <shaju.abraham@nutanix.com>,
Mark Cave-Ayland <mark.caveayland@nutanix.com>,
Prerna Saxena <prerna.saxena@nutanix.com>
Subject: Re: [RFC PATCH v3 14/19] target/arm/kvm: compute supported values for ID register fields
Date: Fri, 14 Aug 2026 17:34:46 +0200 [thread overview]
Message-ID: <0cb9dba3-c905-4e2d-a3e9-539dbf2ea787@redhat.com> (raw)
In-Reply-To: <82F566CD-CC65-4368-AE92-3A2E637CC27A@nutanix.com>
On 8/5/26 11:58 AM, Khushit Shah wrote:
>
>> On 26 Jul 2026, at 7:52 PM, Eric Auger <eric.auger@redhat.com> wrote:
>>
>> !-------------------------------------------------------------------|
>> CAUTION: External Email
>>
>> |-------------------------------------------------------------------!
>>
>> Hi Khushit,
>>
>> On 7/16/26 11:38 PM, Khushit Shah wrote:
>>> Add arm_field_get_supported_values() which, for a given ID register
>>> field, builds the set of values KVM allows it to take on the live host.
>>>
>>> Non-writable fields are pinned to the host value. Writable fields follow
>>> their per field constraints. This function likely needs change when
>>> KVM starts exposing a new writable field that is not lower-safe, hence,
>>> the special handling of TGranX_2/SpecSEI/L1Ip/MIDR/REVIDR/AIDR.
>> so this looks quite risky.
> I agree.
>
> What are your thoughts on having a authoritative list in QEMU of all
> writable fields? No matter what KVM exposes as writable, actual fields
> we allow to be writable will be intersection of KVM writable + QEMU
> writable. When The QEMU list is updated we make sure things like this
> function is updated.
>
> This get’s rid of cases where we silently support writing to a field.
> It is similar to x86, QEMU only supports writing to specific CPUID
> leafs (by the defined Properties) and not just any CPUID leafs.
>
>>> Cross-field constraints are not modelled; for example ID_AA64ZFR0_EL1
>>> is gated by SVE. Reproducing every inter-field dependency in QEMU
>>> would only duplicate KVM's logic and drift out of sync with it.
>> Isn't qmp_query_cpu_model_expansion sufficient? In general upper layers
>> will try to apply raw named models. If ajustements are needed between
>> source and destination, we know field candidate values (either the
>> source or dest one) and this latter can be directly tried using
>> qmp_query_cpu_model_expansion write. On top of that
>> qmp_query_cpu_model_expansion can be directly checked against a scratch
>> vcpu reusing the logic implemented at kernel level.
> I am not sure if it is acceptable for query_cpu_model_expansion should fail
> if model is not realisable. On at least x86 it does not. It just returns the
> state which QEMU would request KVM for the given configurations.
>
> Ref:
> https://github.com/qemu/qemu/blob/3e3ccab106f879b1512f8e0d51a827dd4de30e22/target/i386/cpu.c#L9689
I need to further study that. I will come back to you.
Currently with v7 you get:
(QEMU) query-cpu-model-expansion type=full
model={"name":"host","props":{"SYSREG_ID_AA64MMFR1_EL1_AFP":0x1}}
{"error": {"class": "GenericError", "desc": "failed to apply new value
0x1 for field AFP (previous is 0x0): Invalid argument"}}
This can be implemented elsewhere though
Eric
>
> cpu-definitions is maybe a better candidate for algo you are describing, but
> it will not take the user overrides into considerations and only say if a
> base model is usable or not
>
>
>>> Signed-off-by: Khushit Shah <khushit.shah@nutanix.com>
>>> ---
>>> target/arm/kvm.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
>>> target/arm/kvm_arm.h | 26 ++++++++++++
>>> 2 files changed, 125 insertions(+)
>>>
>>> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
>>> index c38b99cfce..8f452f9570 100644
>>> --- a/target/arm/kvm.c
>>> +++ b/target/arm/kvm.c
>>> @@ -1262,6 +1262,105 @@ bool kvm_arm_cpu_post_load(ARMCPU *cpu)
>>> return true;
>>> }
>>>
>>> +static bool arm_field_is_signed(const ARM64SysRegField *field)
>>> +{
>>> + return field_matches(field, ID_AA64MMFR0_EL1_IDX, "TGran4") ||
>>> + field_matches(field, ID_AA64MMFR0_EL1_IDX, "TGran64") ||
>>> + field_matches(field, ID_MMFR0_EL1_IDX, "InnerShr") ||
>>> + field_matches(field, ID_MMFR0_EL1_IDX, "OuterShr") ||
>>> + field_matches(field, ID_AA64DFR0_EL1_IDX, "DoubleLock") ||
>>> + field_matches(field, ID_AA64DFR0_EL1_IDX, "PMUVer") ||
>>> + field_matches(field, ID_DFR0_EL1_IDX, "PerfMon") ||
>>> + field_matches(field, ID_AA64PFR1_EL1_IDX, "MTE_frac") ||
>>> + field_matches(field, ID_AA64MMFR4_EL1_IDX, "E2H0") ||
>>> + field_matches(field, ID_DFR1_EL1_IDX, "MTPMU") ||
>>> + field_matches(field, ID_AA64PFR0_EL1_IDX, "FP") ||
>>> + field_matches(field, ID_AA64PFR0_EL1_IDX, "AdvSIMD");
>> Can't we extract this from Register.json instead?
> AFAIK, There is not signedness data in Register.json
>
>>> +}
>>> +
>>> +static void ranges_add(GArray *ranges, uint64_t min, uint64_t max)
>>> +{
>>> + ArmFieldRange r = { .min = min, .max = max };
>>> + g_array_append_val(ranges, r);
>>> +}
>>> +
>>> +void arm_field_get_supported_values(const ARM64SysRegField *field,
>>> + const ARMISARegisters *host_isar,
>>> + ArmFieldValueSet **value_set)
>>> +{
>>> + bool is_signed = arm_field_is_signed(field);
>>> + uint64_t host = extract64(host_isar->idregs[field->index],
>>> + field->shift, field->length);
>>> + GArray *ranges = g_array_new(false, false, sizeof(ArmFieldRange));
>>> +
>>> + /* A non-writable field can only ever hold the host value. */
>>> + if (!arm_field_is_writable(field)) {
>>> + ranges_add(ranges, host, host);
>>> + goto done;
>> you already get this info from qmp_query_cpu_model_expansion
> Can you please elaborate how? I thought the current qmp_query_cpu_model_expansion
> (Your v6) only returns the writable field.
> (I have not yet looked at v7)
>
>>> + }
>>> +
>>> + if (field_matches(field, ID_AA64MMFR0_EL1_IDX, "TGran4_2") ||
>>> + field_matches(field, ID_AA64MMFR0_EL1_IDX, "TGran16_2") ||
>>> + field_matches(field, ID_AA64MMFR0_EL1_IDX, "TGran64_2")) {
>>> + /* Either support the host value or the "off" value */
>>> + ranges_add(ranges, host, host);
>>> + if (host != 1) { /* 1 = "off" */
>>> + ranges_add(ranges, 1, 1);
>>> + }
>>> + } else if (field_matches(field, CTR_EL0_IDX, "L1Ip")) {
>>> + /* Only safe to downgrade to VIPT, other values are reserved. */
>>> + ranges_add(ranges, host, host);
>>> + if (host != 2) { /* 2 = "VIPT" */
>>> + ranges_add(ranges, 2, 2);
>>> + }
>>> + } else if (field_matches(field, ID_AA64MMFR1_EL1_IDX, "SpecSEI") ||
>>> + field_matches(field, ID_MMFR4_EL1_IDX, "SpecSEI")) {
>>> + /* It is safe to upgrade SpecSEI to 1, other values are reserved. */
>>> + ranges_add(ranges, host, host);
>>> + if (host != 1) {
>>> + ranges_add(ranges, 1, 1);
>>> + }
>>> + } else if (field->index == MIDR_EL1_IDX ||
>>> + field->index == REVIDR_EL1_IDX ||
>>> + field->index == AIDR_EL1_IDX) {
>>> + /*
>>> + * No restriction on value that can be set for implementation ID
>>> + * registers fields.
>>> + */
>>> + uint64_t max = 0;
>>> + if (field->length == 64) {
>>> + max = ~0ULL;
>>> + } else {
>>> + max = (1ULL << field->length) - 1;
>>> + }
>>> + ranges_add(ranges, 0, max);
>>> + } else {
>>> + /*
>>> + * After handling the special cases, other writable fields are
>>> + * either lower-safe or signed lower-safe.
>>> + */
>>> + if (field->arch_vals_count) {
>>> + for (uint32_t i = 0; i < field->arch_vals_count; i++) {
>>> + uint64_t av = field->arch_vals[i].value;
>>> + int64_t v = is_signed ?
>>> + sextract64(av, 0, field->length) : (int64_t)av;
>>> + int64_t hv = is_signed ?
>>> + sextract64(host, 0, field->length) : (int64_t)host;
>>> + if (v <= hv) {
>>> + ranges_add(ranges, av, av);
>>> + }
>>> + }
>>> + } else {
>>> + g_assert(!is_signed); /* No signed field with no arch vals */
>>> + ranges_add(ranges, 0, host);
>>> + }
>>> + }
>>> +done:
>>> + *value_set = g_new0(ArmFieldValueSet, 1);
>>> + (*value_set)->n_ranges = ranges->len;
>>> + (*value_set)->ranges = (ArmFieldRange *)g_array_free(ranges, false);
>>> +}
>>> +
>>> static bool arm_field_skip_writeback_always(const ARM64SysRegField *field)
>>> {
>>> /*
>>> diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
>>> index 133a026036..9f15c91c4e 100644
>>> --- a/target/arm/kvm_arm.h
>>> +++ b/target/arm/kvm_arm.h
>>> @@ -143,6 +143,32 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
>>> void kvm_arm_add_vcpu_properties(ARMCPU *cpu);
>>>
>>> typedef struct ARM64SysReg ARM64SysReg;
>>> +typedef struct ARM64SysRegField ARM64SysRegField;
>>> +typedef struct ARMISARegisters ARMISARegisters;
>>> +
>>> +typedef struct ArmFieldRange {
>>> + uint64_t min;
>>> + uint64_t max;
>>> +} ArmFieldRange;
>>> +
>>> +typedef struct ArmFieldValueSet {
>>> + ArmFieldRange *ranges;
>>> + size_t n_ranges;
>>> +} ArmFieldValueSet;
>>> +
>>> +/**
>>> + * arm_field_get_supported_values:
>>> + * @field: The field to get the supported values for
>>> + * @host_isar: The host ISAR registers
>>> + * @value_set: The set of supported values for the @field
>>> + *
>>> + * Will be allocated and filled in with the supported values for the @field
>>> + * based on the host_isar and whether the field is writable or not.
>>> + * The caller must free the value_set.
>>> + */
>>> +void arm_field_get_supported_values(const ARM64SysRegField *field,
>>> + const ARMISARegisters *host_isar,
>>> + ArmFieldValueSet **value_set);
>>>
>>> /**
>>> * kvm_arm_steal_time_finalize:
>> Thanks
>>
>> Eric
>
next prev parent reply other threads:[~2026-08-14 15:34 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-16 21:38 [RFC PATCH v3 00/19] named CPU models for Arm64 on KVM Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 01/19] target/arm/sysreg: regenerate cpu-sysregs.h.inc Khushit Shah
2026-07-20 12:11 ` Eric Auger
2026-08-03 14:22 ` Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 02/19] scripts: bug fixes in update-aarch64-cpu-sysreg-properties Khushit Shah
2026-07-20 14:24 ` Eric Auger
2026-08-03 14:32 ` Khushit Shah
2026-08-14 13:45 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 03/19] target/arm: regenerate cpu-idregs.h.inc Khushit Shah
2026-07-20 14:39 ` Eric Auger
2026-08-03 14:34 ` Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 04/19] target/arm: expose all ID regs fields as properties Khushit Shah
2026-07-21 14:44 ` Eric Auger
2026-08-03 15:05 ` Khushit Shah
2026-08-14 13:54 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 05/19] target/arm/kvm: enable writable implementation ID registers Khushit Shah
2026-07-21 15:03 ` Eric Auger
2026-08-03 15:46 ` Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 06/19] target/arm/kvm: Read all ID registers from KVM Khushit Shah
2026-07-22 6:54 ` Eric Auger
2026-08-03 15:47 ` Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 07/19] target/arm/kvm: handle special ID registers cases when reading " Khushit Shah
2026-07-22 12:32 ` Eric Auger
2026-08-03 15:52 ` Khushit Shah
2026-08-14 13:55 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 08/19] target/arm/kvm: Handle writeback for special ID register fields Khushit Shah
2026-07-22 12:05 ` Eric Auger
2026-07-26 13:56 ` Eric Auger
2026-08-03 16:03 ` Khushit Shah
2026-08-14 14:04 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 09/19] target/arm: Add named cpu model infra + graviton3 named model Khushit Shah
2026-07-26 13:14 ` Eric Auger
2026-07-26 13:34 ` Eric Auger
2026-08-05 11:35 ` Khushit Shah
2026-08-14 15:40 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 10/19] target/arm: Add Nvidia Grace " Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 11/19] target/arm: fix sve and pauth finalize for named cpu models Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 12/19] target/arm: Introduce stub files required for qmp support Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 13/19] target/arm/qmp: add named models and properties to cpu-model-expansion Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 14/19] target/arm/kvm: compute supported values for ID register fields Khushit Shah
2026-07-26 14:22 ` Eric Auger
2026-08-05 9:58 ` Khushit Shah
2026-08-14 15:34 ` Eric Auger [this message]
2026-07-16 21:38 ` [RFC PATCH v3 15/19] target/arm/kvm: introduce kvm_arm_get_host_isar helper Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 16/19] qmp: add query-cpu-props-info command Khushit Shah
2026-07-20 13:21 ` Markus Armbruster
2026-08-03 16:05 ` Khushit Shah
2026-08-04 6:05 ` Markus Armbruster
2026-08-04 6:07 ` Khushit Shah
2026-08-04 6:30 ` Khushit Shah
2026-08-04 6:51 ` Markus Armbruster
2026-08-05 6:48 ` Khushit Shah
2026-08-05 6:58 ` Markus Armbruster
2026-08-05 7:32 ` Khushit Shah
2026-08-05 13:22 ` Markus Armbruster
2026-08-06 9:24 ` Khushit Shah
2026-08-04 6:45 ` Markus Armbruster
2026-08-05 6:47 ` Khushit Shah
2026-08-05 6:57 ` Markus Armbruster
2026-08-05 7:32 ` Khushit Shah
2026-08-14 13:38 ` Eric Auger
2026-07-16 21:38 ` [RFC PATCH v3 17/19] target/arm: Report 0 as supported for ID fields gated by vCPU init flags Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 18/19] target/arm/qmp: hook blockers in query-cpu-definitions Khushit Shah
2026-07-16 21:38 ` [RFC PATCH v3 19/19] target/arm/kvm: fix host model writeback when kernel supports EL2 Khushit Shah
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0cb9dba3-c905-4e2d-a3e9-539dbf2ea787@redhat.com \
--to=eric.auger@redhat.com \
--cc=abologna@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=cohuck@redhat.com \
--cc=gshan@redhat.com \
--cc=jdenemar@redhat.com \
--cc=khushit.shah@nutanix.com \
--cc=kvmarm@lists.linux.dev \
--cc=mark.caveayland@nutanix.com \
--cc=maz@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=prerna.saxena@nutanix.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=sebott@redhat.com \
--cc=shaju.abraham@nutanix.com \
--cc=skolothumtho@nvidia.com \
--cc=yangjinqian1@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox