aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-04-12 16:07:31 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-04-15 06:20:54 -0400
commit6d11b87d55eb75007a3721c2de5938f5bbf607fb (patch)
treeca27c670a324dcb47a6b0dbdaf9ced60b53db02f
parent9feb42ac88b516e378b9782e82b651ca5bed95c4 (diff)
powerpc/smp: Replace open coded task affinity logic
Init task invokes smp_ops->setup_cpu() from smp_cpus_done(). Init task can run on any online CPU at this point, but the setup_cpu() callback requires to be invoked on the boot CPU. This is achieved by temporarily setting the affinity of the calling user space thread to the requested CPU and reset it to the original affinity afterwards. That's racy vs. CPU hotplug and concurrent affinity settings for that thread resulting in code executing on the wrong CPU and overwriting the new affinity setting. That's actually not a problem in this context as neither CPU hotplug nor affinity settings can happen, but the access to task_struct::cpus_allowed is about to restricted. Replace it with a call to work_on_cpu_safe() which achieves the same result. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Michael Ellerman <mpe@ellerman.id.au> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Sebastian Siewior <bigeasy@linutronix.de> Cc: Lai Jiangshan <jiangshanlai@gmail.com> Cc: Viresh Kumar <viresh.kumar@linaro.org> Cc: Tejun Heo <tj@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: linuxppc-dev@lists.ozlabs.org Cc: "David S. Miller" <davem@davemloft.net> Cc: Len Brown <lenb@kernel.org> Link: http://lkml.kernel.org/r/20170412201042.518053336@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/powerpc/kernel/smp.c26
1 files changed, 11 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 46f89e66a273..d68ed1f004a3 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -787,24 +787,21 @@ static struct sched_domain_topology_level powerpc_topology[] = {
787 { NULL, }, 787 { NULL, },
788}; 788};
789 789
790void __init smp_cpus_done(unsigned int max_cpus) 790static __init long smp_setup_cpu_workfn(void *data __always_unused)
791{ 791{
792 cpumask_var_t old_mask; 792 smp_ops->setup_cpu(boot_cpuid);
793 return 0;
794}
793 795
794 /* We want the setup_cpu() here to be called from CPU 0, but our 796void __init smp_cpus_done(unsigned int max_cpus)
795 * init thread may have been "borrowed" by another CPU in the meantime 797{
796 * se we pin us down to CPU 0 for a short while 798 /*
799 * We want the setup_cpu() here to be called on the boot CPU, but
800 * init might run on any CPU, so make sure it's invoked on the boot
801 * CPU.
797 */ 802 */
798 alloc_cpumask_var(&old_mask, GFP_NOWAIT);
799 cpumask_copy(old_mask, &current->cpus_allowed);
800 set_cpus_allowed_ptr(current, cpumask_of(boot_cpuid));
801
802 if (smp_ops && smp_ops->setup_cpu) 803 if (smp_ops && smp_ops->setup_cpu)
803 smp_ops->setup_cpu(boot_cpuid); 804 work_on_cpu_safe(boot_cpuid, smp_setup_cpu_workfn, NULL);
804
805 set_cpus_allowed_ptr(current, old_mask);
806
807 free_cpumask_var(old_mask);
808 805
809 if (smp_ops && smp_ops->bringup_done) 806 if (smp_ops && smp_ops->bringup_done)
810 smp_ops->bringup_done(); 807 smp_ops->bringup_done();
@@ -812,7 +809,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
812 dump_numa_cpu_topology(); 809 dump_numa_cpu_topology();
813 810
814 set_sched_topology(powerpc_topology); 811 set_sched_topology(powerpc_topology);
815
816} 812}
817 813
818#ifdef CONFIG_HOTPLUG_CPU 814#ifdef CONFIG_HOTPLUG_CPU