[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 06/11] xen: arm: implement arch/platform SMP and CPU initialisation framework
On 09/27/2013 11:20 AM, Ian Campbell wrote: > Includes an implementation for vexpress using the sysflags interface and > support for the ARMv8 "spin-table" method. > > Unused until the next patch, split out to simplify review. > > Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> > Acked-by: Tim Deegan <tim@xxxxxxx> > Acked-by: Julien Grall <julien.grall@xxxxxxxxxx> > --- > xen/arch/arm/arm32/Makefile | 1 + > xen/arch/arm/arm32/head.S | 2 +- > xen/arch/arm/arm32/smpboot.c | 29 ++++++++++++ > xen/arch/arm/arm64/Makefile | 1 + > xen/arch/arm/arm64/head.S | 1 + > xen/arch/arm/arm64/smpboot.c | 89 > +++++++++++++++++++++++++++++++++++++ > xen/arch/arm/platform.c | 18 ++++++++ > xen/arch/arm/platforms/vexpress.c | 38 ++++++++++++++++ > xen/include/asm-arm/platform.h | 9 ++++ > xen/include/asm-arm/smp.h | 9 ++++ > 10 files changed, 196 insertions(+), 1 deletion(-) > create mode 100644 xen/arch/arm/arm32/smpboot.c > create mode 100644 xen/arch/arm/arm64/smpboot.c > > diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile > index 18522dc..463b1f5 100644 > --- a/xen/arch/arm/arm32/Makefile > +++ b/xen/arch/arm/arm32/Makefile > @@ -7,5 +7,6 @@ obj-y += proc-v7.o > obj-y += traps.o > obj-y += domain.o > obj-y += vfp.o > +obj-y += smpboot.o > > obj-$(EARLY_PRINTK) += debug.o > diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S > index fce18a2..8cb31a2 100644 > --- a/xen/arch/arm/arm32/head.S > +++ b/xen/arch/arm/arm32/head.S > @@ -59,7 +59,7 @@ > * or the initial pagetable code below will need adjustment. */ > .global start > start: > - > +GLOBAL(init_secondary) /* currently unused */ > /* zImage magic header, see: > * > http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html#d0e309 > */ > diff --git a/xen/arch/arm/arm32/smpboot.c b/xen/arch/arm/arm32/smpboot.c > new file mode 100644 > index 0000000..88fe8fb > --- /dev/null > +++ b/xen/arch/arm/arm32/smpboot.c > @@ -0,0 +1,29 @@ > +#include <xen/device_tree.h> > +#include <xen/init.h> > +#include <xen/smp.h> > +#include <asm/platform.h> > + > +int __init arch_smp_init(void) > +{ > + return platform_smp_init(); > +} > + > +int __init arch_cpu_init(int cpu, struct dt_device_node *dn) > +{ > + /* TODO handle PSCI init */ > + return 0; > +} > + > +int __init arch_cpu_up(int cpu) > +{ > + return platform_cpu_up(cpu); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile > index e06a0a9..30fb480 100644 > --- a/xen/arch/arm/arm64/Makefile > +++ b/xen/arch/arm/arm64/Makefile > @@ -6,5 +6,6 @@ obj-y += mode_switch.o > obj-y += traps.o > obj-y += domain.o > obj-y += vfp.o > +obj-y += smpboot.o > > obj-$(EARLY_PRINTK) += debug.o > diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S > index 4495f72..7cecac3 100644 > --- a/xen/arch/arm/arm64/head.S > +++ b/xen/arch/arm/arm64/head.S > @@ -65,6 +65,7 @@ > > .global start > start: > +GLOBAL(init_secondary) /* currently unused */ > /* > * DO NOT MODIFY. Image header expected by Linux boot-loaders. > */ > diff --git a/xen/arch/arm/arm64/smpboot.c b/xen/arch/arm/arm64/smpboot.c > new file mode 100644 > index 0000000..8239590 > --- /dev/null > +++ b/xen/arch/arm/arm64/smpboot.c > @@ -0,0 +1,89 @@ > +#include <xen/cpu.h> > +#include <xen/lib.h> > +#include <xen/init.h> > +#include <xen/errno.h> > +#include <xen/mm.h> > +#include <xen/smp.h> > + > +struct smp_enable_ops { > + int (*prepare_cpu)(int); > +}; > + > +static paddr_t cpu_release_addr[NR_CPUS]; > +static struct smp_enable_ops smp_enable_ops[NR_CPUS]; > + > +static int __init smp_spin_table_cpu_up(int cpu) > +{ > + paddr_t *release; > + > + if (!cpu_release_addr[cpu]) > + { > + printk("CPU%d: No release addr\n", cpu); > + return -ENODEV; > + } > + > + release = __va(cpu_release_addr[cpu]); > + > + release[0] = __pa(init_secondary); > + flush_xen_data_tlb_range_va((vaddr_t)release, sizeof(*release)); > + > + sev(); > + return 0; > +} > + > +static void __init smp_spin_table_init(int cpu, struct dt_device_node *dn) > +{ > + if ( !dt_property_read_u64(dn, "cpu-release-addr", > &cpu_release_addr[cpu]) ) > + { > + printk("CPU%d has no cpu-release-addr\n", cpu); > + return; > + } > + > + smp_enable_ops[cpu].prepare_cpu = smp_spin_table_cpu_up; > +} > + > +int __init arch_smp_init(void) > +{ > + /* Nothing */ > + return 0; > +} > + > +int __init arch_cpu_init(int cpu, struct dt_device_node *dn) > +{ > + const char *enable_method; > + > + enable_method = dt_get_property(dn, "enable-method", NULL); > + if (!enable_method) > + { > + printk("CPU%d has no enable method\n", cpu); > + return -EINVAL; > + } > + > + if ( !strcmp(enable_method, "spin-table") ) > + smp_spin_table_init(cpu, dn); > + /* TODO: method "psci" */ > + else > + { > + printk("CPU%d has unknown enable method \"%s\"\n", cpu, > enable_method); > + return -EINVAL; > + } > + > + return 0; > +} > + > +int __init arch_cpu_up(int cpu) > +{ > + if ( !smp_enable_ops[cpu].prepare_cpu ) > + return -ENODEV; > + > + return smp_enable_ops[cpu].prepare_cpu(cpu); > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c > index db79368..db135f8 100644 > --- a/xen/arch/arm/platform.c > +++ b/xen/arch/arm/platform.c > @@ -105,6 +105,24 @@ int __init platform_specific_mapping(struct domain *d) > return res; > } > > +#ifdef CONFIG_ARM_32 > +int __init platform_cpu_up(int cpu) > +{ > + if ( platform && platform->cpu_up ) > + return platform->cpu_up(cpu); > + > + return -EAGAIN; > +} > + > +int __init platform_smp_init(void) > +{ > + if ( platform && platform->smp_init ) > + return platform->smp_init(); > + > + return 0; > +} > +#endif > + > void platform_reset(void) > { > if ( platform && platform->reset ) > diff --git a/xen/arch/arm/platforms/vexpress.c > b/xen/arch/arm/platforms/vexpress.c > index 22c0c13..be0516f 100644 > --- a/xen/arch/arm/platforms/vexpress.c > +++ b/xen/arch/arm/platforms/vexpress.c > @@ -22,6 +22,7 @@ > #include <xen/mm.h> > #include <xen/vmap.h> > #include <asm/io.h> > +#include <asm/gic.h> > > #define DCC_SHIFT 26 > #define FUNCTION_SHIFT 20 > @@ -120,6 +121,39 @@ static void vexpress_reset(void) > iounmap(sp810); > } > > +#ifdef CONFIG_ARM_32 > + > +static int vexpress_smp_init(void) platform_smp_init is in init section. vexpress_smp should also be here. > +{ > + void __iomem *sysflags; > + > + sysflags = ioremap_nocache(V2M_SYS_MMIO_BASE, PAGE_SIZE); > + if ( !sysflags ) > + { > + dprintk(XENLOG_ERR, "Unable to map vexpress MMIO\n"); > + return -EFAULT; > + } > + > + printk("Set SYS_FLAGS to %"PRIpaddr" (%p)\n", > + __pa(init_secondary), init_secondary); > + writel(~0, sysflags + V2M_SYS_FLAGSCLR); > + writel(__pa(init_secondary), sysflags + V2M_SYS_FLAGSSET); > + > + iounmap(sysflags); > + > + return 0; > +} > + > +static int vexpress_cpu_up(int cpu) same here. > +{ > + /* Nothing to do here, the generic sev() will suffice to kick CPUs > + * out of either the firmware or our own smp_up_cpu gate, > + * depending on where they have ended up. */ > + > + return 0; > +} > +#endif > + > static const char * const vexpress_dt_compat[] __initdata = > { > "arm,vexpress", > @@ -144,6 +178,10 @@ static const struct dt_device_match > vexpress_blacklist_dev[] __initconst = > > PLATFORM_START(vexpress, "VERSATILE EXPRESS") > .compatible = vexpress_dt_compat, > +#ifdef CONFIG_ARM_32 > + .smp_init = vexpress_smp_init, > + .cpu_up = vexpress_cpu_up, > +#endif > .reset = vexpress_reset, > .blacklist_dev = vexpress_blacklist_dev, > PLATFORM_END > diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h > index a19dbf7..dbd2a15 100644 > --- a/xen/include/asm-arm/platform.h > +++ b/xen/include/asm-arm/platform.h > @@ -15,6 +15,11 @@ struct platform_desc { > /* Platform initialization */ > int (*init)(void); > int (*init_time)(void); > +#ifdef CONFIG_ARM_32 > + /* SMP */ > + int (*smp_init)(void); > + int (*cpu_up)(int cpu); > +#endif > /* Specific mapping for dom0 */ > int (*specific_mapping)(struct domain *d); > /* Platform reset */ > @@ -43,6 +48,10 @@ struct platform_desc { > int __init platform_init(void); > int __init platform_init_time(void); > int __init platform_specific_mapping(struct domain *d); > +#ifdef CONFIG_ARM_32 > +int platform_smp_init(void); > +int platform_cpu_up(int cpu); > +#endif > void platform_reset(void); > void platform_poweroff(void); > bool_t platform_has_quirk(uint32_t quirk); > diff --git a/xen/include/asm-arm/smp.h b/xen/include/asm-arm/smp.h > index 1c2746b..1added5 100644 > --- a/xen/include/asm-arm/smp.h > +++ b/xen/include/asm-arm/smp.h > @@ -4,6 +4,7 @@ > #ifndef __ASSEMBLY__ > #include <xen/config.h> > #include <xen/cpumask.h> > +#include <xen/device_tree.h> > #include <asm/current.h> > #endif > > @@ -22,9 +23,17 @@ extern void stop_cpu(void); > extern void > make_cpus_ready(unsigned int max_cpus, unsigned long boot_phys_offset); > > +extern int arch_smp_init(void); > +extern int arch_cpu_init(int cpu, struct dt_device_node *dn); > +extern int arch_cpu_up(int cpu); > + > +/* Secondary CPU entry point */ > +extern void init_secondary(void); > + > extern void smp_clear_cpu_maps (void); > extern int smp_get_max_cpus (void); > #endif > + > /* > * Local variables: > * mode: C > -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |