aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-10-14 21:15:41 -0400
committerAlexander Graf <agraf@suse.de>2012-10-30 05:54:53 -0400
commit512691d4907d7cf4b8d05c6f8572d1fa60ccec20 (patch)
tree8cb0fb7f8cdc1b0283ef7cba585775f47b974ebc /arch/powerpc
parentc99ec973a63e2249020d6d93a46d7572432da6a2 (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')
-rw-r--r--arch/powerpc/include/asm/smp.h8
-rw-r--r--arch/powerpc/kernel/smp.c46
-rw-r--r--arch/powerpc/kvm/book3s_hv.c12
3 files changed, 64 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index ebc24dc5b1a1..b625a1a9ad16 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -66,6 +66,14 @@ void generic_cpu_die(unsigned int cpu);
66void generic_mach_cpu_die(void); 66void generic_mach_cpu_die(void);
67void generic_set_cpu_dead(unsigned int cpu); 67void generic_set_cpu_dead(unsigned int cpu);
68int generic_check_cpu_restart(unsigned int cpu); 68int generic_check_cpu_restart(unsigned int cpu);
69
70extern void inhibit_secondary_onlining(void);
71extern void uninhibit_secondary_onlining(void);
72
73#else /* HOTPLUG_CPU */
74static inline void inhibit_secondary_onlining(void) {}
75static inline void uninhibit_secondary_onlining(void) {}
76
69#endif 77#endif
70 78
71#ifdef CONFIG_PPC64 79#ifdef CONFIG_PPC64
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
421static atomic_t secondary_inhibit_count;
422
423/*
424 * Don't allow secondary CPU threads to come online
425 */
426void 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}
437EXPORT_SYMBOL_GPL(inhibit_secondary_onlining);
438
439/*
440 * Allow secondary CPU threads to come online again
441 */
442void uninhibit_secondary_onlining(void)
443{
444 get_online_cpus();
445 atomic_dec(&secondary_inhibit_count);
446 put_online_cpus();
447}
448EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining);
449
450static 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
422static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) 461static 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;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 9a15da76e56b..c5ddf048e19e 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -47,6 +47,7 @@
47#include <asm/page.h> 47#include <asm/page.h>
48#include <asm/hvcall.h> 48#include <asm/hvcall.h>
49#include <asm/switch_to.h> 49#include <asm/switch_to.h>
50#include <asm/smp.h>
50#include <linux/gfp.h> 51#include <linux/gfp.h>
51#include <linux/vmalloc.h> 52#include <linux/vmalloc.h>
52#include <linux/highmem.h> 53#include <linux/highmem.h>
@@ -1016,8 +1017,6 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
1016 /* 1017 /*
1017 * Make sure we are running on thread 0, and that 1018 * Make sure we are running on thread 0, and that
1018 * secondary threads are offline. 1019 * secondary threads are offline.
1019 * XXX we should also block attempts to bring any
1020 * secondary threads online.
1021 */ 1020 */
1022 if (threads_per_core > 1 && !on_primary_thread()) { 1021 if (threads_per_core > 1 && !on_primary_thread()) {
1023 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) 1022 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
@@ -1730,11 +1729,20 @@ int kvmppc_core_init_vm(struct kvm *kvm)
1730 1729
1731 kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206); 1730 kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206);
1732 spin_lock_init(&kvm->arch.slot_phys_lock); 1731 spin_lock_init(&kvm->arch.slot_phys_lock);
1732
1733 /*
1734 * Don't allow secondary CPU threads to come online
1735 * while any KVM VMs exist.
1736 */
1737 inhibit_secondary_onlining();
1738
1733 return 0; 1739 return 0;
1734} 1740}
1735 1741
1736void kvmppc_core_destroy_vm(struct kvm *kvm) 1742void kvmppc_core_destroy_vm(struct kvm *kvm)
1737{ 1743{
1744 uninhibit_secondary_onlining();
1745
1738 if (kvm->arch.rma) { 1746 if (kvm->arch.rma) {
1739 kvm_release_rma(kvm->arch.rma); 1747 kvm_release_rma(kvm->arch.rma);
1740 kvm->arch.rma = NULL; 1748 kvm->arch.rma = NULL;