ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count
authorWill Deacon <will.deacon@arm.com>
Fri, 19 Oct 2012 16:53:01 +0000 (17:53 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Tue, 30 Oct 2012 23:26:54 +0000 (23:26 +0000)
commit4a40d59021b6b895e3f19e53a5dfee9fefca7855
tree907f5bd5bdd3b514afc1d4bbafbaacc7651a536e
parent3042c7c2ee52f0ebfc8e09bc2c4cdbff3fc4ec61
ARM: 7559/1: smp: switch away from the idmap before updating init_mm.mm_count

commit 5f40b909728ad784eb43aa309d3c4e9bdf050781 upstream.

When booting a secondary CPU, the primary CPU hands two sets of page
tables via the secondary_data struct:

(1) swapper_pg_dir: a normal, cacheable, shared (if SMP) mapping
    of the kernel image (i.e. the tables used by init_mm).

(2) idmap_pgd: an uncached mapping of the .idmap.text ELF
    section.

The idmap is generally used when enabling and disabling the MMU, which
includes early CPU boot. In this case, the secondary CPU switches to
swapper as soon as it enters C code:

struct mm_struct *mm = &init_mm;
unsigned int cpu = smp_processor_id();

/*
 * All kernel threads share the same mm context; grab a
 * reference and switch to it.
 */
atomic_inc(&mm->mm_count);
current->active_mm = mm;
cpumask_set_cpu(cpu, mm_cpumask(mm));
cpu_switch_mm(mm->pgd, mm);

This causes a problem on ARMv7, where the identity mapping is treated as
strongly-ordered leading to architecturally UNPREDICTABLE behaviour of
exclusive accesses, such as those used by atomic_inc.

This patch re-orders the secondary_start_kernel function so that we
switch to swapper before performing any exclusive accesses.

Cc: David McKay <david.mckay@st.com>
Reported-by: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
arch/arm/kernel/smp.c