> On 10 Oct 2026, at 7:06 PM, Eric Auger <[email protected]> wrote:
>
> !-------------------------------------------------------------------|
> CAUTION: External Email
>
> |-------------------------------------------------------------------!
>
> kvm_arm_get_host_cpu_features() already retrieves the values of some
> host id registers to analyze the available vcpu features.
>
> Eventually we want to be able to allow the user to change the value
> of writable ID reg fields. So we need to store the initial value of all
> writable ID regs into isar.idregs[].
>
> Introduce a new get_host_cpu_idregs() helper that populates isar.idregs[]
> and call it from kvm_arm_get_host_cpu_features.
>
> This patch has no impact on cpreg values. isar.idregs[] is only
> used as a temporary storage for register values to be updated in place
> later. Also it does not handle the writeback of isar.idregs[] into cpreg
> value list after user update. This will be handled separately.
>
> Note the host values are retrieved from the scratch vcpu initialized with
> all the available capabilities exposed by KVM, independently on the
> final vcpu features made by the user through the legacy composite
> options such as sve, pauth, virtualization, ...
>
> At the moment, the only caller sets writable to true. Named vcpu models
> will use the writable=false mode. Note this will require some extra
> handling for ID regs that cannot be read from KVM.
>
> Signed-off-by: Eric Auger <[email protected]>
> Signed-off-by: Cornelia Huck <[email protected]>
>
> ---
> v9 -> v10:
> - get rid of spurious kvm_arm_writable_idregs_to_cpreg_list trace point
> - add a writable parameter to get_host_cpu_idregs
> - some code cleanup
>
> v8 -> v9:
> - improve the commit msg. Only initialize in this patch and move the
> write back to cpreg value list in a different patch.
> - Do not hack CLIDR here. The correct way to fix that temporarily is to
> do that in the machine instead.
>
> v7 -> v8
> - fix indent and added Khushit's R-b
>
> v6 -> v7
> - remove vcpu from prototypes (Khushit)
>
> v5 -> v6
> - do not check writable_map anymore
> ---
> target/arm/kvm.c | 44 ++++++++++++++++++++++++++++++++++++++++-
> target/arm/trace-events | 1 +
> 2 files changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 2e68130611..ac4f307276 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -43,6 +43,7 @@
> #include "hw/acpi/ghes.h"
> #include "target/arm/gtimer.h"
> #include "migration/blocker.h"
> +#include "cpu-idregs.h"
>
> const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
> KVM_CAP_INFO(DEVICE_CTRL),
> @@ -329,7 +330,45 @@ static int kvm_feature_idx_to_idregs_idx(int kidx)
> return get_sysreg_idx(sysreg);
> }
>
> -static void kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
> +/*
> + * get_host_cpu_idregs: Read all the ID register values from KVM
> + * vcpu fd and populate @ahcf->isar.idregs[] with those values
> + *
> + * Need to be called once the writable mask has been populated
> + * if @writable is set
> + *
> + * @fd: vcpu fd
> + * @ahcf: ARMHostCPUFeatures whose @ahcf->isar.idregs[] will be
> + * populated
> + * @writable: if set, only writable ID regs are read
> + */
> +static int get_host_cpu_idregs(int fd, ARMHostCPUFeatures *ahcf, bool
> writable)
> +{
> + for (int i = 0; i < NUM_ID_IDX; i++) {
> + ARM64SysReg *sysregdesc = &arm64_id_regs[i];
> + ARMSysRegs sysreg = id_register_sysreg[i];
> + uint64_t *reg;
> + int ret;
> +
> + if (writable && !sysregdesc->writable_mask) {
> + continue;
> + }
> +
> + reg = &ahcf->isar.idregs[i];
> + ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg));
> + if (ret) {
Hi Eric,
We should ignore ENOENT errors here.
Also, When we read the full register set, we need to take care of
some special cases, like I do in (target/arm/kvm: handle special ID
registers when reading from KVM) (I can handle this in my series
if you like).
Anyway, for now, using a local commit for the first point.
Thanks,
Khushit
> + error_report("%s error reading value of host %s register (%m)",
> + __func__, sysregdesc->name);
> +
> + return ret;
> + }
> + trace_get_host_cpu_idregs(sysregdesc->name, *reg);
> + }
> + return 0;
> +}
> +
> +static void
> +kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
> {
> /* Identify the feature bits corresponding to the host CPU, and
> * fill out the ARMHostCPUClass fields accordingly. To do this
> @@ -415,6 +454,9 @@ static void
> kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
> SET_IDREG(&ahcf->isar, ID_AA64PFR0, 0x00000011); /* EL1&0, AArch64
> only */
> err = 0;
> } else {
> + /* Make sure all writable ID reg values are initialized */
> + err |= get_host_cpu_idregs(fd, ahcf, true);
> +
> err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR1_EL1_IDX);
> err |= get_host_cpu_reg(fd, ahcf, ID_AA64PFR2_EL1_IDX);
> err |= get_host_cpu_reg(fd, ahcf, ID_AA64SMFR0_EL1_IDX);
> diff --git a/target/arm/trace-events b/target/arm/trace-events
> index 8502fb3265..8c7faf57c7 100644
> --- a/target/arm/trace-events
> +++ b/target/arm/trace-events
> @@ -13,6 +13,7 @@ arm_gt_update_irq(int timer, int irqstate) "gt_update_irq:
> timer %d irqstate %d"
>
> # kvm.c
> kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64"
> is translated into 0x%"PRIx64
> +get_host_cpu_idregs(const char *name, uint64_t value) "scratch vcpu host
> value for %s is 0x%"PRIx64
>
> # cpu.c
> arm_cpu_reset(uint64_t mp_aff) "cpu %" PRIu64
> --
> 2.53.0
>