|
@@ -135,66 +135,6 @@ static inline unsigned long pte_update(struct mm_struct *mm,
|
|
|
return old;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * We currently remove entries from the hashtable regardless of whether
|
|
|
- * the entry was young or dirty.
|
|
|
- *
|
|
|
- * We should be more intelligent about this but for the moment we override
|
|
|
- * these functions and force a tlb flush unconditionally
|
|
|
- */
|
|
|
-static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
|
|
|
- unsigned long addr, pte_t *ptep)
|
|
|
-{
|
|
|
- unsigned long old;
|
|
|
-
|
|
|
- if ((pte_val(*ptep) & (_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
|
|
|
- return 0;
|
|
|
- old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
|
|
|
- return (old & _PAGE_ACCESSED) != 0;
|
|
|
-}
|
|
|
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
|
|
|
-#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
|
|
|
-({ \
|
|
|
- int __r; \
|
|
|
- __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
|
|
|
- __r; \
|
|
|
-})
|
|
|
-
|
|
|
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
|
|
|
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
|
|
- pte_t *ptep)
|
|
|
-{
|
|
|
-
|
|
|
- if ((pte_val(*ptep) & _PAGE_WRITE) == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
|
|
|
- unsigned long addr, pte_t *ptep)
|
|
|
-{
|
|
|
- if ((pte_val(*ptep) & _PAGE_WRITE) == 0)
|
|
|
- return;
|
|
|
-
|
|
|
- pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1);
|
|
|
-}
|
|
|
-
|
|
|
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
|
|
|
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
|
|
|
- unsigned long addr, pte_t *ptep)
|
|
|
-{
|
|
|
- unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
|
|
|
- return __pte(old);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
|
|
|
- pte_t * ptep)
|
|
|
-{
|
|
|
- pte_update(mm, addr, ptep, ~0UL, 0, 0);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/* Set the dirty and/or accessed bits atomically in a linux PTE, this
|
|
|
* function doesn't need to flush the hash entry
|
|
|
*/
|
|
@@ -237,112 +177,7 @@ static inline unsigned long pgd_page_vaddr(pgd_t pgd)
|
|
|
|
|
|
|
|
|
/* Generic accessors to PTE bits */
|
|
|
-static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_WRITE);}
|
|
|
-static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); }
|
|
|
-static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); }
|
|
|
-static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); }
|
|
|
static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~H_PTE_NONE_MASK) == 0; }
|
|
|
-static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
|
|
|
-
|
|
|
-#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
|
|
|
-static inline bool pte_soft_dirty(pte_t pte)
|
|
|
-{
|
|
|
- return !!(pte_val(pte) & _PAGE_SOFT_DIRTY);
|
|
|
-}
|
|
|
-static inline pte_t pte_mksoft_dirty(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) | _PAGE_SOFT_DIRTY);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_clear_soft_dirty(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) & ~_PAGE_SOFT_DIRTY);
|
|
|
-}
|
|
|
-#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
|
|
|
-
|
|
|
-#ifdef CONFIG_NUMA_BALANCING
|
|
|
-/*
|
|
|
- * These work without NUMA balancing but the kernel does not care. See the
|
|
|
- * comment in include/asm-generic/pgtable.h . On powerpc, this will only
|
|
|
- * work for user pages and always return true for kernel pages.
|
|
|
- */
|
|
|
-static inline int pte_protnone(pte_t pte)
|
|
|
-{
|
|
|
- return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PRIVILEGED)) ==
|
|
|
- (_PAGE_PRESENT | _PAGE_PRIVILEGED);
|
|
|
-}
|
|
|
-#endif /* CONFIG_NUMA_BALANCING */
|
|
|
-
|
|
|
-static inline int pte_present(pte_t pte)
|
|
|
-{
|
|
|
- return !!(pte_val(pte) & _PAGE_PRESENT);
|
|
|
-}
|
|
|
-
|
|
|
-/* Conversion functions: convert a page and protection to a page entry,
|
|
|
- * and a page entry and page directory to the page they refer to.
|
|
|
- *
|
|
|
- * Even if PTEs can be unsigned long long, a PFN is always an unsigned
|
|
|
- * long for now.
|
|
|
- */
|
|
|
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
|
|
|
-{
|
|
|
- return __pte((((pte_basic_t)(pfn) << PAGE_SHIFT) & PTE_RPN_MASK) |
|
|
|
- pgprot_val(pgprot));
|
|
|
-}
|
|
|
-
|
|
|
-static inline unsigned long pte_pfn(pte_t pte)
|
|
|
-{
|
|
|
- return (pte_val(pte) & PTE_RPN_MASK) >> PAGE_SHIFT;
|
|
|
-}
|
|
|
-
|
|
|
-/* Generic modifiers for PTE bits */
|
|
|
-static inline pte_t pte_wrprotect(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) & ~_PAGE_WRITE);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkclean(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) & ~_PAGE_DIRTY);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkold(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) & ~_PAGE_ACCESSED);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkwrite(pte_t pte)
|
|
|
-{
|
|
|
- /*
|
|
|
- * write implies read, hence set both
|
|
|
- */
|
|
|
- return __pte(pte_val(pte) | _PAGE_RW);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkdirty(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) | _PAGE_DIRTY | _PAGE_SOFT_DIRTY);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkyoung(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) | _PAGE_ACCESSED);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkspecial(pte_t pte)
|
|
|
-{
|
|
|
- return __pte(pte_val(pte) | _PAGE_SPECIAL);
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_mkhuge(pte_t pte)
|
|
|
-{
|
|
|
- return pte;
|
|
|
-}
|
|
|
-
|
|
|
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|
|
-{
|
|
|
- return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
|
|
|
-}
|
|
|
|
|
|
/* This low level function performs the actual PTE insertion
|
|
|
* Setting the PTE depends on the MMU type and other factors. It's
|
|
@@ -359,46 +194,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
|
|
*ptep = pte;
|
|
|
}
|
|
|
|
|
|
-#define _PAGE_CACHE_CTL (_PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)
|
|
|
-
|
|
|
-#define pgprot_noncached pgprot_noncached
|
|
|
-static inline pgprot_t pgprot_noncached(pgprot_t prot)
|
|
|
-{
|
|
|
- return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
|
|
|
- _PAGE_NON_IDEMPOTENT);
|
|
|
-}
|
|
|
-
|
|
|
-#define pgprot_noncached_wc pgprot_noncached_wc
|
|
|
-static inline pgprot_t pgprot_noncached_wc(pgprot_t prot)
|
|
|
-{
|
|
|
- return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
|
|
|
- _PAGE_TOLERANT);
|
|
|
-}
|
|
|
-
|
|
|
-#define pgprot_cached pgprot_cached
|
|
|
-static inline pgprot_t pgprot_cached(pgprot_t prot)
|
|
|
-{
|
|
|
- return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL));
|
|
|
-}
|
|
|
-
|
|
|
-#define pgprot_writecombine pgprot_writecombine
|
|
|
-static inline pgprot_t pgprot_writecombine(pgprot_t prot)
|
|
|
-{
|
|
|
- return pgprot_noncached_wc(prot);
|
|
|
-}
|
|
|
-/*
|
|
|
- * check a pte mapping have cache inhibited property
|
|
|
- */
|
|
|
-static inline bool pte_ci(pte_t pte)
|
|
|
-{
|
|
|
- unsigned long pte_v = pte_val(pte);
|
|
|
-
|
|
|
- if (((pte_v & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) ||
|
|
|
- ((pte_v & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT))
|
|
|
- return true;
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
|
extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
|
|
|
pmd_t *pmdp, unsigned long old_pmd);
|