s390/mm: Add memory allocation profiling hooks

Similar to common code changes [1] add alloc_hook() wrappers to page table
allocation functions to allow for memory allocation profiling.

If CONFIG_MEM_ALLOC_PROFILING is enabled call sites of page table
allocations are accounted, instead of e.g. only crst_table_alloc() and
page_table_alloc(). This allows for slightly better profiling data, and the
output of /proc/allocinfo is similar to other architectures.

Without alloc_hook() wrappers the output of /proc/allocinfo looks like
this:

    17096704     4174 mm/memory.c:1061 func:folio_prealloc
    17809408     4348 mm/memory.c:1063 func:folio_prealloc
           0        0 mm/memory.c:4422 func:alloc_swap_folio
           0        0 mm/memory.c:4286 func:__alloc_swap_folio
           0        0 mm/memory.c:4971 func:alloc_anon_folio
         ...
     1589248       97 arch/s390/mm/pgalloc.c:25 func:crst_table_alloc
           0        0 arch/s390/mm/pgalloc.c:124 func:page_table_alloc_pgste
     4280320     1045 arch/s390/mm/pgalloc.c:149 func:page_table_alloc

With alloc_hook() wrappers:

     1097728      268 mm/memory.c:5147 func:__do_fault
    20119552     4912 mm/memory.c:1061 func:folio_prealloc
    17534976     4281 mm/memory.c:1063 func:folio_prealloc
           0        0 mm/memory.c:4422 func:alloc_swap_folio
           0        0 mm/memory.c:4286 func:__alloc_swap_folio
      786432      192 mm/memory.c:452 func:__pte_alloc
      405504       99 mm/memory.c:464 func:__pte_alloc_kernel
     1880064      459 mm/memory.c:5525 func:do_fault_around
           0        0 mm/memory.c:6403 func:__p4d_alloc
           0        0 mm/memory.c:6426 func:__pud_alloc
     1064960       65 mm/memory.c:6450 func:__pmd_alloc
           0        0 mm/memory.c:4971 func:alloc_anon_folio
           0        0 mm/memory.c:5233 func:do_set_pmd

[1] commit 2c321f3f70 ("mm: change inlined allocation helpers to account at the call site")

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
Heiko Carstens 2025-09-23 17:34:30 +02:00 committed by Alexander Gordeev
parent 72105fc1c1
commit 088bb10e37
2 changed files with 25 additions and 17 deletions

View File

@ -19,12 +19,16 @@
#define CRST_ALLOC_ORDER 2 #define CRST_ALLOC_ORDER 2
unsigned long *crst_table_alloc(struct mm_struct *); unsigned long *crst_table_alloc_noprof(struct mm_struct *);
#define crst_table_alloc(...) alloc_hooks(crst_table_alloc_noprof(__VA_ARGS__))
void crst_table_free(struct mm_struct *, unsigned long *); void crst_table_free(struct mm_struct *, unsigned long *);
unsigned long *page_table_alloc(struct mm_struct *); unsigned long *page_table_alloc_noprof(struct mm_struct *);
struct ptdesc *page_table_alloc_pgste(struct mm_struct *mm); #define page_table_alloc(...) alloc_hooks(page_table_alloc_noprof(__VA_ARGS__))
void page_table_free(struct mm_struct *, unsigned long *); void page_table_free(struct mm_struct *, unsigned long *);
struct ptdesc *page_table_alloc_pgste_noprof(struct mm_struct *mm);
#define page_table_alloc_pgste(...) alloc_hooks(page_table_alloc_pgste_noprof(__VA_ARGS__))
void page_table_free_pgste(struct ptdesc *ptdesc); void page_table_free_pgste(struct ptdesc *ptdesc);
static inline void crst_table_init(unsigned long *crst, unsigned long entry) static inline void crst_table_init(unsigned long *crst, unsigned long entry)
@ -48,9 +52,9 @@ static inline unsigned long check_asce_limit(struct mm_struct *mm, unsigned long
return addr; return addr;
} }
static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address) static inline p4d_t *p4d_alloc_one_noprof(struct mm_struct *mm, unsigned long address)
{ {
unsigned long *table = crst_table_alloc(mm); unsigned long *table = crst_table_alloc_noprof(mm);
if (!table) if (!table)
return NULL; return NULL;
@ -59,6 +63,7 @@ static inline p4d_t *p4d_alloc_one(struct mm_struct *mm, unsigned long address)
return (p4d_t *) table; return (p4d_t *) table;
} }
#define p4d_alloc_one(...) alloc_hooks(p4d_alloc_one_noprof(__VA_ARGS__))
static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d) static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
{ {
@ -69,9 +74,9 @@ static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
crst_table_free(mm, (unsigned long *) p4d); crst_table_free(mm, (unsigned long *) p4d);
} }
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) static inline pud_t *pud_alloc_one_noprof(struct mm_struct *mm, unsigned long address)
{ {
unsigned long *table = crst_table_alloc(mm); unsigned long *table = crst_table_alloc_noprof(mm);
if (!table) if (!table)
return NULL; return NULL;
@ -80,6 +85,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
return (pud_t *) table; return (pud_t *) table;
} }
#define pud_alloc_one(...) alloc_hooks(pud_alloc_one_noprof(__VA_ARGS__))
static inline void pud_free(struct mm_struct *mm, pud_t *pud) static inline void pud_free(struct mm_struct *mm, pud_t *pud)
{ {
@ -90,9 +96,9 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
crst_table_free(mm, (unsigned long *) pud); crst_table_free(mm, (unsigned long *) pud);
} }
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) static inline pmd_t *pmd_alloc_one_noprof(struct mm_struct *mm, unsigned long vmaddr)
{ {
unsigned long *table = crst_table_alloc(mm); unsigned long *table = crst_table_alloc_noprof(mm);
if (!table) if (!table)
return NULL; return NULL;
@ -103,6 +109,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
} }
return (pmd_t *) table; return (pmd_t *) table;
} }
#define pmd_alloc_one(...) alloc_hooks(pmd_alloc_one_noprof(__VA_ARGS__))
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
{ {
@ -127,9 +134,9 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
set_pud(pud, __pud(_REGION3_ENTRY | __pa(pmd))); set_pud(pud, __pud(_REGION3_ENTRY | __pa(pmd)));
} }
static inline pgd_t *pgd_alloc(struct mm_struct *mm) static inline pgd_t *pgd_alloc_noprof(struct mm_struct *mm)
{ {
unsigned long *table = crst_table_alloc(mm); unsigned long *table = crst_table_alloc_noprof(mm);
if (!table) if (!table)
return NULL; return NULL;
@ -137,6 +144,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
return (pgd_t *) table; return (pgd_t *) table;
} }
#define pgd_alloc(...) alloc_hooks(pgd_alloc_noprof(__VA_ARGS__))
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{ {

View File

@ -14,7 +14,7 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
unsigned long *crst_table_alloc(struct mm_struct *mm) unsigned long *crst_table_alloc_noprof(struct mm_struct *mm)
{ {
gfp_t gfp = GFP_KERNEL_ACCOUNT; gfp_t gfp = GFP_KERNEL_ACCOUNT;
struct ptdesc *ptdesc; struct ptdesc *ptdesc;
@ -22,7 +22,7 @@ unsigned long *crst_table_alloc(struct mm_struct *mm)
if (mm == &init_mm) if (mm == &init_mm)
gfp &= ~__GFP_ACCOUNT; gfp &= ~__GFP_ACCOUNT;
ptdesc = pagetable_alloc(gfp, CRST_ALLOC_ORDER); ptdesc = pagetable_alloc_noprof(gfp, CRST_ALLOC_ORDER);
if (!ptdesc) if (!ptdesc)
return NULL; return NULL;
table = ptdesc_to_virt(ptdesc); table = ptdesc_to_virt(ptdesc);
@ -116,12 +116,12 @@ err_p4d:
#ifdef CONFIG_PGSTE #ifdef CONFIG_PGSTE
struct ptdesc *page_table_alloc_pgste(struct mm_struct *mm) struct ptdesc *page_table_alloc_pgste_noprof(struct mm_struct *mm)
{ {
struct ptdesc *ptdesc; struct ptdesc *ptdesc;
u64 *table; u64 *table;
ptdesc = pagetable_alloc(GFP_KERNEL_ACCOUNT, 0); ptdesc = pagetable_alloc_noprof(GFP_KERNEL_ACCOUNT, 0);
if (ptdesc) { if (ptdesc) {
table = (u64 *)ptdesc_to_virt(ptdesc); table = (u64 *)ptdesc_to_virt(ptdesc);
__arch_set_page_dat(table, 1); __arch_set_page_dat(table, 1);
@ -138,7 +138,7 @@ void page_table_free_pgste(struct ptdesc *ptdesc)
#endif /* CONFIG_PGSTE */ #endif /* CONFIG_PGSTE */
unsigned long *page_table_alloc(struct mm_struct *mm) unsigned long *page_table_alloc_noprof(struct mm_struct *mm)
{ {
gfp_t gfp = GFP_KERNEL_ACCOUNT; gfp_t gfp = GFP_KERNEL_ACCOUNT;
struct ptdesc *ptdesc; struct ptdesc *ptdesc;
@ -146,7 +146,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
if (mm == &init_mm) if (mm == &init_mm)
gfp &= ~__GFP_ACCOUNT; gfp &= ~__GFP_ACCOUNT;
ptdesc = pagetable_alloc(gfp, 0); ptdesc = pagetable_alloc_noprof(gfp, 0);
if (!ptdesc) if (!ptdesc)
return NULL; return NULL;
if (!pagetable_pte_ctor(mm, ptdesc)) { if (!pagetable_pte_ctor(mm, ptdesc)) {