diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 167 | 
1 files changed, 82 insertions, 85 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3e4b29ee2b1e..cfc72873961d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1282,6 +1282,12 @@ static __always_inline bool free_pages_prepare(struct page *page,  	kernel_poison_pages(page, 1 << order);  	/* +	 * With hardware tag-based KASAN, memory tags must be set before the +	 * page becomes unavailable via debug_pagealloc or arch_free_page. +	 */ +	kasan_free_nondeferred_pages(page, order); + +	/*  	 * arch_free_page() can make the page's contents inaccessible.  s390  	 * does this.  So nothing which can access the page's contents should  	 * happen after this. @@ -1290,8 +1296,6 @@ static __always_inline bool free_pages_prepare(struct page *page,  	debug_pagealloc_unmap_pages(page, 1 << order); -	kasan_free_nondeferred_pages(page, order); -  	return true;  } @@ -3310,6 +3314,7 @@ void split_page(struct page *page, unsigned int order)  	for (i = 1; i < (1 << order); i++)  		set_page_refcounted(page + i);  	split_page_owner(page, 1 << order); +	split_page_memcg(page, 1 << order);  }  EXPORT_SYMBOL_GPL(split_page); @@ -6259,12 +6264,65 @@ static void __meminit zone_init_free_lists(struct zone *zone)  	}  } +#if !defined(CONFIG_FLAT_NODE_MEM_MAP) +/* + * Only struct pages that correspond to ranges defined by memblock.memory + * are zeroed and initialized by going through __init_single_page() during + * memmap_init_zone(). + * + * But, there could be struct pages that correspond to holes in + * memblock.memory. This can happen because of the following reasons: + * - physical 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 and node links point to zone and node that span the page if the + *   hole is in the middle of a zone + * - zone and node links point to adjacent zone/node if the hole falls on + *   the zone boundary; the pages in such holes will be prepended to the + *   zone/node above the hole except for the trailing pages in the last + *   section that will be appended to the zone/node below. + */ +static u64 __meminit init_unavailable_range(unsigned long spfn, +					    unsigned long epfn, +					    int zone, int node) +{ +	unsigned long pfn; +	u64 pgcnt = 0; + +	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, node); +		__SetPageReserved(pfn_to_page(pfn)); +		pgcnt++; +	} + +	return pgcnt; +} +#else +static inline u64 init_unavailable_range(unsigned long spfn, unsigned long epfn, +					 int zone, int node) +{ +	return 0; +} +#endif +  void __meminit __weak memmap_init_zone(struct zone *zone)  {  	unsigned long zone_start_pfn = zone->zone_start_pfn;  	unsigned long zone_end_pfn = zone_start_pfn + zone->spanned_pages;  	int i, nid = zone_to_nid(zone), zone_id = zone_idx(zone); +	static unsigned long hole_pfn;  	unsigned long start_pfn, end_pfn; +	u64 pgcnt = 0;  	for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {  		start_pfn = clamp(start_pfn, zone_start_pfn, zone_end_pfn); @@ -6274,7 +6332,29 @@ void __meminit __weak memmap_init_zone(struct zone *zone)  			memmap_init_range(end_pfn - start_pfn, nid,  					zone_id, start_pfn, zone_end_pfn,  					MEMINIT_EARLY, NULL, MIGRATE_MOVABLE); + +		if (hole_pfn < start_pfn) +			pgcnt += init_unavailable_range(hole_pfn, start_pfn, +							zone_id, nid); +		hole_pfn = end_pfn;  	} + +#ifdef CONFIG_SPARSEMEM +	/* +	 * Initialize the hole in the range [zone_end_pfn, section_end]. +	 * If zone boundary falls in the middle of a section, this hole +	 * will be re-initialized during the call to this function for the +	 * higher zone. +	 */ +	end_pfn = round_up(zone_end_pfn, PAGES_PER_SECTION); +	if (hole_pfn < end_pfn) +		pgcnt += init_unavailable_range(hole_pfn, end_pfn, +						zone_id, nid); +#endif + +	if (pgcnt) +		pr_info("  %s zone: %llu pages in unavailable ranges\n", +			zone->name, pgcnt);  }  static int zone_batchsize(struct zone *zone) @@ -7071,88 +7151,6 @@ void __init free_area_init_memoryless_node(int nid)  	free_area_init_node(nid);  } -#if !defined(CONFIG_FLAT_NODE_MEM_MAP) -/* - * 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) -{ -	unsigned long pfn; -	u64 pgcnt = 0; - -	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); -		__SetPageReserved(pfn_to_page(pfn)); -		pgcnt++; -	} - -	return pgcnt; -} - -/* - * 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. - * - * 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_unavailable_mem(void) -{ -	phys_addr_t start, end; -	u64 i, pgcnt; -	phys_addr_t next = 0; - -	/* -	 * Loop through unavailable ranges not covered by memblock.memory. -	 */ -	pgcnt = 0; -	for_each_mem_range(i, &start, &end) { -		if (next < start) -			pgcnt += init_unavailable_range(PFN_DOWN(next), -							PFN_UP(start)); -		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. -	 */ -	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("Zeroed struct page in unavailable ranges: %lld pages", pgcnt); -} -#else -static inline void __init init_unavailable_mem(void) -{ -} -#endif /* !CONFIG_FLAT_NODE_MEM_MAP */ -  #if MAX_NUMNODES > 1  /*   * Figure out the number of possible node ids. @@ -7576,7 +7574,6 @@ void __init free_area_init(unsigned long *max_zone_pfn)  	/* Initialise every node */  	mminit_verify_pageflags_layout();  	setup_nr_node_ids(); -	init_unavailable_mem();  	for_each_online_node(nid) {  		pg_data_t *pgdat = NODE_DATA(nid);  		free_area_init_node(nid);  | 
