|
@@ -87,6 +87,11 @@
|
|
|
#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */
|
|
|
#define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */
|
|
|
|
|
|
+#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
|
|
|
+#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
|
|
|
+#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56)
|
|
|
+#define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57)
|
|
|
+
|
|
|
/*
|
|
|
* To be used in assembly code with the upper page attributes.
|
|
|
*/
|
|
@@ -196,6 +201,61 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
|
|
#define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT))
|
|
|
#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
|
|
|
|
|
|
+#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF)
|
|
|
+
|
|
|
+#define __HAVE_ARCH_PMD_WRITE
|
|
|
+#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY))
|
|
|
+
|
|
|
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
|
+#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
|
|
|
+#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
|
|
|
+#endif
|
|
|
+
|
|
|
+#define PMD_BIT_FUNC(fn,op) \
|
|
|
+static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
|
|
|
+
|
|
|
+PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY);
|
|
|
+PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
|
|
|
+PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING);
|
|
|
+PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY);
|
|
|
+PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY);
|
|
|
+PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
|
|
|
+
|
|
|
+#define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
|
|
|
+
|
|
|
+#define pmd_pfn(pmd) (((pmd_val(pmd) & PMD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
|
|
|
+#define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
|
|
|
+#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
|
|
|
+
|
|
|
+/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
|
|
|
+#define pmd_mknotpresent(pmd) (__pmd(0))
|
|
|
+
|
|
|
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
|
|
+{
|
|
|
+ const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY |
|
|
|
+ PMD_SECT_VALID | PMD_SECT_NONE;
|
|
|
+ pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
|
|
+ pmd_t *pmdp, pmd_t pmd)
|
|
|
+{
|
|
|
+ BUG_ON(addr >= TASK_SIZE);
|
|
|
+
|
|
|
+ /* create a faulting entry if PROT_NONE protected */
|
|
|
+ if (pmd_val(pmd) & PMD_SECT_NONE)
|
|
|
+ pmd_val(pmd) &= ~PMD_SECT_VALID;
|
|
|
+
|
|
|
+ *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG);
|
|
|
+ flush_pmd_entry(pmdp);
|
|
|
+}
|
|
|
+
|
|
|
+static inline int has_transparent_hugepage(void)
|
|
|
+{
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
|
|
#endif /* _ASM_PGTABLE_3LEVEL_H */
|