Hi Connie,

On 4/14/25 6:38 PM, Cornelia Huck wrote:
> Add an helper to retrieve the writable id reg bitmask. The
> status of the query is stored in the CPU struct so that an
> an error, if any, can be reported on vcpu realize().
>
> Signed-off-by: Eric Auger <eric.au...@redhat.com>
> Signed-off-by: Cornelia Huck <coh...@redhat.com>
> ---
>  target/arm/cpu.h     | 26 ++++++++++++++++++++++++++
>  target/arm/kvm.c     | 32 ++++++++++++++++++++++++++++++++
>  target/arm/kvm_arm.h |  7 +++++++
>  3 files changed, 65 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index d27134f4a025..bbee7ff2414a 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -856,6 +856,26 @@ typedef struct {
>      uint32_t map, init, supported;
>  } ARMVQMap;
>  
> +typedef enum ARMIdRegsState {
> +    WRITABLE_ID_REGS_UNKNOWN,
> +    WRITABLE_ID_REGS_NOT_DISCOVERABLE,
> +    WRITABLE_ID_REGS_FAILED,
> +    WRITABLE_ID_REGS_AVAIL,
> +} ARMIdRegsState;
> +
> +/*
> + * The following structures are for the purpose of mapping the output of
> + * KVM_ARM_GET_REG_WRITABLE_MASKS that also may cover id registers we do
> + * not support in QEMU
> + * ID registers in op0==3, op1=={0,1,3}, crn=0, crm=={0-7}, op2=={0-7},
> + * as used by the KVM_ARM_GET_REG_WRITABLE_MASKS ioctl call.
> + */
> +#define NR_ID_REGS (3 * 8 * 8)
We may rename this define to better associate to the KVM API. I tend to
mix it with NUM_ID_IDX now ;-)
maybe something like KVM_NR_EXPOSED_ID_REGS
> +
> +typedef struct IdRegMap {
> +    uint64_t regs[NR_ID_REGS];
> +} IdRegMap;
I would add a comment saying this is the mask array, just to prevent the
reading from thinking it is the actual reg content.
> +
>  /* REG is ID_XXX */
>  #define FIELD_DP64_IDREG(ISAR, REG, FIELD, VALUE)                       \
>      ({                                                                  \
> @@ -1044,6 +1064,12 @@ struct ArchCPU {
>       */
>      bool host_cpu_probe_failed;
>  
> +    /*
> +     * state of writable id regs query used to report an error, if any,
> +     * on KVM custom vcpu model realize
> +     */
> +    ARMIdRegsState writable_id_regs;
maybe rename into writable_id_reg_status that would better reflect what
it is.
> +
>      /* QOM property to indicate we should use the back-compat CNTFRQ default 
> */
>      bool backcompat_cntfrq;
>  
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 8491f42a18d2..6e3cd06e9bc5 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -50,6 +50,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
>  static bool cap_has_mp_state;
>  static bool cap_has_inject_serror_esr;
>  static bool cap_has_inject_ext_dabt;
> +static int cap_writable_id_regs;
>  
>  /**
>   * ARMHostCPUFeatures: information about the host CPU (identified
> @@ -488,6 +489,37 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
>      env->features = arm_host_cpu_features.features;
>  }
>  
> +int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap)
> +{
> +    struct reg_mask_range range = {
> +        .range = 0, /* up to now only a single range is supported */
> +        .addr = (uint64_t)idregmap,
> +    };
> +    int ret;
> +
> +    if (!kvm_enabled()) {
> +        cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE;
> +        return -ENOSYS;
> +    }
> +
> +    cap_writable_id_regs =
> +        kvm_check_extension(kvm_state, 
> KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES);
> +
> +    if (!cap_writable_id_regs ||
> +        !(cap_writable_id_regs & (1 << KVM_ARM_FEATURE_ID_RANGE))) {
> +        cpu->writable_id_regs = WRITABLE_ID_REGS_NOT_DISCOVERABLE;
> +        return -ENOSYS;
> +    }
> +
> +    ret = kvm_vm_ioctl(kvm_state, KVM_ARM_GET_REG_WRITABLE_MASKS, &range);
> +    if (ret) {
> +        cpu->writable_id_regs = WRITABLE_ID_REGS_FAILED;
> +        return ret;
> +     }
> +    cpu->writable_id_regs = WRITABLE_ID_REGS_AVAIL;
> +    return ret;
> +}
> +
>  static bool kvm_no_adjvtime_get(Object *obj, Error **errp)
>  {
>      return !ARM_CPU(obj)->kvm_adjvtime;
> diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
> index 05c3de8cd46e..8d1f20ca8d89 100644
> --- a/target/arm/kvm_arm.h
> +++ b/target/arm/kvm_arm.h
> @@ -221,6 +221,8 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int 
> level);
>  
>  void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
>  
> +int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap *idregmap);
> +
>  #else
>  
>  /*
> @@ -247,6 +249,11 @@ static inline bool kvm_arm_mte_supported(void)
>      return false;
>  }
>  
> +static inline int kvm_arm_get_writable_id_regs(ARMCPU *cpu, IdRegMap 
> *idregmap)
> +{
> +    return -ENOSYS;
> +}
> +
>  /*
>   * These functions should never actually be called without KVM support.
>   */
Cheers

Eric


Reply via email to