Re: [PATCH kvm-unit-tests 3/6] lib/arm/smp: introduce smp_run

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, May 25, 2017 at 05:07:25PM +0200, Paolo Bonzini wrote:
> 
> 
> On 25/05/2017 16:41, Andrew Jones wrote:
> > On Thu, May 25, 2017 at 03:56:00PM +0200, Paolo Bonzini wrote:
> >>
> >>
> >> On 25/05/2017 12:28, Andrew Jones wrote:
> >>> 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.
> >>
> >> Would it make sense to just call main() this way?
> > 
> > Do you mean to start main() on all cpus all the time and then
> > leave it to the test writer to ensure things that should only
> > be done by the primary are guarded with 'if (cpu == 0)' ? If
> > so, then I think we might over complicate simple tests. I
> > suppose some tests could do something like
> 
> Start main on cpu 0 and put other CPUs in a WFI loop where they can take
> IPIs.  This is similar to how x86 works, and homogeneity would be useful
> I think.

Thinking about this some more, I don't think we need to call main
from smp_run() to be like x86, but rather we just need the two main
API calls on_cpu() and on_cpu_async(). x86 doesn't have something like
smp_run() yet (which would be on_cpus()) and smp_run() currently has the
limitations that it can only be run once and only when secondaries haven't
already been boot. I think I should change that. I propose the following

1) introduce on_cpu() and on_cpu_async() to arm, using PSCI and sev/wfe
   for the underling mechanisms.
2) change smp_run() to be built on on_cpu() and rename it to on_cpus()

How's that sound?

x86 might want an on_cpus() too. I see potentially 16 places it could
be used

 $ git grep -B1 on_cpu | grep -c for
 16

Thanks,
drew

> 
> Paolo
> 
> >  void main(void)
> >  {
> >      if (smp_processor_id() == 0)
> >          smp_run(main);
> >      do_test1();
> >      do_test2();
> >      if (smp_processor_id() == 0)
> >          return report_summary();
> >  }
> > 
> > but I think that looks worse than
> > 
> >  void do_tests(void)
> >  {
> >      do_test1();
> >      do_test2();
> >  }
> > 
> >  void main(void)
> >  {
> >      smp_run(do_tests);
> >      return report_summary();
> >  }
> > 
> > One thing I did think of later is that cpu0 is allowed to
> > halt without setting its bit in cpu_halted_mask. But that
> > can only happen when chr_testdev_exit() fails (and who
> > would look at it?), so it doesn't really matter. I'd fix
> > it up if we want it for completeness though.
> > 
> > Thanks,
> > drew
> > 
> > 
> >>
> >> Paolo
> >>
> >>> Signed-off-by: Andrew Jones <drjones@xxxxxxxxxx>
> >>> ---
> >>>  arm/cstart.S      |  3 ++-
> >>>  arm/cstart64.S    |  3 ++-
> >>>  lib/arm/asm/smp.h |  2 ++
> >>>  lib/arm/smp.c     | 26 ++++++++++++++++++++++++++
> >>>  4 files changed, 32 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/arm/cstart.S b/arm/cstart.S
> >>> index 12461d104dad..b3176b274933 100644
> >>> --- a/arm/cstart.S
> >>> +++ b/arm/cstart.S
> >>> @@ -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:
> >>> diff --git a/arm/cstart64.S b/arm/cstart64.S
> >>> index 7738babc4109..30f732f1e99b 100644
> >>> --- a/arm/cstart64.S
> >>> +++ b/arm/cstart64.S
> >>> @@ -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:
> >>> diff --git a/lib/arm/asm/smp.h b/lib/arm/asm/smp.h
> >>> index 4cb86b6ce342..1d1cd7a29991 100644
> >>> --- a/lib/arm/asm/smp.h
> >>> +++ b/lib/arm/asm/smp.h
> >>> @@ -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_ */
> >>> diff --git a/lib/arm/smp.c b/lib/arm/smp.c
> >>> index bbaf9e60e950..8528aa454108 100644
> >>> --- a/lib/arm/smp.c
> >>> +++ b/lib/arm/smp.c
> >>> @@ -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);
> >>> +}
> >>>



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux