diff options
| author | Andrea Arcangeli <aarcange@redhat.com> | 2011-01-13 15:46:40 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 17:32:40 -0800 | 
| commit | e2cda322648122dc400c85ada80eaddbc612ef6a (patch) | |
| tree | 016981ea6d9d3f7448bd9e04720184b14a79302c /mm/pgtable-generic.c | |
| parent | 5f6e8da70a289d403975907371ce5738c726ad3f (diff) | |
| download | olio-linux-3.10-e2cda322648122dc400c85ada80eaddbc612ef6a.tar.xz olio-linux-3.10-e2cda322648122dc400c85ada80eaddbc612ef6a.zip  | |
thp: add pmd mangling generic functions
Some are needed to build but not actually used on archs not supporting
transparent hugepages.  Others like pmdp_clear_flush are used by x86 too.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Acked-by: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/pgtable-generic.c')
| -rw-r--r-- | mm/pgtable-generic.c | 123 | 
1 files changed, 123 insertions, 0 deletions
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c new file mode 100644 index 00000000000..d030548047e --- /dev/null +++ b/mm/pgtable-generic.c @@ -0,0 +1,123 @@ +/* + *  mm/pgtable-generic.c + * + *  Generic pgtable methods declared in asm-generic/pgtable.h + * + *  Copyright (C) 2010  Linus Torvalds + */ + +#include <asm/tlb.h> +#include <asm-generic/pgtable.h> + +#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +/* + * Only sets the access flags (dirty, accessed, and + * writable). Furthermore, we know it always gets set to a "more + * permissive" setting, which allows most architectures to optimize + * this. We return whether the PTE actually changed, which in turn + * instructs the caller to do things like update__mmu_cache.  This + * used to be done in the caller, but sparc needs minor faults to + * force that call on sun4c so we changed this macro slightly + */ +int ptep_set_access_flags(struct vm_area_struct *vma, +			  unsigned long address, pte_t *ptep, +			  pte_t entry, int dirty) +{ +	int changed = !pte_same(*ptep, entry); +	if (changed) { +		set_pte_at(vma->vm_mm, address, ptep, entry); +		flush_tlb_page(vma, address); +	} +	return changed; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS +int pmdp_set_access_flags(struct vm_area_struct *vma, +			  unsigned long address, pmd_t *pmdp, +			  pmd_t entry, int dirty) +{ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +	int changed = !pmd_same(*pmdp, entry); +	VM_BUG_ON(address & ~HPAGE_PMD_MASK); +	if (changed) { +		set_pmd_at(vma->vm_mm, address, pmdp, entry); +		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); +	} +	return changed; +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +	BUG(); +	return 0; +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +} +#endif + +#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH +int ptep_clear_flush_young(struct vm_area_struct *vma, +			   unsigned long address, pte_t *ptep) +{ +	int young; +	young = ptep_test_and_clear_young(vma, address, ptep); +	if (young) +		flush_tlb_page(vma, address); +	return young; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH +int pmdp_clear_flush_young(struct vm_area_struct *vma, +			   unsigned long address, pmd_t *pmdp) +{ +	int young; +#ifndef CONFIG_TRANSPARENT_HUGEPAGE +	BUG(); +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +	VM_BUG_ON(address & ~HPAGE_PMD_MASK); +	young = pmdp_test_and_clear_young(vma, address, pmdp); +	if (young) +		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); +	return young; +} +#endif + +#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH +pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address, +		       pte_t *ptep) +{ +	pte_t pte; +	pte = ptep_get_and_clear((vma)->vm_mm, address, ptep); +	flush_tlb_page(vma, address); +	return pte; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_CLEAR_FLUSH +pmd_t pmdp_clear_flush(struct vm_area_struct *vma, unsigned long address, +		       pmd_t *pmdp) +{ +	pmd_t pmd; +#ifndef CONFIG_TRANSPARENT_HUGEPAGE +	BUG(); +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +	VM_BUG_ON(address & ~HPAGE_PMD_MASK); +	pmd = pmdp_get_and_clear(vma->vm_mm, address, pmdp); +	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); +	return pmd; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_SPLITTING_FLUSH +pmd_t pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address, +			   pmd_t *pmdp) +{ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +	pmd_t pmd = pmd_mksplitting(*pmdp); +	VM_BUG_ON(address & ~HPAGE_PMD_MASK); +	set_pmd_at(vma->vm_mm, address, pmdp, pmd); +	/* tlb flush only to serialize against gup-fast */ +	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE); +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +	BUG(); +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +} +#endif  |