[PW_SID:1127828] [v5] RISC-V: KVM: Serialize virtual interrupt pending state updates#2286
[PW_SID:1127828] [v5] RISC-V: KVM: Serialize virtual interrupt pending state updates#2286linux-riscv-bot wants to merge 3 commits into
Conversation
setup_smp() calls set_cpu_possible() for CPUs 1..nr_cpu_ids-1 but never for CPU 0 (the boot CPU). x86 handles this via init_cpu_possible(cpumask_of(0)); RISC-V has no equivalent. Without CPU 0 in cpu_possible_mask, rcu_init_one()'s for_each_possible_cpu() loop skips it, leaving rdp->mynode=NULL. rcutree_prepare_cpu() then dereferences NULL and hangs. Exposed on Sophgo SG2042 (64-hart, 4-NUMA) with Linux 7.2-rc3. Cc: stable@vger.kernel.org Fixes: a4166ae ("riscv: Deduplicate code in setup_smp()") Signed-off-by: Paul Sherman <shermanpauldylan@gmail.com> Link: https://patch.msgid.link/20260714223301.5265-1-shermanpauldylan@gmail.com Signed-off-by: Paul Walmsley <pjw@kernel.org>
RISC-V KVM tracks guest interrupt state with two bitmaps:
- irqs_pending: interrupts that should be visible to the guest
- irqs_pending_mask: interrupts whose pending state changed
The current code updates those bitmaps with independent atomic bitops
and assumes a multiple-producer, single-consumer protocol. That model
does not actually hold.
kvm_riscv_vcpu_sync_interrupts() is not a pure consumer. When the guest
changes guest-visible HVIP state, sync_interrupts() writes both
irqs_pending and irqs_pending_mask to reflect the new guest state back
into KVM state. As a result, irqs_pending and irqs_pending_mask form a
single logical state transition, but they are not updated atomically as
a pair.
This allows a race where a newly injected interrupt is lost. For
example:
CPU0 CPU1
---- ----
kvm_riscv_vcpu_set_interrupt(VS_SOFT)
set_bit(VS_SOFT, irqs_pending)
kvm_riscv_vcpu_sync_interrupts()
sees guest-cleared HVIP.VSSIP
sets irqs_pending_mask
clear_bit(IRQ_VS_SOFT, irqs_pending)
set_bit(VS_SOFT, irqs_pending_mask)
kvm_vcpu_kick()
After that interleaving, a later flush can update HVIP without VSSIP
even though a new virtual interrupt was injected. In practice, the
guest can remain blocked in WFI with work pending.
The same pending/mask protocol is shared by VS soft interrupts, PMU
overflow delivery, and AIA high interrupt synchronization, so the race
is not limited to one interrupt source.
Fix this by serializing all updates to irqs_pending and
irqs_pending_mask with a per-vCPU raw spinlock. This keeps the pending
bit and the dirty mask as one state transition across:
- set/unset interrupt
- guest HVIP sync
- interrupt flush to guest CSR state
- vCPU reset
- AIA CSR writes that clear dirty state
Use non-atomic bitmap operations while holding the lock. Hold the lock
across the AIA sync, flush, and pending checks as well, so both bitmap
words share the same serialization domain.
This intentionally replaces the existing lockless protocol instead of
trying to repair it with additional barriers. The problem is not memory
ordering on a single field; it is that two separate bitmaps encode one
shared state machine while both producers and sync paths can modify
them. A per-vCPU raw spinlock keeps the fix small, local, and suitable
for backporting.
Fixes: cce69af ("RISC-V: KVM: Implement VCPU interrupts and requests handling")
Cc: stable@vger.kernel.org
Signed-off-by: Xie Bo <xb@ultrarisc.com>
Signed-off-by: Linux RISC-V bot <linux.riscv.bot@gmail.com>
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
|
Patch 1: "[v5] RISC-V: KVM: Serialize virtual interrupt pending state updates" |
60e0882 to
36eafdd
Compare
PR for series 1127828 applied to workflow__riscv__fixes
Name: [v5] RISC-V: KVM: Serialize virtual interrupt pending state updates
URL: https://patchwork.kernel.org/project/linux-riscv/list/?series=1127828
Version: 5