diff options
author | Paul Mackerras <paulus@samba.org> | 2012-10-14 21:15:41 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-10-30 05:54:53 -0400 |
commit | 512691d4907d7cf4b8d05c6f8572d1fa60ccec20 (patch) | |
tree | 8cb0fb7f8cdc1b0283ef7cba585775f47b974ebc /arch/powerpc/kernel | |
parent | c99ec973a63e2249020d6d93a46d7572432da6a2 (diff) |
KVM: PPC: Book3S HV: Allow KVM guests to stop secondary threads coming online
When a Book3S HV KVM guest is running, we need the host to be in
single-thread mode, that is, all of the cores (or at least all of
the cores where the KVM guest could run) to be running only one
active hardware thread. This is because of the hardware restriction
in POWER processors that all of the hardware threads in the core
must be in the same logical partition. Complying with this restriction
is much easier if, from the host kernel's point of view, only one
hardware thread is active.
This adds two hooks in the SMP hotplug code to allow the KVM code to
make sure that secondary threads (i.e. hardware threads other than
thread 0) cannot come online while any KVM guest exists. The KVM
code still has to check that any core where it runs a guest has the
secondary threads offline, but having done that check it can now be
sure that they will not come online while the guest is running.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/smp.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8d4214afc21d..c4f420c5fc1b 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -417,6 +417,45 @@ int generic_check_cpu_restart(unsigned int cpu) | |||
417 | { | 417 | { |
418 | return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; | 418 | return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; |
419 | } | 419 | } |
420 | |||
421 | static atomic_t secondary_inhibit_count; | ||
422 | |||
423 | /* | ||
424 | * Don't allow secondary CPU threads to come online | ||
425 | */ | ||
426 | void inhibit_secondary_onlining(void) | ||
427 | { | ||
428 | /* | ||
429 | * This makes secondary_inhibit_count stable during cpu | ||
430 | * online/offline operations. | ||
431 | */ | ||
432 | get_online_cpus(); | ||
433 | |||
434 | atomic_inc(&secondary_inhibit_count); | ||
435 | put_online_cpus(); | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(inhibit_secondary_onlining); | ||
438 | |||
439 | /* | ||
440 | * Allow secondary CPU threads to come online again | ||
441 | */ | ||
442 | void uninhibit_secondary_onlining(void) | ||
443 | { | ||
444 | get_online_cpus(); | ||
445 | atomic_dec(&secondary_inhibit_count); | ||
446 | put_online_cpus(); | ||
447 | } | ||
448 | EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining); | ||
449 | |||
450 | static int secondaries_inhibited(void) | ||
451 | { | ||
452 | return atomic_read(&secondary_inhibit_count); | ||
453 | } | ||
454 | |||
455 | #else /* HOTPLUG_CPU */ | ||
456 | |||
457 | #define secondaries_inhibited() 0 | ||
458 | |||
420 | #endif | 459 | #endif |
421 | 460 | ||
422 | static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) | 461 | static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) |
@@ -435,6 +474,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) | |||
435 | { | 474 | { |
436 | int rc, c; | 475 | int rc, c; |
437 | 476 | ||
477 | /* | ||
478 | * Don't allow secondary threads to come online if inhibited | ||
479 | */ | ||
480 | if (threads_per_core > 1 && secondaries_inhibited() && | ||
481 | cpu % threads_per_core != 0) | ||
482 | return -EBUSY; | ||
483 | |||
438 | if (smp_ops == NULL || | 484 | if (smp_ops == NULL || |
439 | (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) | 485 | (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) |
440 | return -EINVAL; | 486 | return -EINVAL; |