Re: [RFC PATCH v3 07/19] target/arm/kvm: handle special ID registers cases when reading from KVM
Eric Auger <[email protected]>
| Newsgroups | org.nongnu.qemu-arm,dev.linux.lists.kvmarm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
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