From 267239116987d64850ad2037d8e0f3071dc3b5ce Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 24 May 2011 17:12:00 -0700 Subject: mm, powerpc: move the RCU page-table freeing into generic code In case other architectures require RCU freed page-tables to implement gup_fast() and software filled hashes and similar things, provide the means to do so by moving the logic into generic code. Signed-off-by: Peter Zijlstra Requested-by: David Miller Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: Russell King Cc: Paul Mundt Cc: Jeff Dike Cc: Richard Weinberger Cc: Tony Luck Cc: KAMEZAWA Hiroyuki Cc: Hugh Dickins Cc: Mel Gorman Cc: KOSAKI Motohiro Cc: Nick Piggin Cc: Namhyung Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/pgtable.c | 98 -------------------------------------------- arch/powerpc/mm/tlb_hash32.c | 3 -- arch/powerpc/mm/tlb_hash64.c | 3 -- arch/powerpc/mm/tlb_nohash.c | 3 -- 4 files changed, 107 deletions(-) (limited to 'arch/powerpc/mm') diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 6e72788598f8..af40c8768a78 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c @@ -33,104 +33,6 @@ #include "mmu_decl.h" -#ifdef CONFIG_SMP - -/* - * Handle batching of page table freeing on SMP. Page tables are - * queued up and send to be freed later by RCU in order to avoid - * freeing a page table page that is being walked without locks - */ - -static unsigned long pte_freelist_forced_free; - -struct pte_freelist_batch -{ - struct rcu_head rcu; - unsigned int index; - unsigned long tables[0]; -}; - -#define PTE_FREELIST_SIZE \ - ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \ - / sizeof(unsigned long)) - -static void pte_free_smp_sync(void *arg) -{ - /* Do nothing, just ensure we sync with all CPUs */ -} - -/* This is only called when we are critically out of memory - * (and fail to get a page in pte_free_tlb). - */ -static void pgtable_free_now(void *table, unsigned shift) -{ - pte_freelist_forced_free++; - - smp_call_function(pte_free_smp_sync, NULL, 1); - - pgtable_free(table, shift); -} - -static void pte_free_rcu_callback(struct rcu_head *head) -{ - struct pte_freelist_batch *batch = - container_of(head, struct pte_freelist_batch, rcu); - unsigned int i; - - for (i = 0; i < batch->index; i++) { - void *table = (void *)(batch->tables[i] & ~MAX_PGTABLE_INDEX_SIZE); - unsigned shift = batch->tables[i] & MAX_PGTABLE_INDEX_SIZE; - - pgtable_free(table, shift); - } - - free_page((unsigned long)batch); -} - -static void pte_free_submit(struct pte_freelist_batch *batch) -{ - call_rcu_sched(&batch->rcu, pte_free_rcu_callback); -} - -void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift) -{ - struct pte_freelist_batch **batchp = &tlb->arch.batch; - unsigned long pgf; - - if (atomic_read(&tlb->mm->mm_users) < 2) { - pgtable_free(table, shift); - return; - } - - if (*batchp == NULL) { - *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); - if (*batchp == NULL) { - pgtable_free_now(table, shift); - return; - } - (*batchp)->index = 0; - } - BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); - pgf = (unsigned long)table | shift; - (*batchp)->tables[(*batchp)->index++] = pgf; - if ((*batchp)->index == PTE_FREELIST_SIZE) { - pte_free_submit(*batchp); - *batchp = NULL; - } -} - -void pte_free_finish(struct mmu_gather *tlb) -{ - struct pte_freelist_batch **batchp = &tlb->arch.batch; - - if (*batchp == NULL) - return; - pte_free_submit(*batchp); - *batchp = NULL; -} - -#endif /* CONFIG_SMP */ - static inline int is_exec_fault(void) { return current->thread.regs && TRAP(current->thread.regs) == 0x400; diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c index d555cdb06bc8..27b863c14941 100644 --- a/arch/powerpc/mm/tlb_hash32.c +++ b/arch/powerpc/mm/tlb_hash32.c @@ -71,9 +71,6 @@ void tlb_flush(struct mmu_gather *tlb) */ _tlbia(); } - - /* Push out batch of freed page tables */ - pte_free_finish(tlb); } /* diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index 5c94ca34cd79..31f18207970b 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c @@ -165,9 +165,6 @@ void tlb_flush(struct mmu_gather *tlb) __flush_tlb_pending(tlbbatch); put_cpu_var(ppc64_tlb_batch); - - /* Push out batch of freed page tables */ - pte_free_finish(tlb); } /** diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 8eaf67d32043..0bdad3aecc67 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -299,9 +299,6 @@ EXPORT_SYMBOL(flush_tlb_range); void tlb_flush(struct mmu_gather *tlb) { flush_tlb_mm(tlb->mm); - - /* Push out batch of freed page tables */ - pte_free_finish(tlb); } /* -- cgit v1.2.2