Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Steve Capper and committed by
Catalin Marinas
9c7e535f c209f799

+24 -28
+24 -28
arch/arm64/include/asm/pgtable.h
··· 227 227 228 228 #define __HAVE_ARCH_PTE_SPECIAL 229 229 230 - /* 231 - * Software PMD bits for THP 232 - */ 230 + static inline pte_t pmd_pte(pmd_t pmd) 231 + { 232 + return __pte(pmd_val(pmd)); 233 + } 233 234 234 - #define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) 235 - #define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57) 235 + static inline pmd_t pte_pmd(pte_t pte) 236 + { 237 + return __pmd(pte_val(pte)); 238 + } 236 239 237 240 /* 238 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 244 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 246 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 247 #endif 249 248 250 - #define PMD_BIT_FUNC(fn,op) \ 251 - static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } 249 + #define pmd_young(pmd) pte_young(pmd_pte(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); 254 - PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); 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); 258 + #define __HAVE_ARCH_PMD_WRITE 259 + #define pmd_write(pmd) pte_write(pmd_pte(pmd)) 260 260 261 261 #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) 262 262 ··· 265 265 #define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot) 266 266 267 267 #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) 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 268 278 269 #define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) 279 270 ··· 372 381 PTE_PROT_NONE | PTE_VALID | PTE_WRITE; 373 382 pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); 374 383 return pte; 384 + } 385 + 386 + static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 387 + { 388 + return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); 375 389 } 376 390 377 391 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];