Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 298846
b: refs/heads/master
c: 719ea79
h: refs/heads/master
v: v3
  • Loading branch information
Chris Metcalf committed Apr 2, 2012
1 parent b2aea41 commit bba58bc
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5f220704127ae70db519fabbda4ece649eadac7f
refs/heads/master: 719ea79e330c5e1a17fb7e4cf352a81e4c84cff5
22 changes: 12 additions & 10 deletions trunk/arch/tile/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,10 @@ void shatter_huge_page(unsigned long addr)
if (!pmd_huge_page(*pmd))
return;

/*
* Grab the pgd_lock, since we may need it to walk the pgd_list,
* and since we need some kind of lock here to avoid races.
*/
spin_lock_irqsave(&pgd_lock, flags);
spin_lock_irqsave(&init_mm.page_table_lock, flags);
if (!pmd_huge_page(*pmd)) {
/* Lost the race to convert the huge page. */
spin_unlock_irqrestore(&pgd_lock, flags);
spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
return;
}

Expand All @@ -194,21 +190,23 @@ void shatter_huge_page(unsigned long addr)

#ifdef __PAGETABLE_PMD_FOLDED
/* Walk every pgd on the system and update the pmd there. */
spin_lock(&pgd_lock);
list_for_each(pos, &pgd_list) {
pmd_t *copy_pmd;
pgd = list_to_pgd(pos) + pgd_index(addr);
pud = pud_offset(pgd, addr);
copy_pmd = pmd_offset(pud, addr);
__set_pmd(copy_pmd, *pmd);
}
spin_unlock(&pgd_lock);
#endif

/* Tell every cpu to notice the change. */
flush_remote(0, 0, NULL, addr, HPAGE_SIZE, HPAGE_SIZE,
cpu_possible_mask, NULL, 0);

/* Hold the lock until the TLB flush is finished to avoid races. */
spin_unlock_irqrestore(&pgd_lock, flags);
spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
}

/*
Expand All @@ -217,9 +215,13 @@ void shatter_huge_page(unsigned long addr)
* against pageattr.c; it is the unique case in which a valid change
* of kernel pagetables can't be lazily synchronized by vmalloc faults.
* vmalloc faults work because attached pagetables are never freed.
* The locking scheme was chosen on the basis of manfred's
* recommendations and having no core impact whatsoever.
* -- wli
*
* The lock is always taken with interrupts disabled, unlike on x86
* and other platforms, because we need to take the lock in
* shatter_huge_page(), which may be called from an interrupt context.
* We are not at risk from the tlbflush IPI deadlock that was seen on
* x86, since we use the flush_remote() API to have the hypervisor do
* the TLB flushes regardless of irq disabling.
*/
DEFINE_SPINLOCK(pgd_lock);
LIST_HEAD(pgd_list);
Expand Down

0 comments on commit bba58bc

Please sign in to comment.