Commit 543ce33c authored by Andrew Jones's avatar Andrew Jones Committed by Paolo Bonzini
Browse files

lib/arm/smp: introduce smp_run



A common pattern is
 - run a function on all cpus
 - signal each cpu's completion with a cpumask
 - halt the secondaries when they're complete
 - have the primary wait on the cpumask for all to complete

smp_run is a wrapper for that pattern. Also, we were allowing
secondaries to go off in the weeds if they returned from their
secondary entry function, which can be difficult to debug. A
nice side-effect of adding this wrapper is we don't do that
anymore, and can even know when a secondary has halted with the
new cpu_halted_mask.

Signed-off-by: Andrew Jones's avatarAndrew Jones <drjones@redhat.com>
Message-Id: <20170525102849.22754-4-drjones@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent c535b2f8
......@@ -118,7 +118,8 @@ secondary_entry:
bl secondary_cinit
/* r0 is now the entry function, run it */
mov pc, r0
blx r0
b secondary_halt
.globl halt
halt:
......
......@@ -79,7 +79,8 @@ secondary_entry:
bl secondary_cinit
/* x0 is now the entry function, run it */
br x0
blr x0
b secondary_halt
.globl halt
halt:
......
......@@ -14,6 +14,7 @@ extern void halt(void);
extern cpumask_t cpu_present_mask;
extern cpumask_t cpu_online_mask;
extern cpumask_t cpu_halted_mask;
#define cpu_present(cpu) cpumask_test_cpu(cpu, &cpu_present_mask)
#define cpu_online(cpu) cpumask_test_cpu(cpu, &cpu_online_mask)
#define for_each_present_cpu(cpu) for_each_cpu(cpu, &cpu_present_mask)
......@@ -45,5 +46,6 @@ struct secondary_data {
extern struct secondary_data secondary_data;
extern void smp_boot_secondary(int cpu, secondary_entry_fn entry);
extern void smp_run(void (*func)(void));
#endif /* _ASMARM_SMP_H_ */
......@@ -15,6 +15,7 @@
cpumask_t cpu_present_mask;
cpumask_t cpu_online_mask;
cpumask_t cpu_halted_mask;
struct secondary_data secondary_data;
secondary_entry_fn secondary_cinit(void)
......@@ -53,3 +54,28 @@ void smp_boot_secondary(int cpu, secondary_entry_fn entry)
while (!cpu_online(cpu))
wfe();
}
void secondary_halt(void)
{
struct thread_info *ti = current_thread_info();
cpumask_set_cpu(ti->cpu, &cpu_halted_mask);
halt();
}
void smp_run(void (*func)(void))
{
int cpu;
for_each_present_cpu(cpu) {
if (cpu == 0)
continue;
smp_boot_secondary(cpu, func);
}
func();
cpumask_set_cpu(0, &cpu_halted_mask);
while (!cpumask_full(&cpu_halted_mask))
cpu_relax();
cpumask_clear_cpu(0, &cpu_halted_mask);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment