diff options
Diffstat (limited to 'include/asm-generic/pgtable.h')
| -rw-r--r-- | include/asm-generic/pgtable.h | 665 | 
1 files changed, 571 insertions, 94 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 6f3c6ae4fe0..53b2acc3821 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -4,68 +4,114 @@  #ifndef __ASSEMBLY__  #ifdef CONFIG_MMU -#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +#include <linux/mm_types.h> +#include <linux/bug.h> +  /* - * Largely same as above, but 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 + * On almost all architectures and configurations, 0 can be used as the + * upper ceiling to free_pgtables(): on many architectures it has the same + * effect as using TASK_SIZE.  However, there is one configuration which + * must impose a more careful limit, to avoid freeing kernel pgtables.   */ -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ -({									  \ -	int __changed = !pte_same(*(__ptep), __entry);			  \ -	if (__changed) {						  \ -		set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \ -		flush_tlb_page(__vma, __address);			  \ -	}								  \ -	__changed;							  \ -}) +#ifndef USER_PGTABLES_CEILING +#define USER_PGTABLES_CEILING	0UL +#endif + +#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +extern int ptep_set_access_flags(struct vm_area_struct *vma, +				 unsigned long address, pte_t *ptep, +				 pte_t entry, int dirty); +#endif + +#ifndef __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS +extern int pmdp_set_access_flags(struct vm_area_struct *vma, +				 unsigned long address, pmd_t *pmdp, +				 pmd_t entry, int dirty);  #endif  #ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG -#define ptep_test_and_clear_young(__vma, __address, __ptep)		\ -({									\ -	pte_t __pte = *(__ptep);					\ -	int r = 1;							\ -	if (!pte_young(__pte))						\ -		r = 0;							\ -	else								\ -		set_pte_at((__vma)->vm_mm, (__address),			\ -			   (__ptep), pte_mkold(__pte));			\ -	r;								\ -}) +static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, +					    unsigned long address, +					    pte_t *ptep) +{ +	pte_t pte = *ptep; +	int r = 1; +	if (!pte_young(pte)) +		r = 0; +	else +		set_pte_at(vma->vm_mm, address, ptep, pte_mkold(pte)); +	return r; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, +					    unsigned long address, +					    pmd_t *pmdp) +{ +	pmd_t pmd = *pmdp; +	int r = 1; +	if (!pmd_young(pmd)) +		r = 0; +	else +		set_pmd_at(vma->vm_mm, address, pmdp, pmd_mkold(pmd)); +	return r; +} +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, +					    unsigned long address, +					    pmd_t *pmdp) +{ +	BUG(); +	return 0; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */  #endif  #ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH -#define ptep_clear_flush_young(__vma, __address, __ptep)		\ -({									\ -	int __young;							\ -	__young = ptep_test_and_clear_young(__vma, __address, __ptep);	\ -	if (__young)							\ -		flush_tlb_page(__vma, __address);			\ -	__young;							\ -}) +int ptep_clear_flush_young(struct vm_area_struct *vma, +			   unsigned long address, pte_t *ptep); +#endif + +#ifndef __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH +int pmdp_clear_flush_young(struct vm_area_struct *vma, +			   unsigned long address, pmd_t *pmdp);  #endif  #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR -#define ptep_get_and_clear(__mm, __address, __ptep)			\ -({									\ -	pte_t __pte = *(__ptep);					\ -	pte_clear((__mm), (__address), (__ptep));			\ -	__pte;								\ -}) +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, +				       unsigned long address, +				       pte_t *ptep) +{ +	pte_t pte = *ptep; +	pte_clear(mm, address, ptep); +	return pte; +} +#endif + +#ifndef __HAVE_ARCH_PMDP_GET_AND_CLEAR +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, +				       unsigned long address, +				       pmd_t *pmdp) +{ +	pmd_t pmd = *pmdp; +	pmd_clear(pmdp); +	return pmd; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */  #endif  #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL -#define ptep_get_and_clear_full(__mm, __address, __ptep, __full)	\ -({									\ -	pte_t __pte;							\ -	__pte = ptep_get_and_clear((__mm), (__address), (__ptep));	\ -	__pte;								\ -}) +static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, +					    unsigned long address, pte_t *ptep, +					    int full) +{ +	pte_t pte; +	pte = ptep_get_and_clear(mm, address, ptep); +	return pte; +}  #endif  /* @@ -74,20 +120,25 @@   * not present, or in the process of an address space destruction.   */  #ifndef __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL -#define pte_clear_not_present_full(__mm, __address, __ptep, __full)	\ -do {									\ -	pte_clear((__mm), (__address), (__ptep));			\ -} while (0) +static inline void pte_clear_not_present_full(struct mm_struct *mm, +					      unsigned long address, +					      pte_t *ptep, +					      int full) +{ +	pte_clear(mm, address, ptep); +}  #endif  #ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH -#define ptep_clear_flush(__vma, __address, __ptep)			\ -({									\ -	pte_t __pte;							\ -	__pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep);	\ -	flush_tlb_page(__vma, __address);				\ -	__pte;								\ -}) +extern pte_t ptep_clear_flush(struct vm_area_struct *vma, +			      unsigned long address, +			      pte_t *ptep); +#endif + +#ifndef __HAVE_ARCH_PMDP_CLEAR_FLUSH +extern pmd_t pmdp_clear_flush(struct vm_area_struct *vma, +			      unsigned long address, +			      pmd_t *pmdp);  #endif  #ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT @@ -99,26 +150,75 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres  }  #endif -#ifndef __HAVE_ARCH_PTE_SAME -#define pte_same(A,B)	(pte_val(A) == pte_val(B)) +#ifndef __HAVE_ARCH_PMDP_SET_WRPROTECT +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline void pmdp_set_wrprotect(struct mm_struct *mm, +				      unsigned long address, pmd_t *pmdp) +{ +	pmd_t old_pmd = *pmdp; +	set_pmd_at(mm, address, pmdp, pmd_wrprotect(old_pmd)); +} +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +static inline void pmdp_set_wrprotect(struct mm_struct *mm, +				      unsigned long address, pmd_t *pmdp) +{ +	BUG(); +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */  #endif -#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY -#define page_test_dirty(page)		(0) +#ifndef __HAVE_ARCH_PMDP_SPLITTING_FLUSH +extern void pmdp_splitting_flush(struct vm_area_struct *vma, +				 unsigned long address, pmd_t *pmdp);  #endif -#ifndef __HAVE_ARCH_PAGE_CLEAR_DIRTY -#define page_clear_dirty(page, mapped)	do { } while (0) +#ifndef __HAVE_ARCH_PGTABLE_DEPOSIT +extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, +				       pgtable_t pgtable);  #endif -#ifndef __HAVE_ARCH_PAGE_TEST_DIRTY -#define pte_maybe_dirty(pte)		pte_dirty(pte) -#else -#define pte_maybe_dirty(pte)		(1) +#ifndef __HAVE_ARCH_PGTABLE_WITHDRAW +extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); +#endif + +#ifndef __HAVE_ARCH_PMDP_INVALIDATE +extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, +			    pmd_t *pmdp);  #endif -#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG -#define page_test_and_clear_young(page) (0) +#ifndef __HAVE_ARCH_PTE_SAME +static inline int pte_same(pte_t pte_a, pte_t pte_b) +{ +	return pte_val(pte_a) == pte_val(pte_b); +} +#endif + +#ifndef __HAVE_ARCH_PTE_UNUSED +/* + * Some architectures provide facilities to virtualization guests + * so that they can flag allocated pages as unused. This allows the + * host to transparently reclaim unused pages. This function returns + * whether the pte's page is unused. + */ +static inline int pte_unused(pte_t pte) +{ +	return 0; +} +#endif + +#ifndef __HAVE_ARCH_PMD_SAME +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b) +{ +	return pmd_val(pmd_a) == pmd_val(pmd_b); +} +#else /* CONFIG_TRANSPARENT_HUGEPAGE */ +static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b) +{ +	BUG(); +	return 0; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */  #endif  #ifndef __HAVE_ARCH_PGD_OFFSET_GATE @@ -129,6 +229,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres  #define move_pte(pte, prot, old_addr, new_addr)	(pte)  #endif +#ifndef pte_accessible +# define pte_accessible(mm, pte)	((void)(pte), 1) +#endif + +#ifndef pte_present_nonuma +#define pte_present_nonuma(pte) pte_present(pte) +#endif +  #ifndef flush_tlb_fix_spurious_fault  #define flush_tlb_fix_spurious_fault(vma, address) flush_tlb_page(vma, address)  #endif @@ -302,52 +410,421 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm,  #define arch_start_context_switch(prev)	do {} while (0)  #endif +#ifndef CONFIG_HAVE_ARCH_SOFT_DIRTY +static inline int pte_soft_dirty(pte_t pte) +{ +	return 0; +} + +static inline int pmd_soft_dirty(pmd_t pmd) +{ +	return 0; +} + +static inline pte_t pte_mksoft_dirty(pte_t pte) +{ +	return pte; +} + +static inline pmd_t pmd_mksoft_dirty(pmd_t pmd) +{ +	return pmd; +} + +static inline pte_t pte_swp_mksoft_dirty(pte_t pte) +{ +	return pte; +} + +static inline int pte_swp_soft_dirty(pte_t pte) +{ +	return 0; +} + +static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) +{ +	return pte; +} + +static inline pte_t pte_file_clear_soft_dirty(pte_t pte) +{ +       return pte; +} + +static inline pte_t pte_file_mksoft_dirty(pte_t pte) +{ +       return pte; +} + +static inline int pte_file_soft_dirty(pte_t pte) +{ +       return 0; +} +#endif +  #ifndef __HAVE_PFNMAP_TRACKING  /* - * Interface that can be used by architecture code to keep track of - * memory type of pfn mappings (remap_pfn_range, vm_insert_pfn) - * - * track_pfn_vma_new is called when a _new_ pfn mapping is being established - * for physical range indicated by pfn and size. + * Interfaces that can be used by architecture code to keep track of + * memory type of pfn mappings specified by the remap_pfn_range, + * vm_insert_pfn. + */ + +/* + * track_pfn_remap is called when a _new_ pfn mapping is being established + * by remap_pfn_range() for physical range indicated by pfn and size.   */ -static inline int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, -					unsigned long pfn, unsigned long size) +static inline int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot, +				  unsigned long pfn, unsigned long addr, +				  unsigned long size)  {  	return 0;  }  /* - * Interface that can be used by architecture code to keep track of - * memory type of pfn mappings (remap_pfn_range, vm_insert_pfn) - * - * track_pfn_vma_copy is called when vma that is covering the pfnmap gets + * track_pfn_insert is called when a _new_ single pfn is established + * by vm_insert_pfn(). + */ +static inline int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, +				   unsigned long pfn) +{ +	return 0; +} + +/* + * track_pfn_copy is called when vma that is covering the pfnmap gets   * copied through copy_page_range().   */ -static inline int track_pfn_vma_copy(struct vm_area_struct *vma) +static inline int track_pfn_copy(struct vm_area_struct *vma)  {  	return 0;  }  /* - * Interface that can be used by architecture code to keep track of - * memory type of pfn mappings (remap_pfn_range, vm_insert_pfn) - *   * untrack_pfn_vma is called while unmapping a pfnmap for a region.   * untrack can be called for a specific region indicated by pfn and size or - * can be for the entire vma (in which case size can be zero). + * can be for the entire vma (in which case pfn, size are zero).   */ -static inline void untrack_pfn_vma(struct vm_area_struct *vma, -					unsigned long pfn, unsigned long size) +static inline void untrack_pfn(struct vm_area_struct *vma, +			       unsigned long pfn, unsigned long size)  {  }  #else -extern int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, -				unsigned long pfn, unsigned long size); -extern int track_pfn_vma_copy(struct vm_area_struct *vma); -extern void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn, -				unsigned long size); +extern int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot, +			   unsigned long pfn, unsigned long addr, +			   unsigned long size); +extern int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, +			    unsigned long pfn); +extern int track_pfn_copy(struct vm_area_struct *vma); +extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, +			unsigned long size);  #endif +#ifdef __HAVE_COLOR_ZERO_PAGE +static inline int is_zero_pfn(unsigned long pfn) +{ +	extern unsigned long zero_pfn; +	unsigned long offset_from_zero_pfn = pfn - zero_pfn; +	return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); +} + +#define my_zero_pfn(addr)	page_to_pfn(ZERO_PAGE(addr)) + +#else +static inline int is_zero_pfn(unsigned long pfn) +{ +	extern unsigned long zero_pfn; +	return pfn == zero_pfn; +} + +static inline unsigned long my_zero_pfn(unsigned long addr) +{ +	extern unsigned long zero_pfn; +	return zero_pfn; +} +#endif + +#ifdef CONFIG_MMU + +#ifndef CONFIG_TRANSPARENT_HUGEPAGE +static inline int pmd_trans_huge(pmd_t pmd) +{ +	return 0; +} +static inline int pmd_trans_splitting(pmd_t pmd) +{ +	return 0; +} +#ifndef __HAVE_ARCH_PMD_WRITE +static inline int pmd_write(pmd_t pmd) +{ +	BUG(); +	return 0; +} +#endif /* __HAVE_ARCH_PMD_WRITE */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + +#ifndef pmd_read_atomic +static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +{ +	/* +	 * Depend on compiler for an atomic pmd read. NOTE: this is +	 * only going to work, if the pmdval_t isn't larger than +	 * an unsigned long. +	 */ +	return *pmdp; +} +#endif + +#ifndef pmd_move_must_withdraw +static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl, +					 spinlock_t *old_pmd_ptl) +{ +	/* +	 * With split pmd lock we also need to move preallocated +	 * PTE page table if new_pmd is on different PMD page table. +	 */ +	return new_pmd_ptl != old_pmd_ptl; +} +#endif + +/* + * This function is meant to be used by sites walking pagetables with + * the mmap_sem hold in read mode to protect against MADV_DONTNEED and + * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd + * into a null pmd and the transhuge page fault can convert a null pmd + * into an hugepmd or into a regular pmd (if the hugepage allocation + * fails). While holding the mmap_sem in read mode the pmd becomes + * stable and stops changing under us only if it's not null and not a + * transhuge pmd. When those races occurs and this function makes a + * difference vs the standard pmd_none_or_clear_bad, the result is + * undefined so behaving like if the pmd was none is safe (because it + * can return none anyway). The compiler level barrier() is critically + * important to compute the two checks atomically on the same pmdval. + * + * For 32bit kernels with a 64bit large pmd_t this automatically takes + * care of reading the pmd atomically to avoid SMP race conditions + * against pmd_populate() when the mmap_sem is hold for reading by the + * caller (a special atomic read not done by "gcc" as in the generic + * version above, is also needed when THP is disabled because the page + * fault can populate the pmd from under us). + */ +static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) +{ +	pmd_t pmdval = pmd_read_atomic(pmd); +	/* +	 * The barrier will stabilize the pmdval in a register or on +	 * the stack so that it will stop changing under the code. +	 * +	 * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, +	 * pmd_read_atomic is allowed to return a not atomic pmdval +	 * (for example pointing to an hugepage that has never been +	 * mapped in the pmd). The below checks will only care about +	 * the low part of the pmd with 32bit PAE x86 anyway, with the +	 * exception of pmd_none(). So the important thing is that if +	 * the low part of the pmd is found null, the high part will +	 * be also null or the pmd_none() check below would be +	 * confused. +	 */ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +	barrier(); +#endif +	if (pmd_none(pmdval) || pmd_trans_huge(pmdval)) +		return 1; +	if (unlikely(pmd_bad(pmdval))) { +		pmd_clear_bad(pmd); +		return 1; +	} +	return 0; +} + +/* + * This is a noop if Transparent Hugepage Support is not built into + * the kernel. Otherwise it is equivalent to + * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in + * places that already verified the pmd is not none and they want to + * walk ptes while holding the mmap sem in read mode (write mode don't + * need this). If THP is not enabled, the pmd can't go away under the + * code even if MADV_DONTNEED runs, but if THP is enabled we need to + * run a pmd_trans_unstable before walking the ptes after + * split_huge_page_pmd returns (because it may have run when the pmd + * become null, but then a page fault can map in a THP and not a + * regular page). + */ +static inline int pmd_trans_unstable(pmd_t *pmd) +{ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +	return pmd_none_or_trans_huge_or_clear_bad(pmd); +#else +	return 0; +#endif +} + +#ifdef CONFIG_NUMA_BALANCING +#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE +/* + * _PAGE_NUMA works identical to _PAGE_PROTNONE (it's actually the + * same bit too). It's set only when _PAGE_PRESET is not set and it's + * never set if _PAGE_PRESENT is set. + * + * pte/pmd_present() returns true if pte/pmd_numa returns true. Page + * fault triggers on those regions if pte/pmd_numa returns true + * (because _PAGE_PRESENT is not set). + */ +#ifndef pte_numa +static inline int pte_numa(pte_t pte) +{ +	return (pte_flags(pte) & +		(_PAGE_NUMA|_PAGE_PROTNONE|_PAGE_PRESENT)) == _PAGE_NUMA; +} +#endif + +#ifndef pmd_numa +static inline int pmd_numa(pmd_t pmd) +{ +	return (pmd_flags(pmd) & +		(_PAGE_NUMA|_PAGE_PROTNONE|_PAGE_PRESENT)) == _PAGE_NUMA; +} +#endif + +/* + * pte/pmd_mknuma sets the _PAGE_ACCESSED bitflag automatically + * because they're called by the NUMA hinting minor page fault. If we + * wouldn't set the _PAGE_ACCESSED bitflag here, the TLB miss handler + * would be forced to set it later while filling the TLB after we + * return to userland. That would trigger a second write to memory + * that we optimize away by setting _PAGE_ACCESSED here. + */ +#ifndef pte_mknonnuma +static inline pte_t pte_mknonnuma(pte_t pte) +{ +	pteval_t val = pte_val(pte); + +	val &= ~_PAGE_NUMA; +	val |= (_PAGE_PRESENT|_PAGE_ACCESSED); +	return __pte(val); +} +#endif + +#ifndef pmd_mknonnuma +static inline pmd_t pmd_mknonnuma(pmd_t pmd) +{ +	pmdval_t val = pmd_val(pmd); + +	val &= ~_PAGE_NUMA; +	val |= (_PAGE_PRESENT|_PAGE_ACCESSED); + +	return __pmd(val); +} +#endif + +#ifndef pte_mknuma +static inline pte_t pte_mknuma(pte_t pte) +{ +	pteval_t val = pte_val(pte); + +	val &= ~_PAGE_PRESENT; +	val |= _PAGE_NUMA; + +	return __pte(val); +} +#endif + +#ifndef ptep_set_numa +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, +				 pte_t *ptep) +{ +	pte_t ptent = *ptep; + +	ptent = pte_mknuma(ptent); +	set_pte_at(mm, addr, ptep, ptent); +	return; +} +#endif + +#ifndef pmd_mknuma +static inline pmd_t pmd_mknuma(pmd_t pmd) +{ +	pmdval_t val = pmd_val(pmd); + +	val &= ~_PAGE_PRESENT; +	val |= _PAGE_NUMA; + +	return __pmd(val); +} +#endif + +#ifndef pmdp_set_numa +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, +				 pmd_t *pmdp) +{ +	pmd_t pmd = *pmdp; + +	pmd = pmd_mknuma(pmd); +	set_pmd_at(mm, addr, pmdp, pmd); +	return; +} +#endif +#else +extern int pte_numa(pte_t pte); +extern int pmd_numa(pmd_t pmd); +extern pte_t pte_mknonnuma(pte_t pte); +extern pmd_t pmd_mknonnuma(pmd_t pmd); +extern pte_t pte_mknuma(pte_t pte); +extern pmd_t pmd_mknuma(pmd_t pmd); +extern void ptep_set_numa(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +extern void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp); +#endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */ +#else +static inline int pmd_numa(pmd_t pmd) +{ +	return 0; +} + +static inline int pte_numa(pte_t pte) +{ +	return 0; +} + +static inline pte_t pte_mknonnuma(pte_t pte) +{ +	return pte; +} + +static inline pmd_t pmd_mknonnuma(pmd_t pmd) +{ +	return pmd; +} + +static inline pte_t pte_mknuma(pte_t pte) +{ +	return pte; +} + +static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, +				 pte_t *ptep) +{ +	return; +} + + +static inline pmd_t pmd_mknuma(pmd_t pmd) +{ +	return pmd; +} + +static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr, +				 pmd_t *pmdp) +{ +	return ; +} +#endif /* CONFIG_NUMA_BALANCING */ + +#endif /* CONFIG_MMU */ +  #endif /* !__ASSEMBLY__ */ +#ifndef io_remap_pfn_range +#define io_remap_pfn_range remap_pfn_range +#endif +  #endif /* _ASM_GENERIC_PGTABLE_H */  | 
