3388 lines · 100.5 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * mm/percpu.c - percpu memory allocator * * Copyright (C) 2009		SUSE Linux Products GmbH * Copyright (C) 2009		Tejun Heo <tj@kernel.org> * * Copyright (C) 2017		Facebook Inc. * Copyright (C) 2017		Dennis Zhou <dennis@kernel.org> * * The percpu allocator handles both static and dynamic areas.  Percpu * areas are allocated in chunks which are divided into units.  There is * a 1-to-1 mapping for units to possible cpus.  These units are grouped * based on NUMA properties of the machine. * *  c0                           c1                         c2 *  -------------------          -------------------        ------------ * | u0 | u1 | u2 | u3 |        | u0 | u1 | u2 | u3 |      | u0 | u1 | u *  -------------------  ......  -------------------  ....  ------------ * * Allocation is done by offsets into a unit's address space.  Ie., an * area of 512 bytes at 6k in c1 occupies 512 bytes at 6k in c1:u0, * c1:u1, c1:u2, etc.  On NUMA machines, the mapping may be non-linear * and even sparse.  Access is handled by configuring percpu base * registers according to the cpu to unit mappings and offsetting the * base address using pcpu_unit_size. * * There is special consideration for the first chunk which must handle * the static percpu variables in the kernel image as allocation services * are not online yet.  In short, the first chunk is structured like so: * *                  <Static | [Reserved] | Dynamic> * * The static data is copied from the original section managed by the * linker.  The reserved section, if non-zero, primarily manages static * percpu variables from kernel modules.  Finally, the dynamic section * takes care of normal allocations. * * The allocator organizes chunks into lists according to free size and * memcg-awareness.  To make a percpu allocation memcg-aware the __GFP_ACCOUNT * flag should be passed.  All memcg-aware allocations are sharing one set * of chunks and all unaccounted allocations and allocations performed * by processes belonging to the root memory cgroup are using the second set. * * The allocator tries to allocate from the fullest chunk first. Each chunk * is managed by a bitmap with metadata blocks.  The allocation map is updated * on every allocation and free to reflect the current state while the boundary * map is only updated on allocation.  Each metadata block contains * information to help mitigate the need to iterate over large portions * of the bitmap.  The reverse mapping from page to chunk is stored in * the page's index.  Lastly, units are lazily backed and grow in unison. * * There is a unique conversion that goes on here between bytes and bits. * Each bit represents a fragment of size PCPU_MIN_ALLOC_SIZE.  The chunk * tracks the number of pages it is responsible for in nr_pages.  Helper * functions are used to convert from between the bytes, bits, and blocks. * All hints are managed in bits unless explicitly stated. * * To use this allocator, arch code should do the following: * * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate *   regular address to percpu pointer and back if they need to be *   different from the default * * - use pcpu_setup_first_chunk() during percpu area initialization to *   setup the first chunk containing the kernel static percpu area */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/bitmap.h>#include <linux/cpumask.h>#include <linux/memblock.h>#include <linux/err.h>#include <linux/list.h>#include <linux/log2.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/mutex.h>#include <linux/percpu.h>#include <linux/pfn.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <linux/vmalloc.h>#include <linux/workqueue.h>#include <linux/kmemleak.h>#include <linux/sched.h>#include <linux/sched/mm.h>#include <linux/memcontrol.h> #include <asm/cacheflush.h>#include <asm/sections.h>#include <asm/tlbflush.h>#include <asm/io.h> #define CREATE_TRACE_POINTS#include <trace/events/percpu.h> #include "percpu-internal.h" /* * The slots are sorted by the size of the biggest continuous free area. * 1-31 bytes share the same slot. */#define PCPU_SLOT_BASE_SHIFT		5/* chunks in slots below this are subject to being sidelined on failed alloc */#define PCPU_SLOT_FAIL_THRESHOLD	3 #define PCPU_EMPTY_POP_PAGES_LOW	2#define PCPU_EMPTY_POP_PAGES_HIGH	4 #ifdef CONFIG_SMP/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */#ifndef __addr_to_pcpu_ptr#define __addr_to_pcpu_ptr(addr)					\	(void __percpu *)((unsigned long)(addr) -			\			  (unsigned long)pcpu_base_addr	+		\			  (unsigned long)__per_cpu_start)#endif#ifndef __pcpu_ptr_to_addr#define __pcpu_ptr_to_addr(ptr)						\	(void __force *)((unsigned long)(ptr) +				\			 (unsigned long)pcpu_base_addr -		\			 (unsigned long)__per_cpu_start)#endif#else	/* CONFIG_SMP *//* on UP, it's always identity mapped */#define __addr_to_pcpu_ptr(addr)	(void __percpu *)(addr)#define __pcpu_ptr_to_addr(ptr)		(void __force *)(ptr)#endif	/* CONFIG_SMP */ static int pcpu_unit_pages __ro_after_init;static int pcpu_unit_size __ro_after_init;static int pcpu_nr_units __ro_after_init;static int pcpu_atom_size __ro_after_init;int pcpu_nr_slots __ro_after_init;static int pcpu_free_slot __ro_after_init;int pcpu_sidelined_slot __ro_after_init;int pcpu_to_depopulate_slot __ro_after_init;static size_t pcpu_chunk_struct_size __ro_after_init; /* cpus with the lowest and highest unit addresses */static unsigned int pcpu_low_unit_cpu __ro_after_init;static unsigned int pcpu_high_unit_cpu __ro_after_init; /* the address of the first chunk which starts with the kernel static area */void *pcpu_base_addr __ro_after_init; static const int *pcpu_unit_map __ro_after_init;		/* cpu -> unit */const unsigned long *pcpu_unit_offsets __ro_after_init;	/* cpu -> unit offset */ /* group information, used for vm allocation */static int pcpu_nr_groups __ro_after_init;static const unsigned long *pcpu_group_offsets __ro_after_init;static const size_t *pcpu_group_sizes __ro_after_init; /* * The first chunk which always exists.  Note that unlike other * chunks, this one can be allocated and mapped in several different * ways and thus often doesn't live in the vmalloc area. */struct pcpu_chunk *pcpu_first_chunk __ro_after_init; /* * Optional reserved chunk.  This chunk reserves part of the first * chunk and serves it for reserved allocations.  When the reserved * region doesn't exist, the following variable is NULL. */struct pcpu_chunk *pcpu_reserved_chunk __ro_after_init; DEFINE_SPINLOCK(pcpu_lock);	/* all internal data structures */static DEFINE_MUTEX(pcpu_alloc_mutex);	/* chunk create/destroy, [de]pop, map ext */ struct list_head *pcpu_chunk_lists __ro_after_init; /* chunk list slots */ /* * The number of empty populated pages, protected by pcpu_lock. * The reserved chunk doesn't contribute to the count. */int pcpu_nr_empty_pop_pages; /* * The number of populated pages in use by the allocator, protected by * pcpu_lock.  This number is kept per a unit per chunk (i.e. when a page gets * allocated/deallocated, it is allocated/deallocated in all units of a chunk * and increments/decrements this count by 1). */static unsigned long pcpu_nr_populated; /* * Balance work is used to populate or destroy chunks asynchronously.  We * try to keep the number of populated free pages between * PCPU_EMPTY_POP_PAGES_LOW and HIGH for atomic allocations and at most one * empty chunk. */static void pcpu_balance_workfn(struct work_struct *work);static DECLARE_WORK(pcpu_balance_work, pcpu_balance_workfn);static bool pcpu_async_enabled __read_mostly;static bool pcpu_atomic_alloc_failed; static void pcpu_schedule_balance_work(void){	if (pcpu_async_enabled)		schedule_work(&pcpu_balance_work);} /** * pcpu_addr_in_chunk - check if the address is served from this chunk * @chunk: chunk of interest * @addr: percpu address * * RETURNS: * True if the address is served from this chunk. */static bool pcpu_addr_in_chunk(struct pcpu_chunk *chunk, void *addr){	void *start_addr, *end_addr; 	if (!chunk)		return false; 	start_addr = chunk->base_addr + chunk->start_offset;	end_addr = chunk->base_addr + chunk->nr_pages * PAGE_SIZE -		   chunk->end_offset; 	return addr >= start_addr && addr < end_addr;} static int __pcpu_size_to_slot(int size){	int highbit = fls(size);	/* size is in bytes */	return max(highbit - PCPU_SLOT_BASE_SHIFT + 2, 1);} static int pcpu_size_to_slot(int size){	if (size == pcpu_unit_size)		return pcpu_free_slot;	return __pcpu_size_to_slot(size);} static int pcpu_chunk_slot(const struct pcpu_chunk *chunk){	const struct pcpu_block_md *chunk_md = &chunk->chunk_md; 	if (chunk->free_bytes < PCPU_MIN_ALLOC_SIZE ||	    chunk_md->contig_hint == 0)		return 0; 	return pcpu_size_to_slot(chunk_md->contig_hint * PCPU_MIN_ALLOC_SIZE);} /* set the pointer to a chunk in a page struct */static void pcpu_set_page_chunk(struct page *page, struct pcpu_chunk *pcpu){	page->private = (unsigned long)pcpu;} /* obtain pointer to a chunk from a page struct */static struct pcpu_chunk *pcpu_get_page_chunk(struct page *page){	return (struct pcpu_chunk *)page->private;} static int __maybe_unused pcpu_page_idx(unsigned int cpu, int page_idx){	return pcpu_unit_map[cpu] * pcpu_unit_pages + page_idx;} static unsigned long pcpu_unit_page_offset(unsigned int cpu, int page_idx){	return pcpu_unit_offsets[cpu] + (page_idx << PAGE_SHIFT);} static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk,				     unsigned int cpu, int page_idx){	return (unsigned long)chunk->base_addr +	       pcpu_unit_page_offset(cpu, page_idx);} /* * The following are helper functions to help access bitmaps and convert * between bitmap offsets to address offsets. */static unsigned long *pcpu_index_alloc_map(struct pcpu_chunk *chunk, int index){	return chunk->alloc_map +	       (index * PCPU_BITMAP_BLOCK_BITS / BITS_PER_LONG);} static unsigned long pcpu_off_to_block_index(int off){	return off / PCPU_BITMAP_BLOCK_BITS;} static unsigned long pcpu_off_to_block_off(int off){	return off & (PCPU_BITMAP_BLOCK_BITS - 1);} static unsigned long pcpu_block_off_to_off(int index, int off){	return index * PCPU_BITMAP_BLOCK_BITS + off;} /** * pcpu_check_block_hint - check against the contig hint * @block: block of interest * @bits: size of allocation * @align: alignment of area (max PAGE_SIZE) * * Check to see if the allocation can fit in the block's contig hint. * Note, a chunk uses the same hints as a block so this can also check against * the chunk's contig hint. */static bool pcpu_check_block_hint(struct pcpu_block_md *block, int bits,				  size_t align){	int bit_off = ALIGN(block->contig_hint_start, align) -		block->contig_hint_start; 	return bit_off + bits <= block->contig_hint;} /* * pcpu_next_hint - determine which hint to use * @block: block of interest * @alloc_bits: size of allocation * * This determines if we should scan based on the scan_hint or first_free. * In general, we want to scan from first_free to fulfill allocations by * first fit.  However, if we know a scan_hint at position scan_hint_start * cannot fulfill an allocation, we can begin scanning from there knowing * the contig_hint will be our fallback. */static int pcpu_next_hint(struct pcpu_block_md *block, int alloc_bits){	/*	 * The three conditions below determine if we can skip past the	 * scan_hint.  First, does the scan hint exist.  Second, is the	 * contig_hint after the scan_hint (possibly not true iff	 * contig_hint == scan_hint).  Third, is the allocation request	 * larger than the scan_hint.	 */	if (block->scan_hint &&	    block->contig_hint_start > block->scan_hint_start &&	    alloc_bits > block->scan_hint)		return block->scan_hint_start + block->scan_hint; 	return block->first_free;} /** * pcpu_next_md_free_region - finds the next hint free area * @chunk: chunk of interest * @bit_off: chunk offset * @bits: size of free area * * Helper function for pcpu_for_each_md_free_region.  It checks * block->contig_hint and performs aggregation across blocks to find the * next hint.  It modifies bit_off and bits in-place to be consumed in the * loop. */static void pcpu_next_md_free_region(struct pcpu_chunk *chunk, int *bit_off,				     int *bits){	int i = pcpu_off_to_block_index(*bit_off);	int block_off = pcpu_off_to_block_off(*bit_off);	struct pcpu_block_md *block; 	*bits = 0;	for (block = chunk->md_blocks + i; i < pcpu_chunk_nr_blocks(chunk);	     block++, i++) {		/* handles contig area across blocks */		if (*bits) {			*bits += block->left_free;			if (block->left_free == PCPU_BITMAP_BLOCK_BITS)				continue;			return;		} 		/*		 * This checks three things.  First is there a contig_hint to		 * check.  Second, have we checked this hint before by		 * comparing the block_off.  Third, is this the same as the		 * right contig hint.  In the last case, it spills over into		 * the next block and should be handled by the contig area		 * across blocks code.		 */		*bits = block->contig_hint;		if (*bits && block->contig_hint_start >= block_off &&		    *bits + block->contig_hint_start < PCPU_BITMAP_BLOCK_BITS) {			*bit_off = pcpu_block_off_to_off(i,					block->contig_hint_start);			return;		}		/* reset to satisfy the second predicate above */		block_off = 0; 		*bits = block->right_free;		*bit_off = (i + 1) * PCPU_BITMAP_BLOCK_BITS - block->right_free;	}} /** * pcpu_next_fit_region - finds fit areas for a given allocation request * @chunk: chunk of interest * @alloc_bits: size of allocation * @align: alignment of area (max PAGE_SIZE) * @bit_off: chunk offset * @bits: size of free area * * Finds the next free region that is viable for use with a given size and * alignment.  This only returns if there is a valid area to be used for this * allocation.  block->first_free is returned if the allocation request fits * within the block to see if the request can be fulfilled prior to the contig * hint. */static void pcpu_next_fit_region(struct pcpu_chunk *chunk, int alloc_bits,				 int align, int *bit_off, int *bits){	int i = pcpu_off_to_block_index(*bit_off);	int block_off = pcpu_off_to_block_off(*bit_off);	struct pcpu_block_md *block; 	*bits = 0;	for (block = chunk->md_blocks + i; i < pcpu_chunk_nr_blocks(chunk);	     block++, i++) {		/* handles contig area across blocks */		if (*bits) {			*bits += block->left_free;			if (*bits >= alloc_bits)				return;			if (block->left_free == PCPU_BITMAP_BLOCK_BITS)				continue;		} 		/* check block->contig_hint */		*bits = ALIGN(block->contig_hint_start, align) -			block->contig_hint_start;		/*		 * This uses the block offset to determine if this has been		 * checked in the prior iteration.		 */		if (block->contig_hint &&		    block->contig_hint_start >= block_off &&		    block->contig_hint >= *bits + alloc_bits) {			int start = pcpu_next_hint(block, alloc_bits); 			*bits += alloc_bits + block->contig_hint_start -				 start;			*bit_off = pcpu_block_off_to_off(i, start);			return;		}		/* reset to satisfy the second predicate above */		block_off = 0; 		*bit_off = ALIGN(PCPU_BITMAP_BLOCK_BITS - block->right_free,				 align);		*bits = PCPU_BITMAP_BLOCK_BITS - *bit_off;		*bit_off = pcpu_block_off_to_off(i, *bit_off);		if (*bits >= alloc_bits)			return;	} 	/* no valid offsets were found - fail condition */	*bit_off = pcpu_chunk_map_bits(chunk);} /* * Metadata free area iterators.  These perform aggregation of free areas * based on the metadata blocks and return the offset @bit_off and size in * bits of the free area @bits.  pcpu_for_each_fit_region only returns when * a fit is found for the allocation request. */#define pcpu_for_each_md_free_region(chunk, bit_off, bits)		\	for (pcpu_next_md_free_region((chunk), &(bit_off), &(bits));	\	     (bit_off) < pcpu_chunk_map_bits((chunk));			\	     (bit_off) += (bits) + 1,					\	     pcpu_next_md_free_region((chunk), &(bit_off), &(bits))) #define pcpu_for_each_fit_region(chunk, alloc_bits, align, bit_off, bits)     \	for (pcpu_next_fit_region((chunk), (alloc_bits), (align), &(bit_off), \				  &(bits));				      \	     (bit_off) < pcpu_chunk_map_bits((chunk));			      \	     (bit_off) += (bits),					      \	     pcpu_next_fit_region((chunk), (alloc_bits), (align), &(bit_off), \				  &(bits))) /** * pcpu_mem_zalloc - allocate memory * @size: bytes to allocate * @gfp: allocation flags * * Allocate @size bytes.  If @size is smaller than PAGE_SIZE, * kzalloc() is used; otherwise, the equivalent of vzalloc() is used. * This is to facilitate passing through whitelisted flags.  The * returned memory is always zeroed. *

Lines 1–500 of 3388.