From a2ba3d525dcf5bc8f1c9a71a5eb356010b2b36f6 Mon Sep 17 00:00:00 2001 From: Pengfei Li Date: Mon, 14 Jul 2025 21:23:05 +0800 Subject: [PATCH] ANDROID: mm: Fix incorrect call to try_to_map_unused_to_zeropage We encounter the following kernel panic in try_to_map_unused_to_zeropage(). Commit d826c844824e ported the series "mm: split underused THPs". It should have been fine, but kernel 6.6 also ported TAO (which is FROMLIST and not upstreamed, see c1ff6dcf209e and 066872d13d0c). This caused anon folios in virtual zones to also go to the newly introduced try_to_map_unused_to_zeropage() function. In commit 066872d13d0c ("FROMLIST: BACKPORT: THP shattering: the reverse of collapsing"), large folios in virtual zones are special and cannot be split. As a result, when split_huge_page_to_list() is called, the large folio in the virtual zone is shattered (it allocates order-0 pages from the non-virtual zone and copies them, and the source folio is not split). So the fix is to add the RMP_USE_SHARED_ZEROPAGE flag only when the anon folio of the non-virtual zone is split. Since TAO has not yet entered the upstream, this patch is added with ANDROID tag. [ 224.266820] page:000000003b799096 refcount:0 mapcount:0 mapping:0000000000000000 index:0x7fa0696 pfn:0xf9406 [ 224.269172] flags: 0x0(zone=0) [ 224.269961] page_type: 0xffffffff() [ 224.270812] raw: 0000000000000000 fffffffe02e50308 fffffffe02e50148 0000000000000000 [ 224.271218] raw: 0000000007fa0696 0000000000000000 00000000ffffffff 0000000000000000 [ 224.271632] page dumped because: VM_BUG_ON_PAGE(!PageAnon(page)) [ 224.272910] ------------[ cut here ]------------ [ 224.273350] kernel BUG at mm/migrate.c:195! [ 224.275375] Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP [ 224.276596] Modules linked in: [ 224.279981] CPU: 2 PID: 197 Comm: stress-ng-vm Not tainted 6.6.92-g615449fbacae-dirty #424 [ 224.281834] Hardware name: linux,dummy-virt (DT) [ 224.282417] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 224.283236] pc : remove_migration_pte+0x908/0x948 [ 224.285270] lr : remove_migration_pte+0x908/0x948 [ 224.286207] sp : ffffffc0807bb2f0 [ 224.286409] x29: ffffffc0807bb360 x28: 00e00000f9402bc3 x27: 0000007fff4e8000 [ 224.287271] x26: fffffffe02e50100 x25: 00000000f0000800 x24: ffffff80c6918000 [ 224.287658] x23: ffffff80c67fd740 x22: fffffffe03600300 x21: fffffffe03600300 [ 224.289112] x20: ffffff80c68ff540 x19: fffffffe02e50100 x18: ffffffd3d866c3e5 [ 224.290446] x17: 0000000000000001 x16: ffffffffffffffff x15: 0000000000000004 [ 224.290911] x14: ffffffd3d8b23d70 x13: 0000000000000003 x12: 0000000000000003 [ 224.291373] x11: 00000000ffffefff x10: c0000000ffffefff x9 : 6efccb02fbf53400 [ 224.291955] x8 : 6efccb02fbf53400 x7 : 205d323336313732 x6 : 322e34323220205b [ 224.292701] x5 : ffffffd3d90c5217 x4 : ffffffc0807bae47 x3 : 0000000000000000 [ 224.293625] x2 : 0000000000000000 x1 : ffffffc0807bb040 x0 : 0000000000000034 [ 224.295026] Call trace: [ 224.295943] remove_migration_pte+0x908/0x948 [ 224.297880] rmap_walk_anon+0x1cc/0x2b4 [ 224.298152] rmap_walk_locked+0x28/0x34 [ 224.299203] remove_migration_ptes+0x6c/0xa4 [ 224.299879] remap_page+0x48/0xe0 [ 224.300272] __split_huge_page+0xe98/0x14d4 [ 224.300787] split_huge_page_to_list+0x498/0x950 [ 224.301316] deferred_split_scan+0x2fc/0x640 [ 224.301600] do_shrink_slab+0x17c/0x520 [ 224.302139] shrink_slab+0x318/0x3d0 [ 224.302670] shrink_node+0x1dc/0x11c4 [ 224.303613] do_try_to_free_pages+0x254/0x654 [ 224.304041] try_to_free_pages+0x390/0x754 [ 224.305094] __alloc_pages_slowpath+0x6dc/0x1600 [ 224.306104] __alloc_pages+0x1ac/0x280 [ 224.306938] __folio_alloc+0x18/0x34 [ 224.307683] vma_alloc_zeroed_movable_folio+0x38/0x44 [ 224.308131] folio_prealloc+0x24/0x134 [ 224.309006] handle_mm_fault+0xb7c/0x16a0 Cc: Kalesh Singh Fixes: d826c844824e ("BACKPORT: mm: remap unused subpages to shared zeropage when splitting isolated thp") Bug: 419599659 Bug: 431730501 Change-Id: Ide6e5b2efe82f5610dd2adee723204f91f7f7312 Signed-off-by: Pengfei Li --- mm/huge_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index fe04753afd32..122f52c172c2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3340,7 +3340,7 @@ static void __split_huge_page(struct page *page, struct list_head *list, if (nr_dropped) shmem_uncharge(head->mapping->host, nr_dropped); - remap_page(folio, nr, PageAnon(head) ? RMP_USE_SHARED_ZEROPAGE : 0); + remap_page(folio, nr, (can_split && PageAnon(head)) ? RMP_USE_SHARED_ZEROPAGE : 0); for (i = 0; i < nr; i++) { struct page *subpage = folio_dst_page(folio, i);