From: Marc Zyngier <maz@kernel.org>
To: Mark Brown <broonie@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>, Joey Gouly <joey.gouly@arm.com>,
Steffen Eiden <seiden@linux.ibm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] KVM: arm64: Preserve all guest ZCR_EL2.LEN values
Date: Sat, 23 May 2026 09:47:38 +0100 [thread overview]
Message-ID: <87h5nya4wl.wl-maz@kernel.org> (raw)
In-Reply-To: <20260522-kvm-arm64-fix-zcr-len-nv-v1-1-ec254e9078cf@kernel.org>
On Fri, 22 May 2026 19:00:04 +0100,
Mark Brown <broonie@kernel.org> wrote:
>
> Since 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.
That's not strictly true. This is only clamped when accessed as
ZCR_EL2. A VHE guest will happily use the ZCR_EL1 accessor for the
same register, and not see the truncation. This has ripple effects
down the line, where the full value will be used at load time.
> This is not the behaviour the
> architecture documents for ZCR_EL2.LEN, the expectation is that all bits
> will be read as written. Further, writing values larger than the largest
> available vector length is part of the documented procedure for enumerating
> the supported vector lengths so we expect to see this happen in practice.
>
> The reasoning for the current behaviour is not specifically articulated, my
> 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. This can
> instead be achieved by configuring ZCR_EL2 when loading guest state:
>
> - When running at EL0 or EL1 configure ZCR_EL2.LEN to the minimum of the
> guest ZCR_EL2.LEN and vcpu_sve_max_vq(vcpu)-1.
This is not EL0 or EL1. This is when in a nested context (i.e. running
a L2 guest), as EL0 exists for L1 as well.
> - When running at EL2 configure the maximum VL for the guest in
> ZCR_EL2.LEN like we do for non-nested guests and load the guest
> ZCR_EL2 into ZCR_EL1.
>
> This will ensure that the guest sees both the ZCR_EL2.LEN value which it
> wrote and the effective VL that resulting from the values it has configured
> in ZCR_ELx.LEN.
>
> Currently all other bits in ZCR_EL2 are either RES0 or RAZ/WI, values
> written are sanitised based on this.
Only for the direct writes to ZCR_EL2, as they are trapping. I don't
see any sanitisation for writes using the ZCR_EL1 accessor, which is
the common case. This needs fixing at the same time.
>
> Fixes: b3d29a823099 ("KVM: arm64: nv: Handle ZCR_EL2 traps")
> Signed-off-by: Mark Brown <broonie@kernel.org>
Given the nature of the bug, this needs a Cc: stable.
> ---
> arch/arm64/kvm/hyp/include/hyp/switch.h | 8 ++++----
> arch/arm64/kvm/sys_regs.c | 6 +-----
> 2 files changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
> index bf0eb5e43427..fd277cb70967 100644
> --- a/arch/arm64/kvm/hyp/include/hyp/switch.h
> +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
> @@ -501,11 +501,11 @@ static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu)
> return;
>
> if (vcpu_has_sve(vcpu)) {
> + zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
> +
> /* A guest hypervisor may restrict the effective max VL. */
> - if (is_nested_ctxt(vcpu))
> - zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2);
> - else
> - zcr_el2 = vcpu_sve_max_vq(vcpu) - 1;
> + if (is_nested_ctxt(vcpu) && !is_hyp_ctxt(vcpu))
> + zcr_el2 = min(zcr_el2, __vcpu_sys_reg(vcpu, ZCR_EL2));
Why the change in the condition guarding this? Given the definition of
is_nested_ctxt(), this seems unnecessary.
>
> write_sysreg_el2(zcr_el2, SYS_ZCR);
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 148fc3400ea8..c4d3bbae2d14 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -2862,8 +2862,6 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu,
> struct sys_reg_params *p,
> const struct sys_reg_desc *r)
> {
> - unsigned int vq;
> -
> if (guest_hyp_sve_traps_enabled(vcpu)) {
> kvm_inject_nested_sve_trap(vcpu);
> return false;
> @@ -2874,9 +2872,7 @@ static bool access_zcr_el2(struct kvm_vcpu *vcpu,
> return true;
> }
>
> - vq = SYS_FIELD_GET(ZCR_ELx, LEN, p->regval) + 1;
> - vq = min(vq, vcpu_sve_max_vq(vcpu));
> - __vcpu_assign_sys_reg(vcpu, ZCR_EL2, vq - 1);
> + __vcpu_assign_sys_reg(vcpu, ZCR_EL2, p->regval & ZCR_ELx_LEN);
Once you have added the full ZCR_EL2 sanitisation, this masking can go.
> return true;
> }
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
next prev parent reply other threads:[~2026-05-23 8:44 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-22 18:00 [PATCH] KVM: arm64: Preserve all guest ZCR_EL2.LEN values Mark Brown
2026-05-23 8:47 ` Marc Zyngier [this message]
2026-05-23 14:38 ` Mark Brown
2026-05-23 15:24 ` Marc Zyngier
2026-05-25 18:36 ` Mark Rutland
2026-05-26 10:19 ` Mark Brown
2026-05-26 12:03 ` Mark Rutland
2026-05-26 13:03 ` Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87h5nya4wl.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=oupton@kernel.org \
--cc=seiden@linux.ibm.com \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.