aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/pgtable-3level.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include/asm/pgtable-3level.h')
-rw-r--r--arch/arm/include/asm/pgtable-3level.h49
1 files changed, 30 insertions, 19 deletions
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 85c60adc8b60..06e0bc0f8b00 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -79,18 +79,19 @@
79#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */ 79#define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Present */
80#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ 80#define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
81#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ 81#define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */
82#define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */
83#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ 82#define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */
84#define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ 83#define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */
85#define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ 84#define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */
86#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ 85#define L_PTE_DIRTY (_AT(pteval_t, 1) << 55)
87#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ 86#define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56)
88#define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */ 87#define L_PTE_NONE (_AT(pteval_t, 1) << 57) /* PROT_NONE */
88#define L_PTE_RDONLY (_AT(pteval_t, 1) << 58) /* READ ONLY */
89 89
90#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0) 90#define L_PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
91#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) 91#define L_PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55)
92#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56) 92#define L_PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 56)
93#define PMD_SECT_NONE (_AT(pmdval_t, 1) << 57) 93#define L_PMD_SECT_NONE (_AT(pmdval_t, 1) << 57)
94#define L_PMD_SECT_RDONLY (_AT(pteval_t, 1) << 58)
94 95
95/* 96/*
96 * To be used in assembly code with the upper page attributes. 97 * To be used in assembly code with the upper page attributes.
@@ -207,27 +208,32 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
207#define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT)) 208#define pte_huge(pte) (pte_val(pte) && !(pte_val(pte) & PTE_TABLE_BIT))
208#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT)) 209#define pte_mkhuge(pte) (__pte(pte_val(pte) & ~PTE_TABLE_BIT))
209 210
210#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) 211#define pmd_isset(pmd, val) ((u32)(val) == (val) ? pmd_val(pmd) & (val) \
212 : !!(pmd_val(pmd) & (val)))
213#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val)))
214
215#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF))
211 216
212#define __HAVE_ARCH_PMD_WRITE 217#define __HAVE_ARCH_PMD_WRITE
213#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) 218#define pmd_write(pmd) (pmd_isclear((pmd), L_PMD_SECT_RDONLY))
219#define pmd_dirty(pmd) (pmd_isset((pmd), L_PMD_SECT_DIRTY))
214 220
215#define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd)) 221#define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd))
216#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd)) 222#define pmd_thp_or_huge(pmd) (pmd_huge(pmd) || pmd_trans_huge(pmd))
217 223
218#ifdef CONFIG_TRANSPARENT_HUGEPAGE 224#ifdef CONFIG_TRANSPARENT_HUGEPAGE
219#define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) 225#define pmd_trans_huge(pmd) (pmd_val(pmd) && !pmd_table(pmd))
220#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) 226#define pmd_trans_splitting(pmd) (pmd_isset((pmd), L_PMD_SECT_SPLITTING))
221#endif 227#endif
222 228
223#define PMD_BIT_FUNC(fn,op) \ 229#define PMD_BIT_FUNC(fn,op) \
224static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } 230static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; }
225 231
226PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); 232PMD_BIT_FUNC(wrprotect, |= L_PMD_SECT_RDONLY);
227PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); 233PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF);
228PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); 234PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING);
229PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); 235PMD_BIT_FUNC(mkwrite, &= ~L_PMD_SECT_RDONLY);
230PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); 236PMD_BIT_FUNC(mkdirty, |= L_PMD_SECT_DIRTY);
231PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); 237PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
232 238
233#define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) 239#define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT))
@@ -241,8 +247,8 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
241 247
242static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 248static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
243{ 249{
244 const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | PMD_SECT_RDONLY | 250 const pmdval_t mask = PMD_SECT_USER | PMD_SECT_XN | L_PMD_SECT_RDONLY |
245 PMD_SECT_VALID | PMD_SECT_NONE; 251 L_PMD_SECT_VALID | L_PMD_SECT_NONE;
246 pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); 252 pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask);
247 return pmd; 253 return pmd;
248} 254}
@@ -253,8 +259,13 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
253 BUG_ON(addr >= TASK_SIZE); 259 BUG_ON(addr >= TASK_SIZE);
254 260
255 /* create a faulting entry if PROT_NONE protected */ 261 /* create a faulting entry if PROT_NONE protected */
256 if (pmd_val(pmd) & PMD_SECT_NONE) 262 if (pmd_val(pmd) & L_PMD_SECT_NONE)
257 pmd_val(pmd) &= ~PMD_SECT_VALID; 263 pmd_val(pmd) &= ~L_PMD_SECT_VALID;
264
265 if (pmd_write(pmd) && pmd_dirty(pmd))
266 pmd_val(pmd) &= ~PMD_SECT_AP2;
267 else
268 pmd_val(pmd) |= PMD_SECT_AP2;
258 269
259 *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG); 270 *pmdp = __pmd(pmd_val(pmd) | PMD_SECT_nG);
260 flush_pmd_entry(pmdp); 271 flush_pmd_entry(pmdp);