1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _LINUX_PGALLOC_TRACK_H 3 #define _LINUX_PGALLOC_TRACK_H 4 5 #include <linux/mm.h> 6 #include <linux/pgtable.h> 7 8 #if defined(CONFIG_MMU) 9 static inline p4d_t *p4d_alloc_track(struct mm_struct *mm, pgd_t *pgd, 10 unsigned long address, 11 pgtbl_mod_mask *mod_mask) 12 { 13 if (unlikely(pgd_none(*pgd))) { 14 if (__p4d_alloc(mm, pgd, address)) 15 return NULL; 16 *mod_mask |= PGTBL_PGD_MODIFIED; 17 } 18 19 return p4d_offset(pgd, address); 20 } 21 22 static inline pud_t *pud_alloc_track(struct mm_struct *mm, p4d_t *p4d, 23 unsigned long address, 24 pgtbl_mod_mask *mod_mask) 25 { 26 if (unlikely(p4d_none(*p4d))) { 27 if (__pud_alloc(mm, p4d, address)) 28 return NULL; 29 *mod_mask |= PGTBL_P4D_MODIFIED; 30 } 31 32 return pud_offset(p4d, address); 33 } 34 35 static inline pmd_t *pmd_alloc_track(struct mm_struct *mm, pud_t *pud, 36 unsigned long address, 37 pgtbl_mod_mask *mod_mask) 38 { 39 if (unlikely(pud_none(*pud))) { 40 if (__pmd_alloc(mm, pud, address)) 41 return NULL; 42 *mod_mask |= PGTBL_PUD_MODIFIED; 43 } 44 45 return pmd_offset(pud, address); 46 } 47 #endif /* CONFIG_MMU */ 48 49 #define pte_alloc_kernel_track(pmd, address, mask) \ 50 ((unlikely(pmd_none(*(pmd))) && \ 51 (__pte_alloc_kernel(pmd) || ({*(mask)|=PGTBL_PMD_MODIFIED;0;})))?\ 52 NULL: pte_offset_kernel(pmd, address)) 53 54 #endif /* _LINUX_PGALLOC_TRACK_H */ 55