From: sashiko-bot@kernel.org
To: "Yong-Xuan Wang" <yongxuan.wang@sifive.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH] KVM: RISC-V: Add CPU PM notifier for non-retention idle states
Date: Thu, 25 Jun 2026 01:50:42 +0000 [thread overview]
Message-ID: <20260625015043.26C701F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260624-kvm-cpu-pm-v1-1-52088e127a55@sifive.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [Critical] The `SYSTEM_SUSPEND` check in the CPU PM notifier incorrectly skips CSR save/restore during suspend-to-idle (s2idle).
- [Critical] CPU PM notifier fails to clear KVM's vCPU cache, leading to guest context loss and a potential sandbox escape.
- [High] Missing restoration of `CSR_HIE` (Hypervisor Interrupt Enable) for Guest External Interrupts (`IRQ_S_GEXT`) on CPU PM exit.
- [High] SBI NACL (Nested Acceleration) shared memory configuration is not restored on CPU PM exit.
- [High] The KVM CPU PM notifier fails to handle `CPU_PM_ENTER_FAILED`, leaving hypervisor CSRs permanently disabled if a suspend transition aborts.
- [Medium] The PM notifier may unconditionally run and use uninitialized AIA state, writing `~0UL` to `CSR_HGEIE` if KVM hardware virtualization is not yet fully enabled.
--
commit 107ddca84d721ec26cecb9bff7a0c2d5722c8a92
Author: Yong-Xuan Wang <yongxuan.wang@sifive.com>
Subject: KVM: RISC-V: Add CPU PM notifier for non-retention idle states
This patch registers a CPU_PM notifier to restore hypervisor CSR content
during CPU non-retention idle states. It handles state saving and restoring
when a CPU enters deep idle states that power off the CPU domain.
> diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
> index bafb009c5ce55..82812493ac684 100644
> --- a/arch/riscv/kvm/aia.c
> +++ b/arch/riscv/kvm/aia.c
[ ... ]
> @@ -532,50 +532,61 @@ static void aia_hgei_exit(void)
[ ... ]
> - raw_spin_lock_irqsave(&hgctrl->lock, flags);
> - if (!hgctrl->free_bitmap_initialized) {
> - hgctrl->free_bitmap = (hgctrl->nr_hgei) ? GENMASK_ULL(hgctrl->nr_hgei, 1) : 0;
> - hgctrl->free_bitmap_initialized = true;
> + raw_spin_lock_irqsave(&hgctrl->lock, flags);
> + if (!hgctrl->free_bitmap_initialized) {
> + hgctrl->free_bitmap = (hgctrl->nr_hgei) ?
> + GENMASK_ULL(hgctrl->nr_hgei, 1) :
> + 0;
> + hgctrl->free_bitmap_initialized = true;
> + }
> + raw_spin_unlock_irqrestore(&hgctrl->lock, flags);
> + } else {
> + raw_spin_lock_irqsave(&hgctrl->lock, flags);
> + csr_write(CSR_HGEIE, ~hgctrl->free_bitmap);
> + raw_spin_unlock_irqrestore(&hgctrl->lock, flags);
> }
[Severity: Medium]
Since cpu_pm_register_notifier() is called in riscv_kvm_init() before
kvm_init() has called hardware_enable_all(), can this PM notifier
unconditionally run before KVM hardware virtualization is fully enabled?
If a CPU enters and exits idle in this window, kvm_riscv_aia_enable(false)
writes ~hgctrl->free_bitmap to CSR_HGEIE. Because free_bitmap is
uninitialized (0), this writes ~0UL, which could lead to unexpected behavior.
[ ... ]
> - /* Enable per-CPU SGEI interrupt */
> - enable_percpu_irq(hgei_parent_irq,
> - irq_get_trigger_type(hgei_parent_irq));
> - csr_set(CSR_HIE, BIT(IRQ_S_GEXT));
> + if (full_cleanup) {
> + /* Enable per-CPU SGEI interrupt */
> + enable_percpu_irq(hgei_parent_irq,
> + irq_get_trigger_type(hgei_parent_irq));
> + csr_set(CSR_HIE, BIT(IRQ_S_GEXT));
> + }
[Severity: High]
Does this prevent the restoration of CSR_HIE for guest external interrupts on
CPU PM exit?
When a CPU enters a non-retention deep idle state, hypervisor CSRs lose their
state. On PM exit, kvm_riscv_aia_enable(false) is invoked. However, because
full_cleanup is false, the CSR_HIE bit is never re-enabled.
This seems like it would cause the host CPU to permanently stop receiving
supervisor guest external interrupts, breaking interrupt delivery to VMs.
[ ... ]
> diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
> index 0924c75100a2d..41ef91ea39218 100644
> --- a/arch/riscv/kvm/main.c
> +++ b/arch/riscv/kvm/main.c
[ ... ]
> +static int kvm_riscv_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v)
> +{
> + /*
> + * To avoid redundant disable/enable operations (since KVM's
> + * syscore ops will handle the state during system suspend),
> + * ignore CPU_PM events when a system suspend/resume is in
> + * progress.
> + */
> + if (system_state == SYSTEM_SUSPEND)
> + return NOTIFY_DONE;
[Severity: Critical]
Does this check incorrectly skip CSR save/restore during suspend-to-idle
(s2idle)?
During s2idle, CPUs are pushed into the idle loop instead of being hotplugged
offline, and syscore suspend callbacks do not execute. When the last CPU
freezes its tick, system_state is set to SYSTEM_SUSPEND. When CPUs
subsequently enter deep idle, KVM's notifier skips the state save due to this
check, completely destroying the hypervisor state on resume.
> +
> + switch (cmd) {
> + case CPU_PM_EXIT:
> + kvm_riscv_csr_enable();
> + kvm_riscv_aia_enable(false);
> + return NOTIFY_OK;
[Severity: High]
Does this omit the restoration of SBI nested acceleration (NACL) shared memory
configuration?
Firmware does not preserve extension-specific shared memory configuration across
non-retentive CPU suspend states. The PM exit handler restores base CSRs and
AIA, but lacks a call to kvm_riscv_nacl_enable(). This seems like it would
cause the NACL shmem mapping to be permanently lost on the CPU, breaking nested
virtualization acceleration.
[Severity: Critical]
Does the CPU PM notifier also need to clear KVM's vCPU cache to prevent guest
context loss?
kvm_arch_vcpu_load() in arch/riscv/kvm/vcpu.c skips writing guest CSRs and
HGATP if vcpu matches the former vcpu and last_exit_cpu matches the current
cpu:
if (vcpu != __this_cpu_read(kvm_former_vcpu))
__this_cpu_write(kvm_former_vcpu, vcpu);
else if (vcpu->arch.last_exit_cpu == cpu && !vcpu->arch.csr_dirty)
goto csr_restore_done;
A non-retention idle state destroys the hardware CSR context (resetting them
to 0). Because the PM notifier does not clear kvm_former_vcpu, a VCPU
rescheduled on the same CPU after wakeup will hit this fast-path and execute
with zeroed hardware CSRs.
Entering guest mode with HGATP=0 configures G-stage translation to bare mode,
mapping guest physical addresses directly to host physical memory. Can this
lead to a trivial sandbox escape?
> + case CPU_PM_ENTER:
> + kvm_riscv_aia_disable(false);
> + kvm_riscv_csr_disable();
> + return NOTIFY_OK;
> + default:
> + break;
> + }
> +
> + return NOTIFY_DONE;
> +}
[Severity: High]
Does this switch statement fail to handle CPU_PM_ENTER_FAILED?
If a subsequent notifier in the chain fails after KVM disables its hypervisor
CSRs on CPU_PM_ENTER, the PM subsystem aborts the suspend sequence and
broadcasts CPU_PM_ENTER_FAILED. Because KVM's notifier lacks a case for it,
it ignores this event.
Will this leave KVM's hypervisor CSRs permanently disabled until a full offline
and online cycle?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624-kvm-cpu-pm-v1-1-52088e127a55@sifive.com?part=1
prev parent reply other threads:[~2026-06-25 1:50 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-25 1:34 [PATCH] KVM: RISC-V: Add CPU PM notifier for non-retention idle states Yong-Xuan Wang
2026-06-25 1:34 ` Yong-Xuan Wang
2026-06-25 1:34 ` Yong-Xuan Wang
2026-06-25 1:50 ` sashiko-bot [this message]
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=20260625015043.26C701F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=yongxuan.wang@sifive.com \
/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.