Subject: Re: [PATCH v2] KVM: arm64: Preserve all guest ZCR_EL2.LEN values

From: Marc Zyngier <[email-masked]>
Date: Fri, 29 May 2026 10:22:41 +0100

Thanks for respinning this patch quickly.

On Fri, 29 May 2026 00:01:44 +0100,
Mark Brown <[email-masked]> wrote:
> 
> Since commit b3d29a823099 ("KVM: arm64: nv: Handle ZCR_EL2 traps") when
> guests write to ZCR_EL2 we have clamped the value of ZCR_EL2.LEN to be
> at most that configuring the maximum guest VL when accessed directly as
> ZCR_EL2. This is not clearly the behaviour the architecture documents
> for ZCR_EL2.LEN, while things are a little ambiguous currently there is
> a fairly direct reading that suggests values will be read as written.
> Further, the documented procedure for enumerating vector lengths means
> that it is expected that values larger than the largest supported vector
> length will be written in practice.

Honestly, that's not the core issue. And even $SUBJECT fails to
capture what is at stake here.

> 
> The reasoning for the current behaviour is not specifically articulated, my

I don't think there is a reasoning behind each and every bug.

> best guess is that it is intended to ensure that the guest can not see an
> effective VL greater than the maximum that has been configured, though
> this will be ineffective when a VHE guest uses the ZCR_EL1 accessor.

This last point *IS* the core problem. It is that the guest can access
VLs beyond what is intended by the VM configuration. Not getting the
read-as-written behaviour really is secondary compared to that issue.

[...]

I've rewritten the commit message to make it plain what the problem
is, see below. I've also slightly tidied up access_zcr_el2(), but the
fix otherwise looks good.

Thanks,

	M.

KVM: arm64: Correctly cap ZCR_EL2 provided by a guest hypervisor

ZCR_EL2 can be updated by a VHE guest hypervisor either using ZCR_EL2
(which traps) or ZCR_EL1 (which does not trap). KVM handles both in
different way:

- on ZCR_EL2 trap, ZCR_EL2.LEN is immediately capped at the VM's own
  VL limit. This has the potential to break existing SW that relies
  on the full LEN field to be stateful.

- on ZCR_EL1 access, we do absolutely nothing.

On restoring the SVE context for an L2 guest, we directly restore the
guest hypervisor's view of ZCR_EL2 into the physical ZCR_EL2. If the
guest's view of the register was updated using the ZCR_EL2 accessor,
the value has already been sanitised (with the caveat mentioned above).

But if the guest used ZCR_EL1, the raw value is written into the HW,
and the L2 guest can now access VLs that it shouldn't.

Fix all the above by moving the VL capping to the restore points,
ensuring that:

- the HW is always programmed with a capped value, irrespective of
  the accessor being used,

- the ZCR_EL2.LEN field is always completely stateful, irrespective
  of the accessor being used.

Additionally, move ZCR_EL2 to be a sanitised register, ensuring that
only the LEN field is actually stateful. This requires some creative
construction of the RES0 mask, as the sysreg generation script does
not yet generate RAZ/WI fields.

-- 
Without deviation from the norm, progress is not possible.