|
@@ -8,6 +8,7 @@
|
|
|
#ifndef _ASM_PGTABLE_H
|
|
|
#define _ASM_PGTABLE_H
|
|
|
|
|
|
+#include <linux/mmzone.h>
|
|
|
#ifdef CONFIG_32BIT
|
|
|
#include <asm/pgtable-32.h>
|
|
|
#endif
|
|
@@ -94,7 +95,12 @@ extern void paging_init(void);
|
|
|
* and a page entry and page directory to the page they refer to.
|
|
|
*/
|
|
|
#define pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd))
|
|
|
-#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
|
|
|
+
|
|
|
+#define __pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
|
|
|
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
|
|
|
+#define pmd_page(pmd) __pmd_page(pmd)
|
|
|
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
|
|
+
|
|
|
#define pmd_page_vaddr(pmd) pmd_val(pmd)
|
|
|
|
|
|
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
|
|
@@ -374,6 +380,14 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
|
|
|
__update_cache(vma, address, pte);
|
|
|
}
|
|
|
|
|
|
+static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
|
|
|
+ unsigned long address, pmd_t *pmdp)
|
|
|
+{
|
|
|
+ pte_t pte = *(pte_t *)pmdp;
|
|
|
+
|
|
|
+ __update_tlb(vma, address, pte);
|
|
|
+}
|
|
|
+
|
|
|
#define kern_addr_valid(addr) (1)
|
|
|
|
|
|
#ifdef CONFIG_64BIT_PHYS_ADDR
|
|
@@ -393,6 +407,157 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
|
|
|
remap_pfn_range(vma, vaddr, pfn, size, prot)
|
|
|
#endif
|
|
|
|
|
|
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
|
+
|
|
|
+extern int has_transparent_hugepage(void);
|
|
|
+
|
|
|
+static inline int pmd_trans_huge(pmd_t pmd)
|
|
|
+{
|
|
|
+ return !!(pmd_val(pmd) & _PAGE_HUGE);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) |= _PAGE_HUGE;
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int pmd_trans_splitting(pmd_t pmd)
|
|
|
+{
|
|
|
+ return !!(pmd_val(pmd) & _PAGE_SPLITTING);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mksplitting(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) |= _PAGE_SPLITTING;
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
|
+ pmd_t *pmdp, pmd_t pmd);
|
|
|
+
|
|
|
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
|
|
|
+/* Extern to avoid header file madness */
|
|
|
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
|
|
|
+ unsigned long address,
|
|
|
+ pmd_t *pmdp);
|
|
|
+
|
|
|
+#define __HAVE_ARCH_PMD_WRITE
|
|
|
+static inline int pmd_write(pmd_t pmd)
|
|
|
+{
|
|
|
+ return !!(pmd_val(pmd) & _PAGE_WRITE);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) |= _PAGE_WRITE;
|
|
|
+ if (pmd_val(pmd) & _PAGE_MODIFIED)
|
|
|
+ pmd_val(pmd) |= _PAGE_SILENT_WRITE;
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int pmd_dirty(pmd_t pmd)
|
|
|
+{
|
|
|
+ return !!(pmd_val(pmd) & _PAGE_MODIFIED);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkclean(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) |= _PAGE_MODIFIED;
|
|
|
+ if (pmd_val(pmd) & _PAGE_WRITE)
|
|
|
+ pmd_val(pmd) |= _PAGE_SILENT_WRITE;
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int pmd_young(pmd_t pmd)
|
|
|
+{
|
|
|
+ return !!(pmd_val(pmd) & _PAGE_ACCESSED);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkold(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) |= _PAGE_ACCESSED;
|
|
|
+
|
|
|
+ if (cpu_has_rixi) {
|
|
|
+ if (!(pmd_val(pmd) & _PAGE_NO_READ))
|
|
|
+ pmd_val(pmd) |= _PAGE_SILENT_READ;
|
|
|
+ } else {
|
|
|
+ if (pmd_val(pmd) & _PAGE_READ)
|
|
|
+ pmd_val(pmd) |= _PAGE_SILENT_READ;
|
|
|
+ }
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+/* Extern to avoid header file madness */
|
|
|
+extern pmd_t mk_pmd(struct page *page, pgprot_t prot);
|
|
|
+
|
|
|
+static inline unsigned long pmd_pfn(pmd_t pmd)
|
|
|
+{
|
|
|
+ return pmd_val(pmd) >> _PFN_SHIFT;
|
|
|
+}
|
|
|
+
|
|
|
+static inline struct page *pmd_page(pmd_t pmd)
|
|
|
+{
|
|
|
+ if (pmd_trans_huge(pmd))
|
|
|
+ return pfn_to_page(pmd_pfn(pmd));
|
|
|
+
|
|
|
+ return pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT);
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
|
|
+{
|
|
|
+ pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot);
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd_val(pmd) &= ~(_PAGE_PRESENT | _PAGE_VALID | _PAGE_DIRTY);
|
|
|
+
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * The generic version pmdp_get_and_clear uses a version of pmd_clear() with a
|
|
|
+ * different prototype.
|
|
|
+ */
|
|
|
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
|
|
|
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
|
|
|
+ unsigned long address, pmd_t *pmdp)
|
|
|
+{
|
|
|
+ pmd_t old = *pmdp;
|
|
|
+
|
|
|
+ pmd_clear(pmdp);
|
|
|
+
|
|
|
+ return old;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
|
|
+
|
|
|
#include <asm-generic/pgtable.h>
|
|
|
|
|
|
/*
|