aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
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;