From: sashiko-bot@kernel.org
To: "Fuad Tabba" <fuad.tabba@linux.dev>
Cc: kvmarm@lists.linux.dev, "Oliver Upton" <oupton@kernel.org>,
"Marc Zyngier" <maz@kernel.org>
Subject: Re: [PATCH v4 16/18] KVM: arm64: Reject host power-on of a vCPU that EL2 holds powered off
Date: Thu, 01 Oct 2026 14:18:27 +0000 [thread overview]
Message-ID: <20261001141827.B97661F00899@smtp.kernel.org> (raw)
In-Reply-To: <20261001135711.1640520-17-fuad.tabba@linux.dev>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] arm64: PSCI CPU_ON spuriously fails for protected secondary vCPUs
- [Medium] arm64: KVM_SET_MP_STATE rejects KVM_MP_STATE_UNINITIALIZED with -EINVAL
--
commit f4c00ca4b159d4b7954978f9de7770cc8b67b029
Author: Fuad Tabba <fuad.tabba@linux.dev>
KVM: arm64: Reject host power-on of a vCPU that EL2 holds powered off
This patch records a protected vCPU held powered off by EL2 as
KVM_MP_STATE_UNINITIALIZED. It restricts KVM_SET_MP_STATE from overwriting
this value with RUNNABLE or SUSPENDED, and updates the guest CPU_ON checks
to gate on this state rather than STOPPED.
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 14fe4e7275796..a89087c83e27f 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
[ ... ]
> @@ -818,12 +829,24 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
>
> switch (mp_state->mp_state) {
> case KVM_MP_STATE_RUNNABLE:
> + if (kvm_pkvm_vcpu_is_powered_off(vcpu)) {
> + ret = -EPERM;
> + break;
> + }
> +
> WRITE_ONCE(vcpu->arch.mp_state, *mp_state);
> break;
> case KVM_MP_STATE_STOPPED:
> - __kvm_arm_vcpu_power_off(vcpu);
> + /* Keep EL2's off record: STOPPED over it would let RUNNABLE through. */
> + if (!kvm_pkvm_vcpu_is_powered_off(vcpu))
> + __kvm_arm_vcpu_power_off(vcpu, KVM_MP_STATE_STOPPED);
> break;
> case KVM_MP_STATE_SUSPENDED:
> + if (kvm_pkvm_vcpu_is_powered_off(vcpu)) {
> + ret = -EPERM;
> + break;
> + }
> +
> kvm_arm_vcpu_suspend(vcpu);
> break;
> default:
> ret = -EINVAL;
> }
[Severity: Medium]
Does this break the userspace API for KVM_SET_MP_STATE?
The switch statement lacks a case for KVM_MP_STATE_UNINITIALIZED, defaulting
to -EINVAL for a state that KVM now actively exposes. If a userspace VMM
attempts to save and restore the state by reading via KVM_GET_MP_STATE and
later passing that exact state back via KVM_SET_MP_STATE, it will fail with
-EINVAL. Can we add a case to properly handle the uninitialized state?
[ ... ]
> @@ -1788,7 +1811,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
> spin_lock(&vcpu->arch.mp_state_lock);
>
> if (power_off)
> - __kvm_arm_vcpu_power_off(vcpu);
> + __kvm_arm_vcpu_power_off(vcpu, KVM_MP_STATE_STOPPED);
[Severity: High]
Can this cause a spurious PSCI_RET_ALREADY_ON failure when booting secondary
protected vCPUs?
When the VMM initializes a secondary protected vCPU with
KVM_ARM_VCPU_POWER_OFF, it explicitly hardcodes its mp_state to
KVM_MP_STATE_STOPPED here.
> else
> WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_RUNNABLE);
>
[ ... ]
> diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> index e3db84400d1f8..b01f8d44033f1 100644
> --- a/arch/arm64/kvm/psci.c
> +++ b/arch/arm64/kvm/psci.c
> @@ -63,7 +63,12 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
> return PSCI_RET_INVALID_PARAMS;
>
> spin_lock(&vcpu->arch.mp_state_lock);
> - if (!kvm_arm_vcpu_stopped(vcpu)) {
> + /*
> + * A protected vCPU is off once the host has acted on EL2's CPU_OFF.
> + * STOPPED before that is the VMM's pause.
> + */
> + if (!kvm_arm_vcpu_stopped(vcpu) ||
> + (vcpu_is_protected(vcpu) && !kvm_pkvm_vcpu_is_powered_off(vcpu))) {
> if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
> ret = PSCI_RET_ALREADY_ON;
> else
[Severity: High]
Following up on the KVM_ARM_VCPU_POWER_OFF initialization above, does this
condition incorrectly reject guest CPU_ON requests?
If the primary vCPU executes a PSCI CPU_ON call before the secondary vCPU
thread has executed its first KVM_RUN, __pkvm_create_hyp_vcpu() hasn't yet
upgraded the state to KVM_MP_STATE_UNINITIALIZED.
Consequently, when kvm_psci_vcpu_on() evaluates the condition above, it
sees the vCPU as STOPPED but not UNINITIALIZED. The condition evaluates
to true, causing it to return PSCI_RET_ALREADY_ON to the guest. This
deterministically breaks SMP boot for protected VMs on VMMs that block
secondary vCPU threads prior to wakeup.
Should kvm_arch_vcpu_ioctl_vcpu_init() directly set the state to
KVM_MP_STATE_UNINITIALIZED for protected vCPUs to avoid this race?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261001135711.1640520-1-fuad.tabba@linux.dev?part=16
next prev parent reply other threads:[~2026-10-01 14:18 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 13:56 [PATCH v4 00/18] KVM: arm64: Confine protected VM vCPU state to EL2 Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 01/18] KVM: arm64: Sync HCR_EL2.VSE back to the host vCPU under pKVM Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 02/18] KVM: arm64: Validate the host vCPU's VM before reading it " Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 03/18] KVM: arm64: Pin the host vCPU before adjusting its PC " Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 04/18] KVM: arm64: Disable steal time for protected VMs Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 05/18] KVM: arm64: Introduce per-EC entry handlers for pKVM Fuad Tabba
2026-10-01 13:56 ` [PATCH v4 06/18] KVM: arm64: Skip fixed-feature state flush for protected vCPUs Fuad Tabba
2026-10-01 14:19 ` sashiko-bot
2026-10-01 15:06 ` Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 07/18] KVM: arm64: Add {flush,sync}_hyp_timer_state() primitives Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 08/18] KVM: arm64: Add system register reset framework for protected VMs Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 09/18] KVM: arm64: Implement HVC handling for protected guests at EL2 Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 10/18] KVM: arm64: Handle PSCI calls for protected VMs " Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 11/18] KVM: arm64: Restrict KVM_ARM_VCPU_INIT and PSCI version for protected VMs Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 12/18] KVM: arm64: Prevent host PC adjustments for protected vCPUs Fuad Tabba
2026-10-01 14:21 ` sashiko-bot
2026-10-01 15:08 ` Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 13/18] KVM: arm64: Inject an UNDEF at EL2 for unhandled protected guest exits Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 14/18] KVM: arm64: Add per-EC entry/exit state marshalling for protected guests Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 15/18] KVM: arm64: Reject host access to protected VM private state Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 16/18] KVM: arm64: Reject host power-on of a vCPU that EL2 holds powered off Fuad Tabba
2026-10-01 14:18 ` sashiko-bot [this message]
2026-10-01 15:10 ` Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 17/18] KVM: arm64: Advertise the capabilities that protected VMs support Fuad Tabba
2026-10-01 13:57 ` [PATCH v4 18/18] KVM: arm64: Document the protected VM userspace API Fuad Tabba
2026-10-01 14:31 ` [PATCH v4 00/18] KVM: arm64: Confine protected VM vCPU state to EL2 Fuad Tabba
2026-10-02 15:55 ` Marc Zyngier
2026-10-03 6:57 ` Fuad Tabba
2026-10-03 8:38 ` Marc Zyngier
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=20261001141827.B97661F00899@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=fuad.tabba@linux.dev \
--cc=kvmarm@lists.linux.dev \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox