From: Alexandru Elisei <alexandru.elisei@arm.com>
To: sashiko-reviews@lists.linux.dev
Cc: Oliver Upton <oupton@kernel.org>, Marc Zyngier <maz@kernel.org>,
kvmarm@lists.linux.dev, linux-perf-users@vger.kernel.org
Subject: Re: [RFC PATCH v7 17/28] KVM: arm64: Apply a RES0 mask to PMBLIMITR_EL1 writes
Date: Fri, 4 Sep 2026 11:41:24 +0100 [thread overview]
Message-ID: <apqgVBwelJtyuwBq@e140010.arm.com> (raw)
In-Reply-To: <20260903163758.22D8D1F000E9@smtp.kernel.org>
Hi Sashiko,
On Thu, Sep 03, 2026 at 04:37:57PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> - [Critical] get_user_spe_sysreg() and set_user_spe_sysreg() return -EBUSY before SPE initialization, violating the KVM_GET_REG_LIST contract.
> - [High] Userspace can bypass the PMBLIMITR_EL1 RES0 mask by writing to the register before the first KVM_RUN.
> - [Low] Missing READ_ONCE() when accessing pmblimitr_el1_res0_mask causes a data race.
> --
>
> commit 1270412c2611a30b1f16a0aa9858eb290c7f9768
> Author: Alexandru Elisei <alexandru.elisei@arm.com>
>
> KVM: arm64: Apply a RES0 mask to PMBLIMITR_EL1 writes
>
> This commit introduces a RES0 mask for PMBLIMITR_EL1 to hide unsupported
> granule sizes from the guest. It computes this mask during the vCPU's
> first run and applies it when userspace or the guest writes to the register.
>
> > diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c
> > index 6a00a44c73edf..8c173a1f48bd4 100644
> > --- a/arch/arm64/kvm/spe.c
> > +++ b/arch/arm64/kvm/spe.c
> [ ... ]
> > @@ -60,13 +60,43 @@ bool kvm_supports_spe(void)
> [ ... ]
> > int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
> > {
> > + struct kvm *kvm = vcpu->kvm;
> > + struct kvm_spe *kvm_spe = &kvm->arch.kvm_spe;
> >
> > - if (!vcpu_spe->initialized)
> > + if (!kvm_vcpu_spe_initialized(vcpu))
> > return -EINVAL;
> >
> > + if (!kvm_spe->pmblimitr_el1_res0_mask)
>
> [Severity: Low]
> Does this plain read of pmblimitr_el1_res0_mask need a READ_ONCE() to
> prevent compiler-induced load tearing?
>
> The mask is updated locklessly using WRITE_ONCE() inside
> kvm_spe_compute_pmblimitr_el1_res0_mask(). Without a READ_ONCE() here,
> concurrent vCPU executions could trigger a data race.
Ok.
>
> > + kvm_spe_compute_pmblimitr_el1_res0_mask(kvm);
> >
> > return 0;
> > }
> > @@ -85,8 +115,12 @@ void kvm_spe_destroy_vm(struct kvm *kvm)
> >
> > bool kvm_spe_write_sysreg(struct kvm_vcpu *vcpu, int reg, u64 val)
> > {
> > + struct kvm_spe *kvm_spe = &vcpu->kvm->arch.kvm_spe;
> > +
> > switch (reg) {
> > case PMBLIMITR_EL1:
> > + val &= ~kvm_spe->pmblimitr_el1_res0_mask;
>
> [Severity: High]
> Can userspace bypass this RES0 sanitization?
>
> If the VMM calls KVM_SET_ONE_REG for PMBLIMITR_EL1 before running the vCPU
> for the first time, pmblimitr_el1_res0_mask will still be 0.
>
> Because the mask isn't computed until the first run, the bitwise NOT evaluates
> to all 1s (val &= ~0), which leaves the user-provided value unmodified and
> potentially exposes the host hardware to unsupported granule configurations.
That's correct, I assumed here that userspace will be aware of the
constraints on PMBLIMITR_EL1 due to missing architectural features and write the
correct value.
Is that placing a too high a burden on userspace? If it is, I can recompute
PMBLIMITR_EL1 when the VCPU is first run.
>
> [Severity: Low]
> Does this mask read also need a READ_ONCE() to safely pair with the
> WRITE_ONCE() update, similar to the check in kvm_spe_vcpu_first_run_init()?
Ok.
>
> > + fallthrough;
> > case PMBSR_EL1:
> > case PMBPTR_EL1:
> > __vcpu_assign_sys_reg(vcpu, reg, val);
>
> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 89b01b6ac7830..4c4bf88c9aa53 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> [ ... ]
> > @@ -1563,6 +1563,38 @@ static unsigned int spe_visibility(const struct kvm_vcpu *vcpu,
> > return REG_HIDDEN;
> > }
> >
> > +static int set_user_spe_sysreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> > + u64 val)
> > +{
> > + int reg = r->reg;
> > +
> > + if (!kvm_vcpu_spe_initialized(vcpu))
> > + return -EBUSY;
>
> [Severity: Critical]
> Does returning -EBUSY here break the KVM_GET_REG_LIST ABI contract?
>
> spe_visibility() currently exposes SPE registers based purely on
> vcpu_has_spe(). Because of this, KVM_GET_REG_LIST will advertise the SPE
> registers immediately after a vCPU is created with the SPE feature.
>
> If a VMM queries the register list and then calls KVM_GET_ONE_REG or
> KVM_SET_ONE_REG before KVM_ARM_VCPU_SPE_INIT is called, it will unexpectedly
> hit this -EBUSY path and fail. The KVM API requires that any register
> returned by KVM_GET_REG_LIST must be successfully readable via
> KVM_GET_ONE_REG.
I can't help but notice an inconsistency: here you say that any register
returned by KVM_GET_REG_LIST must be successfully *readable*, yet above you're
saying that a it is a *write* that breaks the KVM_GET_REG_LIST ABI contract.
Regardless, I think you're right. I only put the check there so I can update the
interrupt level on a PMBSR_EL1 write (implemented later in the series). What I
can do is try to update the interrupt level when the VCPU is first run,
alongside applying the res0 mask to PMBLIMITR_EL1.
Thanks,
Alex
>
> > +
> > + if (reg == PMBLIMITR_EL1 || reg == PMBPTR_EL1 || reg == PMBSR_EL1)
> > + kvm_spe_write_sysreg(vcpu, reg, val);
> > + else
> > + __vcpu_assign_sys_reg(vcpu, reg, val);
> > +
> > + return 0;
> > +}
> > +
> > +static int get_user_spe_sysreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
> > + u64 *val)
> > +{
> > + int reg = r->reg;
> > +
> > + if (!kvm_vcpu_spe_initialized(vcpu))
> > + return -EBUSY;
> > +
> > + if (reg == PMBLIMITR_EL1 || reg == PMBPTR_EL1 || reg == PMBSR_EL1)
> > + *val = kvm_spe_read_sysreg(vcpu, reg);
> > + else
> > + *val = __vcpu_sys_reg(vcpu, reg);
> > +
> > + return 0;
> > +}
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260903160623.315525-1-alexandru.elisei@arm.com?part=17
next prev parent reply other threads:[~2026-09-04 10:41 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 16:05 [RFC PATCH v7 00/28] KVM: arm64: Add Statistical Profiling Extension (SPE) support Alexandru Elisei
2026-09-03 16:05 ` [RFC PATCH v7 01/28] arm64/sysreg: Add the nVM field to PMBLIMITR_EL1 Alexandru Elisei
2026-09-03 16:14 ` sashiko-bot
2026-09-03 16:05 ` [RFC PATCH v7 02/28] arm64/sysreg: Define MDCR_EL2.E2PB values Alexandru Elisei
2026-09-03 16:12 ` sashiko-bot
2026-09-03 16:05 ` [RFC PATCH v7 03/28] KVM: arm64: Add CONFIG_KVM_ARM_SPE Kconfig option Alexandru Elisei
2026-09-03 16:13 ` sashiko-bot
2026-09-03 16:05 ` [RFC PATCH v7 04/28] perf: arm_spe_pmu: Move struct arm_spe_pmu to a separate header file Alexandru Elisei
2026-09-03 16:11 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 05/28] perf: arm_spe_pmu: Add PMBIDR_EL1 and PMSIDR_EL1 to struct arm_spe_pmu Alexandru Elisei
2026-09-03 16:11 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 06/28] KVM: arm64: Add KVM_CAP_ARM_SPE capability Alexandru Elisei
2026-09-03 16:15 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 07/28] KVM: arm64: Add KVM_ARM_VCPU_SPE VCPU feature Alexandru Elisei
2026-09-03 16:21 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 08/28] HACK! KVM: arm64: Disable SPE virtualization if protected KVM is enabled Alexandru Elisei
2026-09-03 16:21 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 09/28] HACK! KVM: arm64: Enable SPE virtualization only in VHE mode Alexandru Elisei
2026-09-03 16:15 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 10/28] HACK! KVM: arm64: Disable SPE virtualization if nested virt is enabled Alexandru Elisei
2026-09-03 16:20 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 11/28] KVM: arm64: Add a new VCPU device control group for SPE Alexandru Elisei
2026-09-03 16:22 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 12/28] KVM: arm64: Add SPE VCPU device attribute to set the interrupt number Alexandru Elisei
2026-09-03 16:27 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 13/28] KVM: arm64: Add SPE VCPU device attribute to set the SPE device Alexandru Elisei
2026-09-03 16:39 ` sashiko-bot
2026-09-04 9:32 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 14/28] KVM: arm64: Add SPE VCPU device attribute to initialize SPE Alexandru Elisei
2026-09-03 16:28 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 15/28] KVM: arm64: Use PMSVer from the assigned SPE instance Alexandru Elisei
2026-09-03 16:41 ` sashiko-bot
2026-09-04 10:26 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 16/28] KVM: arm64: Add SPE system registers to VCPU context Alexandru Elisei
2026-09-03 16:32 ` sashiko-bot
2026-09-04 10:28 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 17/28] KVM: arm64: Apply a RES0 mask to PMBLIMITR_EL1 writes Alexandru Elisei
2026-09-03 16:37 ` sashiko-bot
2026-09-04 10:41 ` Alexandru Elisei [this message]
2026-09-03 16:06 ` [RFC PATCH v7 18/28] KVM: arm64: config: Use functions from spe.c to test FEAT_SPE_{FnE,FDS} Alexandru Elisei
2026-09-03 16:40 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 19/28] KVM: arm64: VHE: Context switch SPE state Alexandru Elisei
2026-09-03 16:43 ` sashiko-bot
2026-09-04 11:35 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 20/28] KVM: arm64: Allow guest SPE physical timestamps only if kernel allows it Alexandru Elisei
2026-09-03 16:48 ` sashiko-bot
2026-09-04 13:45 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 21/28] KVM: arm64: Handle SPE maintenance interrupts Alexandru Elisei
2026-09-03 16:58 ` sashiko-bot
2026-09-04 14:04 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 22/28] arm64: errata: Disable SPE in KVM Alexandru Elisei
2026-09-03 16:50 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 23/28] KVM: arm64: Add kvm-arm.ignore_spe_errata kernel parameter Alexandru Elisei
2026-09-03 16:46 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 24/28] arm64: errata: Don't enable guest buffer if misprogrammed Alexandru Elisei
2026-09-03 17:00 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 25/28] KVM: arm64: at: Use callback for reading descriptor Alexandru Elisei
2026-09-03 16:51 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 26/28] KVM: arm64: Map memory on a SPE stage 2 fault Alexandru Elisei
2026-09-03 17:08 ` sashiko-bot
2026-09-03 16:06 ` [RFC PATCH v7 27/28] KVM: arm64: Handle dirty page logging when SPE feature is set Alexandru Elisei
2026-09-03 17:06 ` sashiko-bot
2026-09-04 14:41 ` Alexandru Elisei
2026-09-03 16:06 ` [RFC PATCH v7 28/28] KVM: arm64: Allow the creation of a SPE enabled VM Alexandru Elisei
2026-09-03 16:59 ` sashiko-bot
2026-09-04 14:09 ` Alexandru Elisei
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=apqgVBwelJtyuwBq@e140010.arm.com \
--to=alexandru.elisei@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-perf-users@vger.kernel.org \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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.