diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-15 08:12:47 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-15 08:12:47 -0700 |
| commit | 9aa622dbaab8addcbe6f65f17c7b4d613d270f05 (patch) | |
| tree | c83eec5d42516a43b6160e5f1c35c2053f49cb50 | |
| parent | 6a66840a68683d9361a9b31faf3bd8104428ad29 (diff) | |
| parent | c8f4cfe1cf93bce924e27f2abead7a4c4a487505 (diff) | |
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini:
"Even more x86 fixes:
- Avoid a false positive panic in the #PF handler, if the kernel
triggers a page fault within the asynchronous page fault handler
before the flags are reset.
This can happen for example because of a perf NMI.
- Always reset a vCPU's MMU pointer back to the root MMU when loading
nested guest state fails during RSM or KVM_SET_NESTED_STATE.
Otherwise KVM tries to run a non-nested guest with a nested MMU,
which can result in a NULL pointer dereference attempting to get
the nested MMU's pgd (EPTP or nested CR3)"
* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry
x86/kvm: Don't consume async #PF flags on a kernel #PF in NMI context
| -rw-r--r-- | arch/x86/kernel/kvm.c | 32 | ||||
| -rw-r--r-- | arch/x86/kvm/vmx/nested.c | 4 |
2 files changed, 32 insertions, 4 deletions
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 6b0a5861ccb8..d8dd2cadcbf7 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -265,11 +265,39 @@ noinstr u32 kvm_read_and_reset_apf_flags(void) } EXPORT_SYMBOL_FOR_KVM(kvm_read_and_reset_apf_flags); +static __always_inline bool kvm_apf_reason_pending(void) +{ + return __this_cpu_read(async_pf_enabled) && + __this_cpu_read(apf_reason.flags); +} + noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token) { - u32 flags = kvm_read_and_reset_apf_flags(); irqentry_state_t state; + u32 flags; + + if (!kvm_apf_reason_pending()) + return false; + + /* + * The guest does not enable KVM_ASYNC_PF_SEND_ALWAYS, so the host + * delivers async #PF only to user mode (or as a #PF VM-exit, which KVM + * reads itself). A #PF from kernel mode can still arrive between that + * delivery and the read of the reason flags, inside an NMI that + * interrupted it, for instance perf reading user memory for a call + * chain. Such a fault is not async, so leave the async PF flags + * untouched for the outer handler. Outside NMI context, on the other + * hand, async PF flags on a kernel-mode fault mean the host is broken. + */ + if (!user_mode(regs)) { + if (likely(in_nmi())) + return false; + state = irqentry_enter(regs); + instrumentation_begin(); + panic("Host injected async #PF in kernel mode\n"); + } + flags = kvm_read_and_reset_apf_flags(); if (!flags) return false; @@ -285,8 +313,6 @@ noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token) panic("Host injected async #PF in interrupt disabled region\n"); if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) { - if (unlikely(!(user_mode(regs)))) - panic("Host injected async #PF in kernel mode\n"); /* Page is swapped out by the host. */ kvm_async_pf_task_wait_schedule(token); } else { diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index b25216862740..5165275128fc 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -3770,8 +3770,10 @@ vmentry_fail_vmexit_guest_mode: vmentry_fail_vmexit: vmx_switch_vmcs(vcpu, &vmx->vmcs01); - if (!from_vmentry) + if (!from_vmentry) { + nested_ept_uninit_mmu_context(vcpu); return NVMX_VMENTRY_VMEXIT; + } nested_put_vmcs12_pages(vcpu); |
