Re: [RFC PATCH v3 07/19] target/arm/kvm: handle special ID registers cases when reading from KVM
Eric Auger <[email protected]>
| Newsgroups | dev.linux.lists.kvmarm,org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On 8/3/26 5:52 PM, Khushit Shah wrote: > >> On 22 Jul 2026, at 6:02 PM, Eric Auger <[email protected]> wrote: >> >> !-------------------------------------------------------------------| >> CAUTION: External Email >> >> |-------------------------------------------------------------------! >> >> 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 > Currently I am just skipping those as anyway KVM exposes a very > barebone Cache topology. > > Agreed on using DEMUX regs, in case we want to support exopsing some other > “config”. > > Also on this point, I don’t know if CCSIDR_EL1/CCSIDR2_EL1 should > be part of idregs[], we already have a ccsidr[], maybe this can be fixed > in your series. OK i will investigate this. Thanks Eric > >>> + 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 > Noted. > > Warm Regards, > Khushit >>> + } 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 >