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