diff options
| author | Steve Capper <steve.capper@linaro.org> | 2014-02-25 05:02:13 -0500 |
|---|---|---|
| committer | Catalin Marinas <catalin.marinas@arm.com> | 2014-03-14 14:02:10 -0400 |
| commit | 9c7e535fcc1725fc2e2d4f0d9dd14137f0243e23 (patch) | |
| tree | 59598b3e9733e62d6ec8e10270dc7b7664916700 | |
| parent | c209f79940ac0c75ae8d2f503a2b9d86255e266c (diff) | |
arm64: mm: Route pmd thp functions through pte equivalents
Rather than have separate hugetlb and transparent huge page pmd
manipulation functions, re-wire our thp functions to simply call the
pte equivalents.
This allows THP to take advantage of the new PTE_WRITE logic introduced
in:
c2c93e5 arm64: mm: Introduce PTE_WRITE
To represent splitting THPs we use the PTE_SPECIAL bit as this is not
used for pmds.
Signed-off-by: Steve Capper <steve.capper@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
| -rw-r--r-- | arch/arm64/include/asm/pgtable.h | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 72c9ac38cdd9..ae10350f75ec 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
| @@ -227,36 +227,36 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 227 | 227 | ||
| 228 | #define __HAVE_ARCH_PTE_SPECIAL | 228 | #define __HAVE_ARCH_PTE_SPECIAL |
| 229 | 229 | ||
| 230 | /* | 230 | static inline pte_t pmd_pte(pmd_t pmd) |
| 231 | * Software PMD bits for THP | 231 | { |
| 232 | */ | 232 | return __pte(pmd_val(pmd)); |
| 233 | } | ||
| 233 | 234 | ||
| 234 | #define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) | 235 | static inline pmd_t pte_pmd(pte_t pte) |
| 235 | #define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57) | 236 | { |
| 237 | return __pmd(pte_val(pte)); | ||
| 238 | } | ||
| 236 | 239 | ||
| 237 | /* | 240 | /* |
| 238 | * THP definitions. | 241 | * THP definitions. |
| 239 | */ | 242 | */ |
| 240 | #define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) | ||
| 241 | |||
| 242 | #define __HAVE_ARCH_PMD_WRITE | ||
| 243 | #define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) | ||
| 244 | 243 | ||
| 245 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 244 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 246 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) | 245 | #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) |
| 247 | #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) | 246 | #define pmd_trans_splitting(pmd) pte_special(pmd_pte(pmd)) |
| 248 | #endif | 247 | #endif |
| 249 | 248 | ||
| 250 | #define PMD_BIT_FUNC(fn,op) \ | 249 | #define pmd_young(pmd) pte_young(pmd_pte(pmd)) |
| 251 | static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } | 250 | #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd))) |
| 251 | #define pmd_mksplitting(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd))) | ||
| 252 | #define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd))) | ||
| 253 | #define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) | ||
| 254 | #define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) | ||
| 255 | #define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) | ||
| 256 | #define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) &= ~PMD_TYPE_MASK)) | ||
| 252 | 257 | ||
| 253 | PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); | 258 | #define __HAVE_ARCH_PMD_WRITE |
| 254 | PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); | 259 | #define pmd_write(pmd) pte_write(pmd_pte(pmd)) |
| 255 | PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); | ||
| 256 | PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); | ||
| 257 | PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); | ||
| 258 | PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); | ||
| 259 | PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); | ||
| 260 | 260 | ||
| 261 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) | 261 | #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) |
| 262 | 262 | ||
| @@ -266,15 +266,6 @@ PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); | |||
| 266 | 266 | ||
| 267 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | 267 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) |
| 268 | 268 | ||
| 269 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
| 270 | { | ||
| 271 | const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN | | ||
| 272 | PMD_SECT_RDONLY | PMD_SECT_PROT_NONE | | ||
| 273 | PMD_SECT_VALID; | ||
| 274 | pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); | ||
| 275 | return pmd; | ||
| 276 | } | ||
| 277 | |||
| 278 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) | 269 | #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) |
| 279 | 270 | ||
| 280 | static inline int has_transparent_hugepage(void) | 271 | static inline int has_transparent_hugepage(void) |
| @@ -383,6 +374,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
| 383 | return pte; | 374 | return pte; |
| 384 | } | 375 | } |
| 385 | 376 | ||
| 377 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
| 378 | { | ||
| 379 | return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); | ||
| 380 | } | ||
| 381 | |||
| 386 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | 382 | extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
| 387 | extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | 383 | extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; |
| 388 | 384 | ||
