--- /dev/null
+From d3921cb8be29ce5668c64e23ffdaeec5f8c69399 Mon Sep 17 00:00:00 2001
+From: Mike Rapoport <rppt@kernel.org>
+Date: Sat, 23 Jan 2021 21:01:02 -0800
+Subject: mm: fix initialization of struct page for holes in memory layout
+
+From: Mike Rapoport <rppt@linux.ibm.com>
+
+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 <rppt@linux.ibm.com>
+Reported-by: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Baoquan He <bhe@redhat.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: Qian Cai <cai@lca.pw>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)
--- /dev/null
+From 377bf660d07a47269510435d11f3b65d53edca20 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+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 <torvalds@linux-foundation.org>
+
+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 <chris@chris-wilson.co.uk>
+Acked-by: Mike Rapoport <rppt@linux.ibm.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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)