aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-07-03 12:53:58 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-07-03 12:55:00 -0400
commit2ecd9d29abb171d6e97a4f3eb29d7456a11401b7 (patch)
tree2c31785e4dff264db31ee0dea5f74c5d29905898 /virt
parent9bdc771f2c29a11920f477fba05a58e23ee42554 (diff)
sched, preempt_notifier: separate notifier registration from static_key inc/dec
Commit 1cde2930e154 ("sched/preempt: Add static_key() to preempt_notifiers") had two problems. First, the preempt-notifier API needs to sleep with the addition of the static_key, we do however need to hold off preemption while modifying the preempt notifier list, otherwise a preemption could observe an inconsistent list state. KVM correctly registers and unregisters preempt notifiers with preemption disabled, so the sleep caused dmesg splats. Second, KVM registers and unregisters preemption notifiers very often (in vcpu_load/vcpu_put). With a single uniprocessor guest the static key would move between 0 and 1 continuously, hitting the slow path on every userspace exit. To fix this, wrap the static_key inc/dec in a new API, and call it from KVM. Fixes: 1cde2930e154 ("sched/preempt: Add static_key() to preempt_notifiers") Reported-by: Pontus Fuchs <pontus.fuchs@gmail.com> Reported-by: Takashi Iwai <tiwai@suse.de> Tested-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 848af90b8091..8b8a44453670 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -553,6 +553,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
553 list_add(&kvm->vm_list, &vm_list); 553 list_add(&kvm->vm_list, &vm_list);
554 spin_unlock(&kvm_lock); 554 spin_unlock(&kvm_lock);
555 555
556 preempt_notifier_inc();
557
556 return kvm; 558 return kvm;
557 559
558out_err: 560out_err:
@@ -620,6 +622,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
620 cleanup_srcu_struct(&kvm->irq_srcu); 622 cleanup_srcu_struct(&kvm->irq_srcu);
621 cleanup_srcu_struct(&kvm->srcu); 623 cleanup_srcu_struct(&kvm->srcu);
622 kvm_arch_free_vm(kvm); 624 kvm_arch_free_vm(kvm);
625 preempt_notifier_dec();
623 hardware_disable_all(); 626 hardware_disable_all();
624 mmdrop(mm); 627 mmdrop(mm);
625} 628}