Skip to content

Commit f67ce83

Browse files
sean-jcjfvogel
authored andcommitted
KVM: x86/mmu: Ensure NX huge page recovery thread is alive before waking
commit 43fb96a upstream. When waking a VM's NX huge page recovery thread, ensure the thread is actually alive before trying to wake it. Now that the thread is spawned on-demand during KVM_RUN, a VM without a recovery thread is reachable via the related module params. BUG: kernel NULL pointer dereference, address: 0000000000000040 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 RIP: 0010:vhost_task_wake+0x5/0x10 Call Trace: <TASK> set_nx_huge_pages+0xcc/0x1e0 [kvm] param_attr_store+0x8a/0xd0 module_attr_store+0x1a/0x30 kernfs_fop_write_iter+0x12f/0x1e0 vfs_write+0x233/0x3e0 ksys_write+0x60/0xd0 do_syscall_64+0x5b/0x160 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x7f3b52710104 </TASK> Modules linked in: kvm_intel kvm CR2: 0000000000000040 Fixes: 931656b ("kvm: defer huge page recovery vhost task to later") Cc: [email protected] Cc: Keith Busch <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit 2b3928b7c896e5a9fb6b1373924adafe8e01a0c6) Signed-off-by: Jack Vogel <[email protected]>
1 parent a95ae3c commit f67ce83

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

arch/x86/kvm/mmu/mmu.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7229,6 +7229,19 @@ static void mmu_destroy_caches(void)
72297229
kmem_cache_destroy(mmu_page_header_cache);
72307230
}
72317231

7232+
static void kvm_wake_nx_recovery_thread(struct kvm *kvm)
7233+
{
7234+
/*
7235+
* The NX recovery thread is spawned on-demand at the first KVM_RUN and
7236+
* may not be valid even though the VM is globally visible. Do nothing,
7237+
* as such a VM can't have any possible NX huge pages.
7238+
*/
7239+
struct vhost_task *nx_thread = READ_ONCE(kvm->arch.nx_huge_page_recovery_thread);
7240+
7241+
if (nx_thread)
7242+
vhost_task_wake(nx_thread);
7243+
}
7244+
72327245
static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp)
72337246
{
72347247
if (nx_hugepage_mitigation_hard_disabled)
@@ -7289,7 +7302,7 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp)
72897302
kvm_mmu_zap_all_fast(kvm);
72907303
mutex_unlock(&kvm->slots_lock);
72917304

7292-
vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread);
7305+
kvm_wake_nx_recovery_thread(kvm);
72937306
}
72947307
mutex_unlock(&kvm_lock);
72957308
}
@@ -7435,7 +7448,7 @@ static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel
74357448
mutex_lock(&kvm_lock);
74367449

74377450
list_for_each_entry(kvm, &vm_list, vm_list)
7438-
vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread);
7451+
kvm_wake_nx_recovery_thread(kvm);
74397452

74407453
mutex_unlock(&kvm_lock);
74417454
}
@@ -7571,14 +7584,20 @@ static void kvm_mmu_start_lpage_recovery(struct once *once)
75717584
{
75727585
struct kvm_arch *ka = container_of(once, struct kvm_arch, nx_once);
75737586
struct kvm *kvm = container_of(ka, struct kvm, arch);
7587+
struct vhost_task *nx_thread;
75747588

75757589
kvm->arch.nx_huge_page_last = get_jiffies_64();
7576-
kvm->arch.nx_huge_page_recovery_thread = vhost_task_create(
7577-
kvm_nx_huge_page_recovery_worker, kvm_nx_huge_page_recovery_worker_kill,
7578-
kvm, "kvm-nx-lpage-recovery");
7590+
nx_thread = vhost_task_create(kvm_nx_huge_page_recovery_worker,
7591+
kvm_nx_huge_page_recovery_worker_kill,
7592+
kvm, "kvm-nx-lpage-recovery");
75797593

7580-
if (kvm->arch.nx_huge_page_recovery_thread)
7581-
vhost_task_start(kvm->arch.nx_huge_page_recovery_thread);
7594+
if (!nx_thread)
7595+
return;
7596+
7597+
vhost_task_start(nx_thread);
7598+
7599+
/* Make the task visible only once it is fully started. */
7600+
WRITE_ONCE(kvm->arch.nx_huge_page_recovery_thread, nx_thread);
75827601
}
75837602

75847603
int kvm_mmu_post_init_vm(struct kvm *kvm)

0 commit comments

Comments
 (0)