Skip to content

Commit

Permalink
sparc64: use RCU page table freeing
Browse files Browse the repository at this point in the history
Make use of the generic RCU page table freeing on Sparc64, doing so allows
for race-free software page-table walkers like gup_fast().

Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Peter Zijlstra <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
davem330 authored and torvalds committed Jul 26, 2011
1 parent 4dedbf8 commit 4a0100f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/sparc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ config SPARC64
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES
select HAVE_KPROBES
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_MEMBLOCK
select HAVE_SYSCALL_WRAPPERS
select HAVE_DYNAMIC_FTRACE
Expand Down
48 changes: 46 additions & 2 deletions arch/sparc/include/asm/pgalloc_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,51 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)

#define check_pgt_cache() do { } while (0)

#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
static inline void pgtable_free(void *table, bool is_page)
{
if (is_page)
free_page((unsigned long)table);
else
kmem_cache_free(pgtable_cache, table);
}

#ifdef CONFIG_SMP

struct mmu_gather;
extern void tlb_remove_table(struct mmu_gather *, void *);

static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
{
unsigned long pgf = (unsigned long)table;
if (is_page)
pgf |= 0x1UL;
tlb_remove_table(tlb, (void *)pgf);
}

static inline void __tlb_remove_table(void *_table)
{
void *table = (void *)((unsigned long)_table & ~0x1UL);
bool is_page = false;

if ((unsigned long)_table & 0x1UL)
is_page = true;
pgtable_free(table, is_page);
}
#else /* CONFIG_SMP */
static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
{
pgtable_free(table, is_page);
}
#endif /* !CONFIG_SMP */

static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage,
unsigned long address)
{
pgtable_page_dtor(ptepage);
pgtable_free_tlb(tlb, page_address(ptepage), true);
}

#define __pmd_free_tlb(tlb, pmd, addr) \
pgtable_free_tlb(tlb, pmd, false)

#endif /* _SPARC64_PGALLOC_H */

0 comments on commit 4a0100f

Please sign in to comment.