Merge tag 'drm-misc-fixes-2021-01-27' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / mm / page_alloc.c
index bdbec4c..783913e 100644 (file)
@@ -1207,8 +1207,10 @@ static void kernel_init_free_pages(struct page *page, int numpages)
        /* s390's use of memset() could override KASAN redzones. */
        kasan_disable_current();
        for (i = 0; i < numpages; i++) {
+               u8 tag = page_kasan_tag(page + i);
                page_kasan_tag_reset(page + i);
                clear_highpage(page + i);
+               page_kasan_tag_set(page + i, tag);
        }
        kasan_enable_current();
 }
@@ -2862,20 +2864,20 @@ __rmqueue(struct zone *zone, unsigned int order, int migratetype,
 {
        struct page *page;
 
-#ifdef CONFIG_CMA
-       /*
-        * Balance movable allocations between regular and CMA areas by
-        * allocating from CMA when over half of the zone's free memory
-        * is in the CMA area.
-        */
-       if (alloc_flags & ALLOC_CMA &&
-           zone_page_state(zone, NR_FREE_CMA_PAGES) >
-           zone_page_state(zone, NR_FREE_PAGES) / 2) {
-               page = __rmqueue_cma_fallback(zone, order);
-               if (page)
-                       return page;
+       if (IS_ENABLED(CONFIG_CMA)) {
+               /*
+                * Balance movable allocations between regular and CMA areas by
+                * allocating from CMA when over half of the zone's free memory
+                * is in the CMA area.
+                */
+               if (alloc_flags & ALLOC_CMA &&
+                   zone_page_state(zone, NR_FREE_CMA_PAGES) >
+                   zone_page_state(zone, NR_FREE_PAGES) / 2) {
+                       page = __rmqueue_cma_fallback(zone, order);
+                       if (page)
+                               goto out;
+               }
        }
-#endif
 retry:
        page = __rmqueue_smallest(zone, order, migratetype);
        if (unlikely(!page)) {
@@ -2886,8 +2888,9 @@ retry:
                                                                alloc_flags))
                        goto retry;
        }
-
-       trace_mm_page_alloc_zone_locked(page, order, migratetype);
+out:
+       if (page)
+               trace_mm_page_alloc_zone_locked(page, order, migratetype);
        return page;
 }
 
@@ -7077,23 +7080,26 @@ void __init free_area_init_memoryless_node(int nid)
  * 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++;
        }
@@ -7102,51 +7108,64 @@ static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn)
 }
 
 /*
- * 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().
+ *
+ * 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
  *
- * 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.
+ * 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)