From 5f135711ba99240f24b0f3fb3571159c02d97129 Mon Sep 17 00:00:00 2001 From: Pengfei Li Date: Mon, 14 Jul 2025 16:02:10 +0800 Subject: [PATCH] ANDROID: vendor_hook: Added hook for memory allocation tuning The following hooks are added for memory allocation tuning: android_vh_mm_customize_ac - In __alloc_pages(), this hook provides the ability to modify alloc_context and alloc_flags to accommodate processes of different importance. android_vh_mm_customize_rmqueue - In rmqueue, this hook provides the ability to modify alloc_flags and migratetype, which will be used by vendors to customize alloc_flags and migratetype to speed up memory allocation. android_vh_mm_customize_suitable_zone - For some specific gfp_mask and order requests, this hook is used to skip zones that should not be allocated, and for some critical processes, the wmark limit is skipped and jumps to try_this_zone for allocation to prevent it from being stuck. android_vh_mm_customize_zone_max_order - This hook is used to limit the maximum order allowed for special zone. It reduces a lot of unnecessary repeated merges and splits (because large orders are rarely allocated). android_vh_mm_customize_zone_pageset - This hook allows vendors to customize the high and batch of pagesets. Bug: 431730501 Change-Id: I65d6b2cd63688291e6360597bc2a4157fa228df7 Signed-off-by: Pengfei Li --- drivers/android/vendor_hooks.c | 5 +++++ include/trace/hooks/mm.h | 19 +++++++++++++++++++ mm/page_alloc.c | 25 ++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 00ffd7ed2ffc..6a107980ac45 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -682,3 +682,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_folio_remove_rmap_ptes); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_pageset_update); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_xhci_full_reset_on_remove); EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mempool_alloc_skip_wait); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_ac); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_rmqueue); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_suitable_zone); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_zone_max_order); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_mm_customize_zone_pageset); diff --git a/include/trace/hooks/mm.h b/include/trace/hooks/mm.h index 8087138ba33c..c692582c5f77 100644 --- a/include/trace/hooks/mm.h +++ b/include/trace/hooks/mm.h @@ -615,6 +615,25 @@ DECLARE_HOOK(android_vh_pageset_update, DECLARE_HOOK(android_vh_mempool_alloc_skip_wait, TP_PROTO(gfp_t *gfp_flags, bool *skip_wait), TP_ARGS(gfp_flags, skip_wait)); +DECLARE_HOOK(android_vh_mm_customize_ac, + TP_PROTO(gfp_t gfp, unsigned int order, struct zonelist **zonelist, + struct zoneref **preferred_zoneref, enum zone_type *highest_zoneidx, + unsigned int *alloc_flags), + TP_ARGS(gfp, order, zonelist, preferred_zoneref, highest_zoneidx, alloc_flags)); +DECLARE_HOOK(android_vh_mm_customize_rmqueue, + TP_PROTO(struct zone *zone, unsigned int order, unsigned int *alloc_flags, + int *migratetype), + TP_ARGS(zone, order, alloc_flags, migratetype)); +DECLARE_HOOK(android_vh_mm_customize_suitable_zone, + TP_PROTO(struct zone *zone, gfp_t gfp, int order, enum zone_type highest_zoneidx, + bool *use_this_zone, bool *suitable), + TP_ARGS(zone, gfp, order, highest_zoneidx, use_this_zone, suitable)); +DECLARE_HOOK(android_vh_mm_customize_zone_max_order, + TP_PROTO(struct zone *zone, int *max_order), + TP_ARGS(zone, max_order)); +DECLARE_HOOK(android_vh_mm_customize_zone_pageset, + TP_PROTO(struct zone *zone, int *new_high, int *new_batch), + TP_ARGS(zone, new_high, new_batch)); #endif /* _TRACE_HOOK_MM_H */ /* This part must be outside protection */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d1ecd3793e40..395f3674c8e4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -869,7 +869,10 @@ buddy_merge_likely(unsigned long pfn, unsigned long buddy_pfn, static int zone_max_order(struct zone *zone) { - return zone->order && zone_idx(zone) == ZONE_NOMERGE ? zone->order : MAX_ORDER; + int max_order = zone->order && zone_idx(zone) == ZONE_NOMERGE ? zone->order : MAX_ORDER; + + trace_android_vh_mm_customize_zone_max_order(zone, &max_order); + return max_order; } /* @@ -3087,6 +3090,8 @@ struct page *rmqueue(struct zone *preferred_zone, */ WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1)); + trace_android_vh_mm_customize_rmqueue(zone, order, &alloc_flags, &migratetype); + if (likely(pcp_allowed_order(order))) { page = rmqueue_pcplist(preferred_zone, zone, order, migratetype, alloc_flags); @@ -3546,12 +3551,25 @@ retry: z = ac->preferred_zoneref; for_next_zone_zonelist_nodemask(zone, z, ac->highest_zoneidx, ac->nodemask) { + bool use_this_zone = false; + bool suitable = true; struct page *page; unsigned long mark; if (!zone_is_suitable(zone, order)) continue; + trace_android_vh_mm_customize_suitable_zone(zone, gfp_mask, order, ac->highest_zoneidx, + &use_this_zone, &suitable); + if (!suitable) + continue; + + if (use_this_zone) + goto try_this_zone; + + /* + * This hook is deprecated by trace_android_vh_mm_customize_suitable_zone. + */ trace_android_vh_should_skip_zone(zone, gfp_mask, order, ac->migratetype, &should_skip_zone); if (should_skip_zone) @@ -4993,6 +5011,9 @@ struct page *__alloc_pages(gfp_t gfp, unsigned int order, int preferred_nid, &alloc_gfp, &alloc_flags)) return NULL; + trace_android_vh_mm_customize_ac(gfp, order, &ac.zonelist, &ac.preferred_zoneref, + &ac.highest_zoneidx, &alloc_flags); + trace_android_rvh_try_alloc_pages_gfp(&page, order, gfp, gfp_zone(gfp)); if (page) goto out; @@ -5953,6 +5974,8 @@ static void zone_set_pageset_high_and_batch(struct zone *zone, int cpu_online) zone->pageset_batch == new_batch) return; + trace_android_vh_mm_customize_zone_pageset(zone, &new_high, &new_batch); + zone->pageset_high = new_high; zone->pageset_batch = new_batch;