Skip to content

Commit

Permalink
ARM: 6279/1: highmem: fix SMP preemption bug in kmap_high_l1_vipt
Browse files Browse the repository at this point in the history
smp_processor_id() must not be called from a preemptible context (this
is checked by CONFIG_DEBUG_PREEMPT).  kmap_high_l1_vipt() was doing so.
This lead to a problem where the wrong per_cpu kmap_high_l1_vipt_depth
could be incremented, causing a BUG_ON(*depth <= 0); in
kunmap_high_l1_vipt().

The solution is to move the call to smp_processor_id() after the call
to preempt_disable().

Originally by: Andrew Howe <[email protected]>

Signed-off-by: Gary King <[email protected]>
Acked-by: Nicolas Pitre <[email protected]>
Signed-off-by: Russell King <[email protected]>
  • Loading branch information
Gary King authored and Russell King committed Jul 30, 2010
1 parent b92b361 commit 831e804
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions arch/arm/mm/highmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,19 +163,22 @@ static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);

void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
{
unsigned int idx, cpu = smp_processor_id();
int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
unsigned int idx, cpu;
int *depth;
unsigned long vaddr, flags;
pte_t pte, *ptep;

if (!in_interrupt())
preempt_disable();

cpu = smp_processor_id();
depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);

idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
ptep = TOP_PTE(vaddr);
pte = mk_pte(page, kmap_prot);

if (!in_interrupt())
preempt_disable();

raw_local_irq_save(flags);
(*depth)++;
if (pte_val(*ptep) == pte_val(pte)) {
Expand Down

0 comments on commit 831e804

Please sign in to comment.