Message ID | 20121011195033.GA31946@mudshark.cambridge.arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 10/11/2012 09:50 PM, Will Deacon wrote: > On 10/11/2012 03:59 PM, Will Deacon wrote: >> I'll have to do some digging and get back to you. > > Ok, so here's what I think is going on (although note that I'm at home now, > so I've not been able to test anything): > > - Your PHYS_OFFSET is at 2GB, so your static idmap is as follows: > idmap: 0x8029c638 - 0x8029c66c and I think your init_mm lives > at 0x8037f2b4. > > - The idmap takes up two sections, so actually spans from: > 0x80200000 - 0x80400000 and is mapped as *strongly ordered*. > > This means that the atomic_inc(&mm->mm_count); in secondary_start_kernel > is UNPREDICTABLE, because it results in an exclusive access to > strongly-ordered memory. > > There are several ways to solve this: > > 1. Avoid exclusives with the idmap (see patch below) > 2. Set idmap_pgd to swapper when VA == PA > 3. Map idmap with pages and round up text section > 4. Switch to swapper before entering secondary_start_kernel > 5. Make idmap normal (cacheable?) shared memory > > However, these have some problems: > > (2) means the idmap is cacheable. This is probably not an issue > when VA == PA, but it's still an oddity compared to other setups > > (3) is really messy > > (4,5) probably have serious issues with SMP > > so I've had a crack at (1) below. Please see if it fixes your problem. > > Cheers, > > Will > > --->8 > > diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c > index d100eac..aa55580 100644 > --- a/arch/arm/kernel/smp.c > +++ b/arch/arm/kernel/smp.c > @@ -290,18 +290,24 @@ static void percpu_timer_setup(void); > asmlinkage void __cpuinit secondary_start_kernel(void) > { > struct mm_struct *mm = &init_mm; > - unsigned int cpu = smp_processor_id(); > + unsigned int cpu; > + > + /* > + * The identity mapping is uncached (strongly ordered), so > + * switch away from it before attempting any exclusive accesses. > + */ > + cpu_switch_mm(mm->pgd, mm); > + enter_lazy_tlb(mm, current); > + local_flush_tlb_all(); > > /* > * All kernel threads share the same mm context; grab a > * reference and switch to it. > */ > + cpu = smp_processor_id(); > atomic_inc(&mm->mm_count); > current->active_mm = mm; > cpumask_set_cpu(cpu, mm_cpumask(mm)); > - cpu_switch_mm(mm->pgd, mm); > - enter_lazy_tlb(mm, current); > - local_flush_tlb_all(); > > printk("CPU%u: Booted secondary processor\n", cpu); Works for me. But note that now the comment is wrong.
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d100eac..aa55580 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -290,18 +290,24 @@ static void percpu_timer_setup(void); asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + /* + * The identity mapping is uncached (strongly ordered), so + * switch away from it before attempting any exclusive accesses. + */ + cpu_switch_mm(mm->pgd, mm); + enter_lazy_tlb(mm, current); + local_flush_tlb_all(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ + cpu = smp_processor_id(); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); printk("CPU%u: Booted secondary processor\n", cpu);
On 10/11/2012 03:59 PM, Will Deacon wrote: > I'll have to do some digging and get back to you. Ok, so here's what I think is going on (although note that I'm at home now, so I've not been able to test anything): - Your PHYS_OFFSET is at 2GB, so your static idmap is as follows: idmap: 0x8029c638 - 0x8029c66c and I think your init_mm lives at 0x8037f2b4. - The idmap takes up two sections, so actually spans from: 0x80200000 - 0x80400000 and is mapped as *strongly ordered*. This means that the atomic_inc(&mm->mm_count); in secondary_start_kernel is UNPREDICTABLE, because it results in an exclusive access to strongly-ordered memory. There are several ways to solve this: 1. Avoid exclusives with the idmap (see patch below) 2. Set idmap_pgd to swapper when VA == PA 3. Map idmap with pages and round up text section 4. Switch to swapper before entering secondary_start_kernel 5. Make idmap normal (cacheable?) shared memory However, these have some problems: (2) means the idmap is cacheable. This is probably not an issue when VA == PA, but it's still an oddity compared to other setups (3) is really messy (4,5) probably have serious issues with SMP so I've had a crack at (1) below. Please see if it fixes your problem. Cheers, Will --->8