diff options
Diffstat (limited to 'arch/arm/include/asm/pgtable-3level.h')
-rw-r--r-- | arch/arm/include/asm/pgtable-3level.h | 49 |
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) \ |
224 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } | 230 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } |
225 | 231 | ||
226 | PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); | 232 | PMD_BIT_FUNC(wrprotect, |= L_PMD_SECT_RDONLY); |
227 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); | 233 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); |
228 | PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); | 234 | PMD_BIT_FUNC(mksplitting, |= L_PMD_SECT_SPLITTING); |
229 | PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); | 235 | PMD_BIT_FUNC(mkwrite, &= ~L_PMD_SECT_RDONLY); |
230 | PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); | 236 | PMD_BIT_FUNC(mkdirty, |= L_PMD_SECT_DIRTY); |
231 | PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); | 237 | PMD_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 | ||
242 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | 248 | static 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); |