From: Greg Kroah-Hartman Date: Wed, 27 Jan 2021 09:59:55 +0000 (+0100) Subject: add commit and revert to make tools happy to prevent from coming back... X-Git-Tag: v4.19.171~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6e1f8987b269c5af92f50191f9674ba9c0173fa2;p=thirdparty%2Fkernel%2Fstable-queue.git add commit and revert to make tools happy to prevent from coming back... --- diff --git a/queue-5.10/mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch b/queue-5.10/mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch new file mode 100644 index 00000000000..41c71376511 --- /dev/null +++ b/queue-5.10/mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch @@ -0,0 +1,192 @@ +From d3921cb8be29ce5668c64e23ffdaeec5f8c69399 Mon Sep 17 00:00:00 2001 +From: Mike Rapoport +Date: Sat, 23 Jan 2021 21:01:02 -0800 +Subject: mm: fix initialization of struct page for holes in memory layout + +From: Mike Rapoport + +commit d3921cb8be29ce5668c64e23ffdaeec5f8c69399 upstream. + +There could be struct pages that are not backed by actual physical +memory. This can happen when the actual memory bank is not a multiple +of SECTION_SIZE or when an architecture does not register memory holes +reserved by the firmware as memblock.memory. + +Such pages are currently initialized using init_unavailable_mem() +function that iterates through PFNs in holes in memblock.memory and if +there is a struct page corresponding to a PFN, the fields if this page +are set to default values and the page is marked as Reserved. + +init_unavailable_mem() does not take into account zone and node the page +belongs to and sets both zone and node links in struct page to zero. + +On a system that has firmware reserved holes in a zone above ZONE_DMA, +for instance in a configuration below: + + # grep -A1 E820 /proc/iomem + 7a17b000-7a216fff : Unknown E820 type + 7a217000-7bffffff : System RAM + +unset zone link in struct page will trigger + + VM_BUG_ON_PAGE(!zone_spans_pfn(page_zone(page), pfn), page); + +because there are pages in both ZONE_DMA32 and ZONE_DMA (unset zone link +in struct page) in the same pageblock. + +Update init_unavailable_mem() to use zone constraints defined by an +architecture to properly setup the zone link and use node ID of the +adjacent range in memblock.memory to set the node link. + +Link: https://lkml.kernel.org/r/20210111194017.22696-3-rppt@kernel.org +Fixes: 73a6e474cb37 ("mm: memmap_init: iterate over memblock regions rather that check each PFN") +Signed-off-by: Mike Rapoport +Reported-by: Andrea Arcangeli +Cc: Andrea Arcangeli +Cc: Baoquan He +Cc: Borislav Petkov +Cc: David Hildenbrand +Cc: "H. Peter Anvin" +Cc: Ingo Molnar +Cc: Mel Gorman +Cc: Michal Hocko +Cc: Qian Cai +Cc: Thomas Gleixner +Cc: Vlastimil Babka +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 84 +++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 50 insertions(+), 34 deletions(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7003,23 +7003,26 @@ void __init free_area_init_memoryless_no + * Initialize all valid struct pages in the range [spfn, epfn) and mark them + * PageReserved(). Return the number of struct pages that were initialized. + */ +-static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn) ++static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn, ++ int zone, int nid) + { +- unsigned long pfn; ++ unsigned long pfn, zone_spfn, zone_epfn; + u64 pgcnt = 0; + ++ zone_spfn = arch_zone_lowest_possible_pfn[zone]; ++ zone_epfn = arch_zone_highest_possible_pfn[zone]; ++ ++ spfn = clamp(spfn, zone_spfn, zone_epfn); ++ epfn = clamp(epfn, zone_spfn, zone_epfn); ++ + for (pfn = spfn; pfn < epfn; pfn++) { + if (!pfn_valid(ALIGN_DOWN(pfn, pageblock_nr_pages))) { + pfn = ALIGN_DOWN(pfn, pageblock_nr_pages) + + pageblock_nr_pages - 1; + continue; + } +- /* +- * Use a fake node/zone (0) for now. Some of these pages +- * (in memblock.reserved but not in memblock.memory) will +- * get re-initialized via reserve_bootmem_region() later. +- */ +- __init_single_page(pfn_to_page(pfn), pfn, 0, 0); ++ ++ __init_single_page(pfn_to_page(pfn), pfn, zone, nid); + __SetPageReserved(pfn_to_page(pfn)); + pgcnt++; + } +@@ -7028,51 +7031,64 @@ static u64 __init init_unavailable_range + } + + /* +- * Only struct pages that are backed by physical memory are zeroed and +- * initialized by going through __init_single_page(). But, there are some +- * struct pages which are reserved in memblock allocator and their fields +- * may be accessed (for example page_to_pfn() on some configuration accesses +- * flags). We must explicitly initialize those struct pages. ++ * Only struct pages that correspond to ranges defined by memblock.memory ++ * are zeroed and initialized by going through __init_single_page() during ++ * memmap_init(). + * +- * This function also addresses a similar issue where struct pages are left +- * uninitialized because the physical address range is not covered by +- * memblock.memory or memblock.reserved. That could happen when memblock +- * layout is manually configured via memmap=, or when the highest physical +- * address (max_pfn) does not end on a section boundary. ++ * But, there could be struct pages that correspond to holes in ++ * memblock.memory. This can happen because of the following reasons: ++ * - phyiscal memory bank size is not necessarily the exact multiple of the ++ * arbitrary section size ++ * - early reserved memory may not be listed in memblock.memory ++ * - memory layouts defined with memmap= kernel parameter may not align ++ * nicely with memmap sections ++ * ++ * Explicitly initialize those struct pages so that: ++ * - PG_Reserved is set ++ * - zone link is set accorging to the architecture constrains ++ * - node is set to node id of the next populated region except for the ++ * trailing hole where last node id is used + */ +-static void __init init_unavailable_mem(void) ++static void __init init_zone_unavailable_mem(int zone) + { +- phys_addr_t start, end; +- u64 i, pgcnt; +- phys_addr_t next = 0; ++ unsigned long start, end; ++ int i, nid; ++ u64 pgcnt; ++ unsigned long next = 0; + + /* +- * Loop through unavailable ranges not covered by memblock.memory. ++ * Loop through holes in memblock.memory and initialize struct ++ * pages corresponding to these holes + */ + pgcnt = 0; +- for_each_mem_range(i, &start, &end) { ++ for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid) { + if (next < start) +- pgcnt += init_unavailable_range(PFN_DOWN(next), +- PFN_UP(start)); ++ pgcnt += init_unavailable_range(next, start, zone, nid); + next = end; + } + + /* +- * Early sections always have a fully populated memmap for the whole +- * section - see pfn_valid(). If the last section has holes at the +- * end and that section is marked "online", the memmap will be +- * considered initialized. Make sure that memmap has a well defined +- * state. ++ * Last section may surpass the actual end of memory (e.g. we can ++ * have 1Gb section and 512Mb of RAM pouplated). ++ * Make sure that memmap has a well defined state in this case. + */ +- pgcnt += init_unavailable_range(PFN_DOWN(next), +- round_up(max_pfn, PAGES_PER_SECTION)); ++ end = round_up(max_pfn, PAGES_PER_SECTION); ++ pgcnt += init_unavailable_range(next, end, zone, nid); + + /* + * Struct pages that do not have backing memory. This could be because + * firmware is using some of this memory, or for some other reasons. + */ + if (pgcnt) +- pr_info("Zeroed struct page in unavailable ranges: %lld pages", pgcnt); ++ pr_info("Zone %s: zeroed struct page in unavailable ranges: %lld pages", zone_names[zone], pgcnt); ++} ++ ++static void __init init_unavailable_mem(void) ++{ ++ int zone; ++ ++ for (zone = 0; zone < ZONE_MOVABLE; zone++) ++ init_zone_unavailable_mem(zone); + } + #else + static inline void __init init_unavailable_mem(void) diff --git a/queue-5.10/revert-mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch b/queue-5.10/revert-mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch new file mode 100644 index 00000000000..43407ff3612 --- /dev/null +++ b/queue-5.10/revert-mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch @@ -0,0 +1,160 @@ +From 377bf660d07a47269510435d11f3b65d53edca20 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Tue, 26 Jan 2021 10:39:46 -0800 +Subject: Revert "mm: fix initialization of struct page for holes in memory layout" + +From: Linus Torvalds + +commit 377bf660d07a47269510435d11f3b65d53edca20 upstream. + +This reverts commit d3921cb8be29ce5668c64e23ffdaeec5f8c69399. + +Chris Wilson reports that it causes boot problems: + + "We have half a dozen or so different machines in CI that are silently + failing to boot, that we believe is bisected to this patch" + +and the CI team confirmed that a revert fixed the issues. + +The cause is unknown for now, so let's revert it. + +Link: https://lore.kernel.org/lkml/161160687463.28991.354987542182281928@build.alporthouse.com/ +Reported-and-tested-by: Chris Wilson +Acked-by: Mike Rapoport +Cc: Andrea Arcangeli +Cc: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 84 ++++++++++++++++++++++---------------------------------- + 1 file changed, 34 insertions(+), 50 deletions(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7003,26 +7003,23 @@ void __init free_area_init_memoryless_no + * Initialize all valid struct pages in the range [spfn, epfn) and mark them + * PageReserved(). Return the number of struct pages that were initialized. + */ +-static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn, +- int zone, int nid) ++static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn) + { +- unsigned long pfn, zone_spfn, zone_epfn; ++ unsigned long pfn; + u64 pgcnt = 0; + +- zone_spfn = arch_zone_lowest_possible_pfn[zone]; +- zone_epfn = arch_zone_highest_possible_pfn[zone]; +- +- spfn = clamp(spfn, zone_spfn, zone_epfn); +- epfn = clamp(epfn, zone_spfn, zone_epfn); +- + for (pfn = spfn; pfn < epfn; pfn++) { + if (!pfn_valid(ALIGN_DOWN(pfn, pageblock_nr_pages))) { + pfn = ALIGN_DOWN(pfn, pageblock_nr_pages) + + pageblock_nr_pages - 1; + continue; + } +- +- __init_single_page(pfn_to_page(pfn), pfn, zone, nid); ++ /* ++ * Use a fake node/zone (0) for now. Some of these pages ++ * (in memblock.reserved but not in memblock.memory) will ++ * get re-initialized via reserve_bootmem_region() later. ++ */ ++ __init_single_page(pfn_to_page(pfn), pfn, 0, 0); + __SetPageReserved(pfn_to_page(pfn)); + pgcnt++; + } +@@ -7031,64 +7028,51 @@ static u64 __init init_unavailable_range + } + + /* +- * Only struct pages that correspond to ranges defined by memblock.memory +- * are zeroed and initialized by going through __init_single_page() during +- * memmap_init(). ++ * Only struct pages that are backed by physical memory are zeroed and ++ * initialized by going through __init_single_page(). But, there are some ++ * struct pages which are reserved in memblock allocator and their fields ++ * may be accessed (for example page_to_pfn() on some configuration accesses ++ * flags). We must explicitly initialize those struct pages. + * +- * But, there could be struct pages that correspond to holes in +- * memblock.memory. This can happen because of the following reasons: +- * - phyiscal memory bank size is not necessarily the exact multiple of the +- * arbitrary section size +- * - early reserved memory may not be listed in memblock.memory +- * - memory layouts defined with memmap= kernel parameter may not align +- * nicely with memmap sections +- * +- * Explicitly initialize those struct pages so that: +- * - PG_Reserved is set +- * - zone link is set accorging to the architecture constrains +- * - node is set to node id of the next populated region except for the +- * trailing hole where last node id is used ++ * This function also addresses a similar issue where struct pages are left ++ * uninitialized because the physical address range is not covered by ++ * memblock.memory or memblock.reserved. That could happen when memblock ++ * layout is manually configured via memmap=, or when the highest physical ++ * address (max_pfn) does not end on a section boundary. + */ +-static void __init init_zone_unavailable_mem(int zone) ++static void __init init_unavailable_mem(void) + { +- unsigned long start, end; +- int i, nid; +- u64 pgcnt; +- unsigned long next = 0; ++ phys_addr_t start, end; ++ u64 i, pgcnt; ++ phys_addr_t next = 0; + + /* +- * Loop through holes in memblock.memory and initialize struct +- * pages corresponding to these holes ++ * Loop through unavailable ranges not covered by memblock.memory. + */ + pgcnt = 0; +- for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid) { ++ for_each_mem_range(i, &start, &end) { + if (next < start) +- pgcnt += init_unavailable_range(next, start, zone, nid); ++ pgcnt += init_unavailable_range(PFN_DOWN(next), ++ PFN_UP(start)); + next = end; + } + + /* +- * Last section may surpass the actual end of memory (e.g. we can +- * have 1Gb section and 512Mb of RAM pouplated). +- * Make sure that memmap has a well defined state in this case. ++ * Early sections always have a fully populated memmap for the whole ++ * section - see pfn_valid(). If the last section has holes at the ++ * end and that section is marked "online", the memmap will be ++ * considered initialized. Make sure that memmap has a well defined ++ * state. + */ +- end = round_up(max_pfn, PAGES_PER_SECTION); +- pgcnt += init_unavailable_range(next, end, zone, nid); ++ pgcnt += init_unavailable_range(PFN_DOWN(next), ++ round_up(max_pfn, PAGES_PER_SECTION)); + + /* + * Struct pages that do not have backing memory. This could be because + * firmware is using some of this memory, or for some other reasons. + */ + if (pgcnt) +- pr_info("Zone %s: zeroed struct page in unavailable ranges: %lld pages", zone_names[zone], pgcnt); +-} +- +-static void __init init_unavailable_mem(void) +-{ +- int zone; +- +- for (zone = 0; zone < ZONE_MOVABLE; zone++) +- init_zone_unavailable_mem(zone); ++ pr_info("Zeroed struct page in unavailable ranges: %lld pages", pgcnt); + } + #else + static inline void __init init_unavailable_mem(void) diff --git a/queue-5.10/series b/queue-5.10/series index 62105821961..1197af90e62 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -200,3 +200,5 @@ kernfs-wire-up-splice_read-and-splice_write.patch interconnect-imx8mq-use-icc_sync_state.patch fs-pipe-allow-sendfile-to-pipe-again.patch commit-9bb48c82aced-tty-implement-write_iter-converted-the-tty-layer-to-use-write_iter.-fix-the-redirected_tty_write-declaration-also-in-n_tty-and-change-the-comparisons-to-use-write_iter-instead-of-write.patch +mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch +revert-mm-fix-initialization-of-struct-page-for-holes-in-memory-layout.patch