Hi Khushit,

On 7/16/26 11:38 PM, Khushit Shah wrote:
> The generic KVM_GET_ONE_REG loop cannot correctly read a handful of
> ID registers, so specially handle those:
>
> - DCZID_EL0: No fine grain trap exists, hence not tracked by KVM.
>   It is EL0-readable and untrapped, so read it directly with MRS.
>
> - CCSIDR_EL1/CCSIDR2_EL1: not plain ID registers, their value is
>   selected by CSSELR_EL1. KVM only exposes them via the DEMUX API
>   (KVM_REG_ARM_DEMUX_ID_CCSIDR), so there is no single value to read
>   here. Skip them.
>
> - SMIDR_EL1: KVM does not support SME, so there is no meaningful host
>   value. Skip it.
>
> - GMID_EL1: not in KVM's sys_reg_descs[] and, being an EL1 register,
>   cannot be read from userspace via MRS either. The guest reads the
>   raw host value; this is a genuine miss when MTE is enabled.
>
> Signed-off-by: Khushit Shah <[email protected]>
> ---
>  target/arm/kvm.c | 53 ++++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index 42ff731f6e..6974e5c551 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -311,15 +311,50 @@ static int get_host_cpu_idregs(int fd, 
> ARMHostCPUFeatures *ahcf)
>          int ret;
>  
>          reg = &ahcf->isar.idregs[i];
> -        ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg));
> -        if (ret) {
> -            if (errno == ENOENT) {
> -                warn_report("%s error reading value of host %s register "
> -                                "(ENOENT)", __func__, sysregdesc->name);
> -            } else {
> -                error_report("%s error reading value of host %s register"
> -                            " (%m)", __func__, sysregdesc->name);
> -                err = ret;
> +        switch (i) {
> +        case DCZID_EL0_IDX:
> +            /*
> +             * DCZID_EL0 is not in KVM's sys_reg_descs[], so
> +             * KVM_GET_ONE_REG will fail. Read it directly from
> +             * hardware since KVM doesn't trap guest reads of it.
> +             */
> +            asm volatile("mrs %0, DCZID_EL0" : "=r" (*reg));
> +            break;
> +        case CCSIDR_EL1_IDX:
> +        case CCSIDR2_EL1_IDX:
> +            /*
> +             * CCSIDR_EL1 is not a plain ID register: the value it
> +             * returns is selected by CSSELR_EL1, so there is no single
> +             * value to capture here. It is exposed to userspace only via
> +             * the DEMUX API (KVM_REG_ARM_DEMUX_ID_CCSIDR), indexed by
> +             * CSSELR. Skip reading it here as there is no meaningful host
> +             * value to read.
> +             */
I think you should rely on prerequisite
[PATCH v4 3/3] arm/kvm: get demuxed ID registers from kvm


> +            break;
> +        case SMIDR_EL1_IDX:
> +            /*
> +             * As SME is not yet supported by KVM, ignore reading SMIDR_EL1
> +             */
> +             break;
> +        case GMID_EL1_IDX:
> +            /*
> +             * GMID_EL1 is not in KVM's sys_reg_descs[] and guest reads
> +             * the raw host value. But as it is an EL1 register, we cannot
> +             * read it directly. This is a genuine miss when MTE is
> +             * enabled for the guest.
> +             */
> +            break;
> +        default:
> +            ret = read_sys_reg64(fd, reg, idregs_sysreg_to_kvm_reg(sysreg));
> +            if (ret) {
> +                if (errno == ENOENT) {
> +                    warn_report("%s error reading value of host %s register "
> +                                    "(ENOENT)", __func__, sysregdesc->name);
trace point
> +                } else {
> +                    error_report("%s error reading value of host %s register"
> +                                " (%m)", __func__, sysregdesc->name);
> +                    err = ret;
> +                }
>              }
>          }
>          trace_get_host_cpu_idregs(sysregdesc->name, *reg);
Thanks

Eric


Reply via email to