* [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
@ 2026-10-22 21:55 Sean Christopherson
2026-10-22 21:55 ` [PATCH 1/2] KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion Sean Christopherson
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Sean Christopherson @ 2026-10-22 21:55 UTC (permalink / raw)
To: Vitaly Kuznetsov, Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Stefan Teodorescu
Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
strictly scoped to module init/exit, or similar, to ONCE() variants for what
should be fairly obvious reasons at this point.
Sean Christopherson (2):
KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion
KVM: x86: Convert all runtime WARNs to ONCE variants
arch/x86/kvm/hyperv.c | 2 +-
arch/x86/kvm/i8254.c | 2 +-
arch/x86/kvm/irq.c | 4 ++--
arch/x86/kvm/lapic.c | 17 ++++++++++-------
arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
arch/x86/kvm/msrs.c | 2 +-
arch/x86/kvm/svm/avic.c | 2 +-
arch/x86/kvm/svm/nested.c | 12 ++++++------
arch/x86/kvm/svm/sev.c | 2 +-
arch/x86/kvm/svm/svm.c | 12 ++++++------
arch/x86/kvm/vmx/nested.c | 12 ++++++------
arch/x86/kvm/vmx/posted_intr.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 8 ++++----
arch/x86/kvm/x86.c | 18 +++++++++---------
arch/x86/kvm/x86.h | 2 +-
15 files changed, 51 insertions(+), 48 deletions(-)
base-commit: 814607cd40df80d5727957adaa857e0feca43497
--
2.56.0.257.gf7497c7d27-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion
2026-10-22 21:55 [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Sean Christopherson
@ 2026-10-22 21:55 ` Sean Christopherson
2026-10-22 21:55 ` [PATCH 2/2] KVM: x86: Convert all runtime WARNs to ONCE variants Sean Christopherson
2026-10-23 14:59 ` [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Yosry Ahmed
2 siblings, 0 replies; 8+ messages in thread
From: Sean Christopherson @ 2026-10-22 21:55 UTC (permalink / raw)
To: Vitaly Kuznetsov, Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Stefan Teodorescu
Use lockdep_assert_preemption_disabled() in the local APIC code instead of
open-coding a rough equivalent that would likely do more harm than good if
it were to ever fire (the non-ONCE WARN_ON() would likely spam the kernel
log and hang the host).
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/lapic.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ecf611845fb1..61bf09badb5a 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2270,7 +2270,8 @@ bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
static void cancel_hv_timer(struct kvm_lapic *apic)
{
- WARN_ON(preemptible());
+ lockdep_assert_preemption_disabled();
+
WARN_ON(!apic->lapic_timer.hv_timer_in_use);
kvm_x86_call(cancel_hv_timer)(apic->vcpu);
apic->lapic_timer.hv_timer_in_use = false;
@@ -2282,7 +2283,8 @@ static bool start_hv_timer(struct kvm_lapic *apic)
struct kvm_vcpu *vcpu = apic->vcpu;
bool expired;
- WARN_ON(preemptible());
+ lockdep_assert_preemption_disabled();
+
if (!kvm_can_use_hv_timer(vcpu))
return false;
@@ -2322,7 +2324,8 @@ static void start_sw_timer(struct kvm_lapic *apic)
{
struct kvm_timer *ktimer = &apic->lapic_timer;
- WARN_ON(preemptible());
+ lockdep_assert_preemption_disabled();
+
if (apic->lapic_timer.hv_timer_in_use)
cancel_hv_timer(apic);
if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
--
2.56.0.257.gf7497c7d27-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] KVM: x86: Convert all runtime WARNs to ONCE variants
2026-10-22 21:55 [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Sean Christopherson
2026-10-22 21:55 ` [PATCH 1/2] KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion Sean Christopherson
@ 2026-10-22 21:55 ` Sean Christopherson
2026-10-23 14:59 ` [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Yosry Ahmed
2 siblings, 0 replies; 8+ messages in thread
From: Sean Christopherson @ 2026-10-22 21:55 UTC (permalink / raw)
To: Vitaly Kuznetsov, Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, Stefan Teodorescu
Bulk convert all non-ONCE WARN_ON() and WARN() calls that are reachable at
runtime to have ONCE protection, as WARNing multiple times on the same
issue rarely adds value, and if KVM is flawed/buggy, unprotected WARNs can
be leveraged by a misbehaving guest to effectively DoS the host. In the
Age of AI, such flaws/bugs are depressingly easy to find.
Reported-by: Stefan Teodorescu <fane@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/hyperv.c | 2 +-
arch/x86/kvm/i8254.c | 2 +-
arch/x86/kvm/irq.c | 4 ++--
arch/x86/kvm/lapic.c | 8 ++++----
arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
arch/x86/kvm/msrs.c | 2 +-
arch/x86/kvm/svm/avic.c | 2 +-
arch/x86/kvm/svm/nested.c | 12 ++++++------
arch/x86/kvm/svm/sev.c | 2 +-
arch/x86/kvm/svm/svm.c | 12 ++++++------
arch/x86/kvm/vmx/nested.c | 12 ++++++------
arch/x86/kvm/vmx/posted_intr.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 8 ++++----
arch/x86/kvm/x86.c | 18 +++++++++---------
arch/x86/kvm/x86.h | 2 +-
15 files changed, 45 insertions(+), 45 deletions(-)
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 5d2e3617c952..d9e3d49a6cc5 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1977,7 +1977,7 @@ static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu, u64 *entries, int count,
* space, just put 'flush all' entry there.
*/
if (count && entries && count < kfifo_avail(&tlb_flush_fifo->entries)) {
- WARN_ON(kfifo_in(&tlb_flush_fifo->entries, entries, count) != count);
+ WARN_ON_ONCE(kfifo_in(&tlb_flush_fifo->entries, entries, count) != count);
goto out_unlock;
}
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 1982b0077ddd..7ad8c11a1809 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -409,7 +409,7 @@ static void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
if (hpet_legacy_start) {
/* save existing mode for later reenablement */
- WARN_ON(channel != 0);
+ WARN_ON_ONCE(channel != 0);
saved_mode = pit->pit_state.channels[0].mode;
pit->pit_state.channels[0].mode = 0xff; /* disable timer */
pit_load_count(pit, channel, val);
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index 871977288272..7f8b092b4479 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -128,7 +128,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_cpu_has_interrupt);
int kvm_cpu_get_extint(struct kvm_vcpu *v)
{
if (!kvm_cpu_has_extint(v)) {
- WARN_ON(!lapic_in_kernel(v));
+ WARN_ON_ONCE(!lapic_in_kernel(v));
return -1;
}
@@ -513,7 +513,7 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
struct kvm *kvm = irqfd->kvm;
int ret;
- WARN_ON(irqfd->producer != prod);
+ WARN_ON_ONCE(irqfd->producer != prod);
/*
* If the producer of an IRQ that is currently being posted to a vCPU
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 61bf09badb5a..08b96b124b07 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2062,7 +2062,7 @@ static void apic_timer_expired(struct kvm_lapic *apic, bool from_timer_fn)
ktimer->expired_tscdeadline = ktimer->tscdeadline;
if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {
- WARN_ON(kvm_get_running_vcpu() != vcpu);
+ WARN_ON_ONCE(kvm_get_running_vcpu() != vcpu);
kvm_apic_inject_pending_timer_irqs(apic);
return;
}
@@ -2272,7 +2272,7 @@ static void cancel_hv_timer(struct kvm_lapic *apic)
{
lockdep_assert_preemption_disabled();
- WARN_ON(!apic->lapic_timer.hv_timer_in_use);
+ WARN_ON_ONCE(!apic->lapic_timer.hv_timer_in_use);
kvm_x86_call(cancel_hv_timer)(apic->vcpu);
apic->lapic_timer.hv_timer_in_use = false;
}
@@ -2359,7 +2359,7 @@ void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
/* If the preempt notifier has already run, it also called apic_timer_expired */
if (!apic->lapic_timer.hv_timer_in_use)
goto out;
- WARN_ON(kvm_vcpu_is_blocking(vcpu));
+ WARN_ON_ONCE(kvm_vcpu_is_blocking(vcpu));
apic_timer_expired(apic, false);
cancel_hv_timer(apic);
@@ -2392,7 +2392,7 @@ void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- WARN_ON(!apic->lapic_timer.hv_timer_in_use);
+ WARN_ON_ONCE(!apic->lapic_timer.hv_timer_in_use);
restart_apic_timer(apic);
}
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 44dad106fad1..945efc1cfaea 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -1368,7 +1368,7 @@ static bool __kvm_tdp_mmu_age_gfn_range(struct kvm *kvm,
* this helper must NOT be used to unmap GFNs, as it processes only
* valid roots!
*/
- WARN_ON(types & ~KVM_VALID_ROOTS);
+ WARN_ON_ONCE(types & ~KVM_VALID_ROOTS);
guard(rcu)();
for_each_tdp_mmu_root_rcu(kvm, root, range->slot->as_id, types) {
diff --git a/arch/x86/kvm/msrs.c b/arch/x86/kvm/msrs.c
index e91650af44c2..b8ab784704fa 100644
--- a/arch/x86/kvm/msrs.c
+++ b/arch/x86/kvm/msrs.c
@@ -643,7 +643,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
r = kvm_x86_call(set_efer)(vcpu, efer);
if (r) {
- WARN_ON(r > 0);
+ WARN_ON_ONCE(r > 0);
return r;
}
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 3b037e385523..0042039e15e3 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -1042,7 +1042,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
lockdep_assert_preemption_disabled();
- if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
+ if (WARN_ON_ONCE(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
return;
if (WARN_ON_ONCE(vcpu->vcpu_id * sizeof(entry) >=
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
index af0ef678433d..ab66f07337b5 100644
--- a/arch/x86/kvm/svm/nested.c
+++ b/arch/x86/kvm/svm/nested.c
@@ -100,7 +100,7 @@ static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
- WARN_ON(mmu_is_nested(vcpu));
+ WARN_ON_ONCE(mmu_is_nested(vcpu));
vcpu->arch.mmu = &vcpu->arch.guest_mmu;
@@ -260,7 +260,7 @@ int __init nested_svm_init_msrpm_merge_offsets(void)
int bit_nr = svm_msrpm_bit_nr(merge_msrs[i]);
u32 offset;
- if (WARN_ON(bit_nr < 0))
+ if (WARN_ON_ONCE(bit_nr < 0))
return -EIO;
/*
@@ -277,7 +277,7 @@ int __init nested_svm_init_msrpm_merge_offsets(void)
if (j < nested_svm_nr_msrpm_merge_offsets)
continue;
- if (WARN_ON(j >= ARRAY_SIZE(nested_svm_msrpm_merge_offsets)))
+ if (WARN_ON_ONCE(j >= ARRAY_SIZE(nested_svm_msrpm_merge_offsets)))
return -EIO;
nested_svm_msrpm_merge_offsets[j] = offset;
@@ -1065,7 +1065,7 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, bool from_vmrun)
svm->nested.vmcb12_gpa = vmcb12_gpa;
- WARN_ON(svm->vmcb == svm->nested.vmcb02.ptr);
+ WARN_ON_ONCE(svm->vmcb == svm->nested.vmcb02.ptr);
nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr);
@@ -1716,7 +1716,7 @@ static void nested_svm_inject_exception_vmexit(struct kvm_vcpu *vcpu)
kvm_update_dr7(vcpu);
}
} else {
- WARN_ON(ex->has_payload);
+ WARN_ON_ONCE(ex->has_payload);
}
nested_svm_vmexit(svm);
@@ -2123,7 +2123,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
{
- if (WARN_ON(!is_guest_mode(vcpu)))
+ if (WARN_ON_ONCE(!is_guest_mode(vcpu)))
return true;
if (is_pae_paging(vcpu)) {
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 6427db390b1c..8cd0f1539829 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -3007,7 +3007,7 @@ void sev_vm_destroy(struct kvm *kvm)
if (!sev_guest(kvm))
return;
- WARN_ON(!list_empty(&sev->mirror_vms));
+ WARN_ON_ONCE(!list_empty(&sev->mirror_vms));
/*
* If this is a mirror VM, remove it from the owner's list of a mirrors
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 487897ef11dd..c8e82debb7f4 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1598,7 +1598,7 @@ static void svm_set_vintr(struct vcpu_svm *svm)
/*
* The following fields are ignored when AVIC is enabled
*/
- WARN_ON(kvm_vcpu_apicv_activated(&svm->vcpu));
+ WARN_ON_ONCE(kvm_vcpu_apicv_activated(&svm->vcpu));
svm_set_intercept(svm, INTERCEPT_VINTR);
@@ -1633,8 +1633,8 @@ static void svm_clear_vintr(struct vcpu_svm *svm)
if (is_guest_mode(&svm->vcpu)) {
svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
- WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
- (svm->nested.ctl.int_ctl & V_TPR_MASK));
+ WARN_ON_ONCE((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
+ (svm->nested.ctl.int_ctl & V_TPR_MASK));
svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
V_IRQ_INJECTION_BITS_MASK;
@@ -2666,7 +2666,7 @@ static int cr_interception(struct kvm_vcpu *vcpu)
err = kvm_set_cr8(vcpu, val);
break;
default:
- WARN(1, "unhandled write to CR%d", cr);
+ WARN_ONCE(1, "unhandled write to CR%d", cr);
kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
@@ -2688,7 +2688,7 @@ static int cr_interception(struct kvm_vcpu *vcpu)
val = kvm_get_cr8(vcpu);
break;
default:
- WARN(1, "unhandled read from CR%d", cr);
+ WARN_ONCE(1, "unhandled read from CR%d", cr);
kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
@@ -2725,7 +2725,7 @@ static int cr_trap(struct kvm_vcpu *vcpu)
ret = kvm_set_cr8(vcpu, new_value);
break;
default:
- WARN(1, "unhandled CR%d write trap", cr);
+ WARN_ONCE(1, "unhandled CR%d write trap", cr);
kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 9b0bfa2f854c..ec3bc441a0e6 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -515,7 +515,7 @@ static void nested_ept_new_eptp(struct kvm_vcpu *vcpu)
static void nested_ept_init_mmu_context(struct kvm_vcpu *vcpu)
{
- WARN_ON(mmu_is_nested(vcpu));
+ WARN_ON_ONCE(mmu_is_nested(vcpu));
vcpu->arch.mmu = &vcpu->arch.guest_mmu;
nested_ept_new_eptp(vcpu);
@@ -1315,7 +1315,7 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu,
}
/* L2 should never have a VPID if VPID is disabled. */
- WARN_ON(!enable_vpid);
+ WARN_ON_ONCE(!enable_vpid);
/*
* VPID is enabled and in use by vmcs12. If vpid12 is changing, then
@@ -1698,7 +1698,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
unsigned long val;
int i;
- if (WARN_ON(!shadow_vmcs))
+ if (WARN_ON_ONCE(!shadow_vmcs))
return;
preempt_disable();
@@ -1733,7 +1733,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)
unsigned long val;
int i, q;
- if (WARN_ON(!shadow_vmcs))
+ if (WARN_ON_ONCE(!shadow_vmcs))
return;
vmcs_load(shadow_vmcs);
@@ -4978,7 +4978,7 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)
kvm_set_dr(vcpu, 7, DR7_FIXED_1);
else
- WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7)));
+ WARN_ON_ONCE(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7)));
}
/* Reload DEBUGCTL to ensure vmcs01 has a fresh FREEZE_IN_SMM value. */
@@ -5408,7 +5408,7 @@ static struct vmcs *alloc_shadow_vmcs(struct kvm_vcpu *vcpu)
* doesn't support virtualization of VMCS shadowing, so vmcs01 should
* always be the loaded VMCS.
*/
- if (WARN_ON(loaded_vmcs != &vmx->vmcs01 || loaded_vmcs->shadow_vmcs))
+ if (WARN_ON_ONCE(loaded_vmcs != &vmx->vmcs01 || loaded_vmcs->shadow_vmcs))
return loaded_vmcs->shadow_vmcs;
loaded_vmcs->shadow_vmcs = alloc_vmcs(true);
diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c
index 2644add54b76..0f508015692b 100644
--- a/arch/x86/kvm/vmx/posted_intr.c
+++ b/arch/x86/kvm/vmx/posted_intr.c
@@ -187,7 +187,7 @@ static void pi_enable_wakeup_handler(struct kvm_vcpu *vcpu)
&per_cpu(wakeup_vcpus_on_cpu, vcpu->cpu));
raw_spin_unlock(&per_cpu(wakeup_vcpus_on_cpu_lock, vcpu->cpu));
- WARN(pi_test_sn(pi_desc), "PI descriptor SN field set before blocking");
+ WARN_ONCE(pi_test_sn(pi_desc), "PI descriptor SN field set before blocking");
old.control = READ_ONCE(pi_desc->control);
do {
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index b341af4c6057..0038626f5486 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -3089,7 +3089,7 @@ void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
loaded_vmcs->vmcs = NULL;
if (loaded_vmcs->msr_bitmap)
free_page((unsigned long)loaded_vmcs->msr_bitmap);
- WARN_ON(loaded_vmcs->shadow_vmcs != NULL);
+ WARN_ON_ONCE(loaded_vmcs->shadow_vmcs != NULL);
}
int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
@@ -4468,7 +4468,7 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
unsigned long cr0, cr3, cr4;
cr0 = read_cr0();
- WARN_ON(cr0 & X86_CR0_TS);
+ WARN_ON_ONCE(cr0 & X86_CR0_TS);
vmcs_writel(HOST_CR0, cr0); /* 22.2.3 */
/*
@@ -5537,7 +5537,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
* STI and MOVSS blocking.
*/
if (is_icebp(intr_info))
- WARN_ON(!skip_emulated_instruction(vcpu));
+ WARN_ON_ONCE(!skip_emulated_instruction(vcpu));
kvm_queue_exception_p(vcpu, DB_VECTOR, dr6);
return 1;
@@ -5962,7 +5962,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
if (!idt_v || (type != INTR_TYPE_HARD_EXCEPTION &&
type != INTR_TYPE_EXT_INTR &&
type != INTR_TYPE_NMI_INTR))
- WARN_ON(!skip_emulated_instruction(vcpu));
+ WARN_ON_ONCE(!skip_emulated_instruction(vcpu));
/*
* TODO: What about debug traps on tss switch?
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 32563a91fba9..a9be847d3cc2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -370,7 +370,7 @@ static int exception_type(int vector)
{
unsigned int mask;
- if (WARN_ON(vector > 31 || vector == NMI_VECTOR))
+ if (WARN_ON_ONCE(vector > 31 || vector == NMI_VECTOR))
return EXCPT_INTERRUPT;
mask = 1 << vector;
@@ -4907,7 +4907,7 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
return X86EMUL_PROPAGATE_FAULT;
offset = addr & (PAGE_SIZE-1);
- if (WARN_ON(offset + bytes > PAGE_SIZE))
+ if (WARN_ON_ONCE(offset + bytes > PAGE_SIZE))
bytes = (unsigned)PAGE_SIZE - offset;
ret = kvm_vcpu_read_guest_page(vcpu, gpa >> PAGE_SHIFT, val,
offset, bytes);
@@ -5167,7 +5167,7 @@ static int emulator_read_write_onepage(unsigned long addr, void *val,
bytes -= handled;
val += handled;
- WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
+ WARN_ON_ONCE(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
frag->gpa = gpa;
if (write && bytes <= 8u) {
@@ -7042,7 +7042,7 @@ static int kvm_x86_check_processor_compatibility(void)
* compatible, i.e. KVM should never perform a compatibility check on
* an offline CPU.
*/
- WARN_ON(!cpu_online(cpu));
+ WARN_ON_ONCE(!cpu_online(cpu));
if (__cr4_reserved_bits(cpu_has, c) !=
__cr4_reserved_bits(cpu_has, &boot_cpu_data))
@@ -7783,7 +7783,7 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
vcpu->arch.nmi_injected = true;
kvm_x86_call(inject_nmi)(vcpu);
can_inject = false;
- WARN_ON(kvm_x86_call(nmi_allowed)(vcpu, true) < 0);
+ WARN_ON_ONCE(kvm_x86_call(nmi_allowed)(vcpu, true) < 0);
}
if (vcpu->arch.nmi_pending)
kvm_x86_call(enable_nmi_window)(vcpu);
@@ -7800,7 +7800,7 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
if (likely(irq != -1)) {
kvm_queue_interrupt(vcpu, irq, false);
kvm_x86_call(inject_irq)(vcpu, false);
- WARN_ON(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);
+ WARN_ON_ONCE(kvm_x86_call(interrupt_allowed)(vcpu, true) < 0);
} else {
kvm_warn_on_lost_irq(vcpu);
}
@@ -8470,8 +8470,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
* KVM_DEBUGREG_WONT_EXIT again.
*/
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
- WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
- WARN_ON(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH);
+ WARN_ON_ONCE(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
+ WARN_ON_ONCE(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH);
kvm_x86_call(sync_dirty_debug_regs)(vcpu);
kvm_update_dr0123(vcpu);
vcpu->arch.dr6 |= kvm_get_dr6_fixed_1(vcpu);
@@ -10038,7 +10038,7 @@ void __user * __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa,
lockdep_assert_held(&kvm->slots_lock);
- if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
+ if (WARN_ON_ONCE(id >= KVM_MEM_SLOTS_NUM))
return ERR_PTR_USR(-EINVAL);
slot = id_to_memslot(slots, id);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index cfe96962a4e4..99ba31aa5ef5 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -348,7 +348,7 @@ static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
{
if (vcpu->arch.l1_tsc_scaling_ratio != kvm_caps.default_tsc_scaling_ratio)
- WARN_ON(adjustment < 0);
+ WARN_ON_ONCE(adjustment < 0);
adjustment = kvm_scale_tsc((u64) adjustment,
vcpu->arch.l1_tsc_scaling_ratio);
adjust_tsc_offset_guest(vcpu, adjustment);
--
2.56.0.257.gf7497c7d27-goog
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
2026-10-22 21:55 [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Sean Christopherson
2026-10-22 21:55 ` [PATCH 1/2] KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion Sean Christopherson
2026-10-22 21:55 ` [PATCH 2/2] KVM: x86: Convert all runtime WARNs to ONCE variants Sean Christopherson
@ 2026-10-23 14:59 ` Yosry Ahmed
2026-10-26 17:35 ` Sean Christopherson
2 siblings, 1 reply; 8+ messages in thread
From: Yosry Ahmed @ 2026-10-23 14:59 UTC (permalink / raw)
To: Sean Christopherson
Cc: Vitaly Kuznetsov, Paolo Bonzini, kvm, linux-kernel, Stefan Teodorescu
On Thu, Oct 22, 2026 at 2:55 PM Sean Christopherson <seanjc@google.com> wrote:
>
> Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
> strictly scoped to module init/exit, or similar, to ONCE() variants for what
> should be fairly obvious reasons at this point.
Do you wanna CC stable?
>
> Sean Christopherson (2):
> KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion
> KVM: x86: Convert all runtime WARNs to ONCE variants
>
> arch/x86/kvm/hyperv.c | 2 +-
> arch/x86/kvm/i8254.c | 2 +-
> arch/x86/kvm/irq.c | 4 ++--
> arch/x86/kvm/lapic.c | 17 ++++++++++-------
> arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
> arch/x86/kvm/msrs.c | 2 +-
> arch/x86/kvm/svm/avic.c | 2 +-
> arch/x86/kvm/svm/nested.c | 12 ++++++------
> arch/x86/kvm/svm/sev.c | 2 +-
> arch/x86/kvm/svm/svm.c | 12 ++++++------
> arch/x86/kvm/vmx/nested.c | 12 ++++++------
> arch/x86/kvm/vmx/posted_intr.c | 2 +-
> arch/x86/kvm/vmx/vmx.c | 8 ++++----
> arch/x86/kvm/x86.c | 18 +++++++++---------
> arch/x86/kvm/x86.h | 2 +-
> 15 files changed, 51 insertions(+), 48 deletions(-)
>
>
> base-commit: 814607cd40df80d5727957adaa857e0feca43497
> --
> 2.56.0.257.gf7497c7d27-goog
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
2026-10-23 14:59 ` [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Yosry Ahmed
@ 2026-10-26 17:35 ` Sean Christopherson
2026-10-26 18:04 ` Yosry Ahmed
0 siblings, 1 reply; 8+ messages in thread
From: Sean Christopherson @ 2026-10-26 17:35 UTC (permalink / raw)
To: Yosry Ahmed
Cc: Vitaly Kuznetsov, Paolo Bonzini, kvm, linux-kernel, Stefan Teodorescu
On Fri, Oct 23, 2026, Yosry Ahmed wrote:
> On Thu, Oct 22, 2026 at 2:55 PM Sean Christopherson <seanjc@google.com> wrote:
> >
> > Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
> > strictly scoped to module init/exit, or similar, to ONCE() variants for what
> > should be fairly obvious reasons at this point.
>
> Do you wanna CC stable?
Not really? Maybe? I worry that this will generate an absurd number of conflicts
and also have "misses" in older kernels, to the point where it oculd do more harm
than good.
I could be convinced this should be tagged for stable@, though honestly it might
be better to omit the automatic backport trigger and just rely on someone to
"manually" provide equivalent patches.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
2026-10-26 17:35 ` Sean Christopherson
@ 2026-10-26 18:04 ` Yosry Ahmed
2026-10-26 18:38 ` Vitaly Kuznetsov
0 siblings, 1 reply; 8+ messages in thread
From: Yosry Ahmed @ 2026-10-26 18:04 UTC (permalink / raw)
To: Sean Christopherson
Cc: Vitaly Kuznetsov, Paolo Bonzini, kvm, linux-kernel, Stefan Teodorescu
On Mon, Oct 26, 2026 at 10:36 AM Sean Christopherson <seanjc@google.com> wrote:
>
> On Fri, Oct 23, 2026, Yosry Ahmed wrote:
> > On Thu, Oct 22, 2026 at 2:55 PM Sean Christopherson <seanjc@google.com> wrote:
> > >
> > > Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
> > > strictly scoped to module init/exit, or similar, to ONCE() variants for what
> > > should be fairly obvious reasons at this point.
> >
> > Do you wanna CC stable?
>
> Not really? Maybe? I worry that this will generate an absurd number of conflicts
> and also have "misses" in older kernels, to the point where it oculd do more harm
> than good.
>
> I could be convinced this should be tagged for stable@, though honestly it might
> be better to omit the automatic backport trigger and just rely on someone to
> "manually" provide equivalent patches.
I can just see this ultimately preventing a DoS and if it lands on any
stable kernel it should be a win, but yeah probably manual backports
are needed :/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
2026-10-26 18:04 ` Yosry Ahmed
@ 2026-10-26 18:38 ` Vitaly Kuznetsov
2026-10-26 18:59 ` Sean Christopherson
0 siblings, 1 reply; 8+ messages in thread
From: Vitaly Kuznetsov @ 2026-10-26 18:38 UTC (permalink / raw)
To: Yosry Ahmed, Sean Christopherson
Cc: Paolo Bonzini, kvm, linux-kernel, Stefan Teodorescu
Yosry Ahmed <yosry@kernel.org> writes:
> On Mon, Oct 26, 2026 at 10:36 AM Sean Christopherson <seanjc@google.com> wrote:
>>
>> On Fri, Oct 23, 2026, Yosry Ahmed wrote:
>> > On Thu, Oct 22, 2026 at 2:55 PM Sean Christopherson <seanjc@google.com> wrote:
>> > >
>> > > Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
>> > > strictly scoped to module init/exit, or similar, to ONCE() variants for what
>> > > should be fairly obvious reasons at this point.
>> >
>> > Do you wanna CC stable?
>>
>> Not really? Maybe? I worry that this will generate an absurd number of conflicts
>> and also have "misses" in older kernels, to the point where it oculd do more harm
>> than good.
>>
>> I could be convinced this should be tagged for stable@, though honestly it might
>> be better to omit the automatic backport trigger and just rely on someone to
>> "manually" provide equivalent patches.
>
> I can just see this ultimately preventing a DoS and if it lands on any
> stable kernel it should be a win, but yeah probably manual backports
> are needed :/
With my backporter's hat on, it would help significantly if we split the
patch per-area (hyperv, [l]apic, posted_intr, vmx, svm,...). It would
also help those who want to analyze whether the particular WARN_ON() is
actually guest triggerable and open the corresponding CVEs.
--
Vitaly
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE
2026-10-26 18:38 ` Vitaly Kuznetsov
@ 2026-10-26 18:59 ` Sean Christopherson
0 siblings, 0 replies; 8+ messages in thread
From: Sean Christopherson @ 2026-10-26 18:59 UTC (permalink / raw)
To: Vitaly Kuznetsov
Cc: Yosry Ahmed, Paolo Bonzini, kvm, linux-kernel, Stefan Teodorescu
On Mon, Oct 26, 2026, Vitaly Kuznetsov wrote:
> Yosry Ahmed <yosry@kernel.org> writes:
>
> > On Mon, Oct 26, 2026 at 10:36 AM Sean Christopherson <seanjc@google.com> wrote:
> >>
> >> On Fri, Oct 23, 2026, Yosry Ahmed wrote:
> >> > On Thu, Oct 22, 2026 at 2:55 PM Sean Christopherson <seanjc@google.com> wrote:
> >> > >
> >> > > Convert all bare WARN() and WARN_ON() runtime usage, i.e. WARNs that aren't
> >> > > strictly scoped to module init/exit, or similar, to ONCE() variants for what
> >> > > should be fairly obvious reasons at this point.
> >> >
> >> > Do you wanna CC stable?
> >>
> >> Not really? Maybe? I worry that this will generate an absurd number of conflicts
> >> and also have "misses" in older kernels, to the point where it oculd do more harm
> >> than good.
> >>
> >> I could be convinced this should be tagged for stable@, though honestly it might
> >> be better to omit the automatic backport trigger and just rely on someone to
> >> "manually" provide equivalent patches.
> >
> > I can just see this ultimately preventing a DoS and if it lands on any
> > stable kernel it should be a win, but yeah probably manual backports
> > are needed :/
>
> With my backporter's hat on, it would help significantly if we split the
> patch per-area (hyperv, [l]apic, posted_intr, vmx, svm,...). It would
> also help those who want to analyze whether the particular WARN_ON() is
> actually guest triggerable and open the corresponding CVEs.
Honestly, I don't think that's actually going to help. Exactly which WARNs are
problematic will vary by kernel, a lot. I.e. the set of WARNs that are spammable
*now* is not the same set that was spammable in 6.18, 6.12, 6.6, 6.1, etc. Then
factor in different configurations and threat models, and the set of problematic
WARNs gets quite large.
So from an upstream perspective, I think we should assume everything the worst
and "fix" everything, and then do the same for LTS kernels. I.e. backport the
concept of "never do multi-WARNs at runtime", not necessarily the literal patch.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-26 18:59 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-22 21:55 [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Sean Christopherson
2026-10-22 21:55 ` [PATCH 1/2] KVM: x86: Convert WARN_ON(preemptible()) to lockdep assertion Sean Christopherson
2026-10-22 21:55 ` [PATCH 2/2] KVM: x86: Convert all runtime WARNs to ONCE variants Sean Christopherson
2026-10-23 14:59 ` [PATCH 0/2] KVM: x86: Convert all runtime WARNs to ONCE Yosry Ahmed
2026-10-26 17:35 ` Sean Christopherson
2026-10-26 18:04 ` Yosry Ahmed
2026-10-26 18:38 ` Vitaly Kuznetsov
2026-10-26 18:59 ` Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®