Re: [PATCH 2/3] ARM: Xilinx: add SMP specific support files

From: Catalin Marinas
Date: Mon Apr 04 2011 - 11:13:31 EST


John,

A few suggestions on barriers below.

On 3 April 2011 22:00, John Linn <john.linn@xxxxxxxxxx> wrote:
> diff --git a/arch/arm/mach-xilinx/platsmp.c b/arch/arm/mach-xilinx/platsmp.c
> new file mode 100644
> index 0000000..be2d55c
> --- /dev/null
> +++ b/arch/arm/mach-xilinx/platsmp.c
...
> +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
> +{
> + Â Â Â unsigned long timeout;
> +
> + Â Â Â /*
> + Â Â Â Â* set synchronisation state between this boot processor
> + Â Â Â Â* and the secondary one
> + Â Â Â Â*/
> + Â Â Â spin_lock(&boot_lock);
> +
> + Â Â Â printk(KERN_INFO "Xilinx SMP: booting CPU1 now\n");
> +
> + Â Â Â /*
> + Â Â Â Â* Update boot lock register with the boot key to allow the
> + Â Â Â Â* secondary processor to start the kernel after an SEV.
> + Â Â Â Â*/
> + Â Â Â __raw_writel(BOOT_LOCK_KEY, OCM_HIGH_BASE + BOOT_LOCK_OFFSET);
> +
> + Â Â Â /* Flush the kernel cache to ensure that the page tables are
> + Â Â Â Â* available for the secondary CPU to use and make sure that
> + Â Â Â Â* the write buffer is drained before doing an SEV.
> + Â Â Â Â*/
> + Â Â Â flush_cache_all();
> + Â Â Â smp_wmb();
> +
> + Â Â Â /*
> + Â Â Â Â* Send an event to wake the secondary core from WFE state.
> + Â Â Â Â*/
> + Â Â Â sev();

You could flush the cache before writing the boot lock register in
case the secondary wakes up from WFE. You also need a wmb() rather
than the smp_wmb(). The latter only works in the inner shareable
domain but the secondary CPU hasn't initialised the MMU yet.

Something like below:

flush_cache_all();
__raw_writel(BOOT_LOCK_KEY, OCM_HIGH_BASE + BOOT_LOCK_OFFSET);
mb();
sev();

> +void __init platform_smp_prepare_cpus(unsigned int max_cpus)
> +{
> + Â Â Â int i;
> +
> + Â Â Â /*
> + Â Â Â Â* Initialise the present map, which describes the set of CPUs
> + Â Â Â Â* actually populated at the present time.
> + Â Â Â Â*/
> + Â Â Â for (i = 0; i < max_cpus; i++)
> + Â Â Â Â Â Â Â set_cpu_present(i, true);
> +
> + Â Â Â scu_enable(scu_base);
> +
> + Â Â Â /* Initialize the boot lock register to prevent CPU1 from
> + Â Â Â Â Âstarting the kernel before CPU0 is ready for that.
> + Â Â Â */
> + Â Â Â __raw_writel(0, OCM_HIGH_BASE + BOOT_LOCK_OFFSET);
> +
> + Â Â Â /*
> + Â Â Â Â* Write the address of secondary startup routine into the
> + Â Â Â Â* boot address. The secondary CPU will use this value
> + Â Â Â Â* to get into the kernel after it's awake from WFE state.
> + Â Â Â Â*
> + Â Â Â Â* Note the physical address is needed as the secondary CPU
> + Â Â Â Â* will not have the MMU on yet. A barrier is added to ensure
> + Â Â Â Â* that write buffer is drained.
> + Â Â Â Â*/
> + Â Â Â __raw_writel(virt_to_phys(xilinx_secondary_startup),
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OCM_HIGH_BASE + BOOT_ADDR_OFFSET);
> + Â Â Â smp_wmb();

Same here, use a wmb() or mb() before the sev().

--
Catalin
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/