On Fri, 2012-09-21 at 15:35 +1000, Paul Mackerras wrote: > 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 <pau...@samba.org>
Acked-by: Benjamin Herrenschmidt <b...@kernel.crashing.org> > --- > arch/powerpc/include/asm/smp.h | 8 +++++++ > arch/powerpc/kernel/smp.c | 46 > ++++++++++++++++++++++++++++++++++++++++ > arch/powerpc/kvm/book3s_hv.c | 12 +++++++++-- > 3 files changed, 64 insertions(+), 2 deletions(-) > > diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h > index ebc24dc..b625a1a 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); > void generic_mach_cpu_die(void); > void generic_set_cpu_dead(unsigned int cpu); > int generic_check_cpu_restart(unsigned int cpu); > + > +extern void inhibit_secondary_onlining(void); > +extern void uninhibit_secondary_onlining(void); > + > +#else /* HOTPLUG_CPU */ > +static inline void inhibit_secondary_onlining(void) {} > +static inline void uninhibit_secondary_onlining(void) {} > + > #endif > > #ifdef CONFIG_PPC64 > diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c > index 0321007..c45f51d 100644 > --- a/arch/powerpc/kernel/smp.c > +++ b/arch/powerpc/kernel/smp.c > @@ -410,6 +410,45 @@ int generic_check_cpu_restart(unsigned int cpu) > { > return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE; > } > + > +static atomic_t secondary_inhibit_count; > + > +/* > + * Don't allow secondary CPU threads to come online > + */ > +void inhibit_secondary_onlining(void) > +{ > + /* > + * This makes secondary_inhibit_count stable during cpu > + * online/offline operations. > + */ > + get_online_cpus(); > + > + atomic_inc(&secondary_inhibit_count); > + put_online_cpus(); > +} > +EXPORT_SYMBOL_GPL(inhibit_secondary_onlining); > + > +/* > + * Allow secondary CPU threads to come online again > + */ > +void uninhibit_secondary_onlining(void) > +{ > + get_online_cpus(); > + atomic_dec(&secondary_inhibit_count); > + put_online_cpus(); > +} > +EXPORT_SYMBOL_GPL(uninhibit_secondary_onlining); > + > +static int secondaries_inhibited(void) > +{ > + return atomic_read(&secondary_inhibit_count); > +} > + > +#else /* HOTPLUG_CPU */ > + > +#define secondaries_inhibited() 0 > + > #endif > > static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle) > @@ -428,6 +467,13 @@ int __cpuinit __cpu_up(unsigned int cpu, struct > task_struct *tidle) > { > int rc, c; > > + /* > + * Don't allow secondary threads to come online if inhibited > + */ > + if (threads_per_core > 1 && secondaries_inhibited() && > + cpu % threads_per_core != 0) > + return -EBUSY; > + > if (smp_ops == NULL || > (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))) > return -EINVAL; > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index bebf9cb..6fe1410 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -47,6 +47,7 @@ > #include <asm/page.h> > #include <asm/hvcall.h> > #include <asm/switch_to.h> > +#include <asm/smp.h> > #include <linux/gfp.h> > #include <linux/vmalloc.h> > #include <linux/highmem.h> > @@ -918,8 +919,6 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc) > /* > * Make sure we are running on thread 0, and that > * secondary threads are offline. > - * XXX we should also block attempts to bring any > - * secondary threads online. > */ > if (threads_per_core > 1 && !on_primary_thread()) { > list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) > @@ -1632,11 +1631,20 @@ int kvmppc_core_init_vm(struct kvm *kvm) > > kvm->arch.using_mmu_notifiers = !!cpu_has_feature(CPU_FTR_ARCH_206); > spin_lock_init(&kvm->arch.slot_phys_lock); > + > + /* > + * Don't allow secondary CPU threads to come online > + * while any KVM VMs exist. > + */ > + inhibit_secondary_onlining(); > + > return 0; > } > > void kvmppc_core_destroy_vm(struct kvm *kvm) > { > + uninhibit_secondary_onlining(); > + > if (kvm->arch.rma) { > kvm_release_rma(kvm->arch.rma); > kvm->arch.rma = NULL; -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html