On Wed, 9 Sept 2026 at 15:42, Sebastian Ott <[email protected]> wrote:
>
> From: Cornelia Huck <[email protected]>
>
> We now have the infrastructure in place to handle demuxed ID registers
> from kvm. Use it to get the values that kvm emulates for CCSIDR_EL1.
>
> Tested-by: Alireza Sanaee <[email protected]>
> Signed-off-by: Cornelia Huck <[email protected]>
> Signed-off-by: Sebastian Ott <[email protected]>
> ---
> target/arm/kvm.c | 31 +++++++++++++++++++++++++++++++
> 1 file changed, 31 insertions(+)
>
> diff --git a/target/arm/kvm.c b/target/arm/kvm.c
> index ed99be7fd8..1230acaff0 100644
> --- a/target/arm/kvm.c
> +++ b/target/arm/kvm.c
> @@ -244,6 +244,33 @@ static int get_host_cpu_reg(int fd, ARMHostCPUFeatures
> *ahcf,
> return ret;
> }
>
> +
> +/* CSSELR values supported by kvm; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR
> */
> +#define CSSELR_MAX 14
This is a bit misleading as a constant name because that 14 limit
is KVM-specific, and doesn't apply to the architecture or QEMU.
Somewhere in here we should document why the KVM number is different
from what QEMU has and why it doesn't matter (i.e. that neither KVM
nor QEMU currently handle reporting separate MTE Allocation Tag caches,
so CCSELR_EL1 bit 4 is always 0, and that a Level of 0b111 is reserved
and so CCSELR values 14 and 15 are never valid and will always make
CCSIDR read as zero).
> +static int get_host_cpu_reg_demux(int fd, ARMHostCPUFeatures *ahcf,
> + ARMIDRegisterIdx index, int subindex)
> +{
> +
> + struct kvm_one_reg one_reg = {
> + .id = KVM_REG_ARM64 | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX,
> + };
> +
> + switch (index) {
> + case CCSIDR_EL1_IDX:
> + if (subindex >= CSSELR_MAX) {
> + return -EINVAL;
> + }
> + one_reg.id |= KVM_REG_ARM_DEMUX_ID_CCSIDR | subindex;
> + one_reg.addr = (uintptr_t)&ahcf->isar.idregs[index + subindex];
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return ioctl(fd, KVM_GET_ONE_REG, &one_reg);
> +}
> +
> static uint32_t kvm_arm_sve_get_vls(int fd)
> {
> uint64_t vls[KVM_ARM64_SVE_VLS_WORDS];
> @@ -454,6 +481,10 @@ static void
> kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
> /* Read the set of supported vector lengths. */
> arm_host_cpu_features.sve_vq_supported = kvm_arm_sve_get_vls(fd);
> }
> + /* Grab demuxed registers. */
> + for (int i = 0; i < CSSELR_MAX; i++) {
> + err |= get_host_cpu_reg_demux(fd, ahcf, CCSIDR_EL1_IDX, i);
> + }
> }
I think I would favour being a bit more explicit in code about how
we're converting from a KVM-ism to QEMU's underlying format here:
have this loop go from 0 to QEMU's maximum CCSELR index (currently 15),
and then have get_host_cpu_reg_demux() handle 14 and 15 as "this ID
register value is 0" (with suitable comment). At some later point
if we need to handle Allocation Tag cache ID values then that code
will expand to "read cache index values 16 and up, with suitable
fallback to 'is zero' for older kernels".
thanks
-- PMM