diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-08-18 08:57:29 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-09-06 12:30:25 -0400 |
commit | 9a20ea4b4c34764416e935090d6e5ede02d1bada (patch) | |
tree | 913ee443b564815b42c683592c599d431b01c201 | |
parent | e8483b578b229774382a95891439b2ebd9c92fc5 (diff) |
x86/kvm: Convert to hotplug state machine
Install the callbacks via the state machine. The online & down callbacks are
invoked on the target CPU so we can avoid using smp_call_function_single().
local_irq_disable() is used because smp_call_function_single() used to invoke
the function with interrupts disabled.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Gleb Natapov <gleb@kernel.org>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160818125731.27256-15-bigeasy@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/kernel/kvm.c | 43 |
1 files changed, 16 insertions, 27 deletions
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 1726c4c12336..1f431f362dd5 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
@@ -423,12 +423,7 @@ static void __init kvm_smp_prepare_boot_cpu(void) | |||
423 | kvm_spinlock_init(); | 423 | kvm_spinlock_init(); |
424 | } | 424 | } |
425 | 425 | ||
426 | static void kvm_guest_cpu_online(void *dummy) | 426 | static void kvm_guest_cpu_offline(void) |
427 | { | ||
428 | kvm_guest_cpu_init(); | ||
429 | } | ||
430 | |||
431 | static void kvm_guest_cpu_offline(void *dummy) | ||
432 | { | 427 | { |
433 | kvm_disable_steal_time(); | 428 | kvm_disable_steal_time(); |
434 | if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) | 429 | if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) |
@@ -437,29 +432,21 @@ static void kvm_guest_cpu_offline(void *dummy) | |||
437 | apf_task_wake_all(); | 432 | apf_task_wake_all(); |
438 | } | 433 | } |
439 | 434 | ||
440 | static int kvm_cpu_notify(struct notifier_block *self, unsigned long action, | 435 | static int kvm_cpu_online(unsigned int cpu) |
441 | void *hcpu) | ||
442 | { | 436 | { |
443 | int cpu = (unsigned long)hcpu; | 437 | local_irq_disable(); |
444 | switch (action) { | 438 | kvm_guest_cpu_init(); |
445 | case CPU_ONLINE: | 439 | local_irq_enable(); |
446 | case CPU_DOWN_FAILED: | 440 | return 0; |
447 | case CPU_ONLINE_FROZEN: | ||
448 | smp_call_function_single(cpu, kvm_guest_cpu_online, NULL, 0); | ||
449 | break; | ||
450 | case CPU_DOWN_PREPARE: | ||
451 | case CPU_DOWN_PREPARE_FROZEN: | ||
452 | smp_call_function_single(cpu, kvm_guest_cpu_offline, NULL, 1); | ||
453 | break; | ||
454 | default: | ||
455 | break; | ||
456 | } | ||
457 | return NOTIFY_OK; | ||
458 | } | 441 | } |
459 | 442 | ||
460 | static struct notifier_block kvm_cpu_notifier = { | 443 | static int kvm_cpu_down_prepare(unsigned int cpu) |
461 | .notifier_call = kvm_cpu_notify, | 444 | { |
462 | }; | 445 | local_irq_disable(); |
446 | kvm_guest_cpu_offline(); | ||
447 | local_irq_enable(); | ||
448 | return 0; | ||
449 | } | ||
463 | #endif | 450 | #endif |
464 | 451 | ||
465 | static void __init kvm_apf_trap_init(void) | 452 | static void __init kvm_apf_trap_init(void) |
@@ -494,7 +481,9 @@ void __init kvm_guest_init(void) | |||
494 | 481 | ||
495 | #ifdef CONFIG_SMP | 482 | #ifdef CONFIG_SMP |
496 | smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; | 483 | smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; |
497 | register_cpu_notifier(&kvm_cpu_notifier); | 484 | if (cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/kvm:online", |
485 | kvm_cpu_online, kvm_cpu_down_prepare) < 0) | ||
486 | pr_err("kvm_guest: Failed to install cpu hotplug callbacks\n"); | ||
498 | #else | 487 | #else |
499 | kvm_guest_cpu_init(); | 488 | kvm_guest_cpu_init(); |
500 | #endif | 489 | #endif |