···233233 "%zu bytes\n", vm.addr, static_size);234234235235 ret = pcpu_setup_first_chunk(pcpur_get_page, static_size,236236- PERCPU_FIRST_CHUNK_RESERVE,237237- PMD_SIZE, dyn_size, vm.addr, NULL);236236+ PERCPU_FIRST_CHUNK_RESERVE, dyn_size,237237+ PMD_SIZE, vm.addr, NULL);238238 goto out_free_ar;239239240240enomem:···257257 * Embedding allocator258258 *259259 * The first chunk is sized to just contain the static area plus260260- * module and dynamic reserves, and allocated as a contiguous area261261- * using bootmem allocator and used as-is without being mapped into262262- * vmalloc area. This enables the first chunk to piggy back on the263263- * linear physical PMD mapping and doesn't add any additional pressure264264- * to TLB. Note that if the needed size is smaller than the minimum265265- * unit size, the leftover is returned to the bootmem allocator.260260+ * module and dynamic reserves and embedded into linear physical261261+ * mapping so that it can use PMD mapping without additional TLB262262+ * pressure.266263 */267267-static void *pcpue_ptr __initdata;268268-static size_t pcpue_size __initdata;269269-static size_t pcpue_unit_size __initdata;270270-271271-static struct page * __init pcpue_get_page(unsigned int cpu, int pageno)272272-{273273- size_t off = (size_t)pageno << PAGE_SHIFT;274274-275275- if (off >= pcpue_size)276276- return NULL;277277-278278- return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off);279279-}280280-281264static ssize_t __init setup_pcpu_embed(size_t static_size)282265{283283- unsigned int cpu;284284- size_t dyn_size;266266+ size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;285267286268 /*287269 * If large page isn't supported, there's no benefit in doing···273291 if (!cpu_has_pse || pcpu_need_numa())274292 return -EINVAL;275293276276- /* allocate and copy */277277- pcpue_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +278278- PERCPU_DYNAMIC_RESERVE);279279- pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE);280280- dyn_size = pcpue_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;281281-282282- pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size,283283- PAGE_SIZE);284284- if (!pcpue_ptr)285285- return -ENOMEM;286286-287287- for_each_possible_cpu(cpu) {288288- void *ptr = pcpue_ptr + cpu * pcpue_unit_size;289289-290290- free_bootmem(__pa(ptr + pcpue_size),291291- pcpue_unit_size - pcpue_size);292292- memcpy(ptr, __per_cpu_load, static_size);293293- }294294-295295- /* we're ready, commit */296296- pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n",297297- pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size);298298-299299- return pcpu_setup_first_chunk(pcpue_get_page, static_size,300300- PERCPU_FIRST_CHUNK_RESERVE,301301- pcpue_unit_size, dyn_size,302302- pcpue_ptr, NULL);294294+ return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE,295295+ reserve - PERCPU_FIRST_CHUNK_RESERVE, -1);303296}304297305298/*···332375 pcpu4k_nr_static_pages, static_size);333376334377 ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size,335335- PERCPU_FIRST_CHUNK_RESERVE, -1, -1, NULL,336336- pcpu4k_populate_pte);378378+ PERCPU_FIRST_CHUNK_RESERVE, -1,379379+ -1, NULL, pcpu4k_populate_pte);337380 goto out_free_ar;338381339382enomem:
+5-1
include/linux/percpu.h
···107107108108extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,109109 size_t static_size, size_t reserved_size,110110- ssize_t unit_size, ssize_t dyn_size,110110+ ssize_t dyn_size, ssize_t unit_size,111111 void *base_addr,112112 pcpu_populate_pte_fn_t populate_pte_fn);113113+114114+extern ssize_t __init pcpu_embed_first_chunk(115115+ size_t static_size, size_t reserved_size,116116+ ssize_t dyn_size, ssize_t unit_size);113117114118/*115119 * Use this to get to a cpu's version of the per-cpu object
+1-1
mm/allocpercpu.c
···120120 * on it. Larger alignment should only be used for module121121 * percpu sections on SMP for which this path isn't used.122122 */123123- WARN_ON_ONCE(align > __alignof__(unsigned long long));123123+ WARN_ON_ONCE(align > SMP_CACHE_BYTES);124124125125 if (unlikely(!pdata))126126 return NULL;
+115-15
mm/percpu.c
···4646 * - define CONFIG_HAVE_DYNAMIC_PER_CPU_AREA4747 *4848 * - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate4949- * regular address to percpu pointer and back4949+ * regular address to percpu pointer and back if they need to be5050+ * different from the default5051 *5152 * - use pcpu_setup_first_chunk() during percpu area initialization to5253 * setup the first chunk containing the kernel static percpu area···6867#include <linux/workqueue.h>69687069#include <asm/cacheflush.h>7070+#include <asm/sections.h>7171#include <asm/tlbflush.h>72727373#define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */7474#define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */7575+7676+/* default addr <-> pcpu_ptr mapping, override in asm/percpu.h if necessary */7777+#ifndef __addr_to_pcpu_ptr7878+#define __addr_to_pcpu_ptr(addr) \7979+ (void *)((unsigned long)(addr) - (unsigned long)pcpu_base_addr \8080+ + (unsigned long)__per_cpu_start)8181+#endif8282+#ifndef __pcpu_ptr_to_addr8383+#define __pcpu_ptr_to_addr(ptr) \8484+ (void *)((unsigned long)(ptr) + (unsigned long)pcpu_base_addr \8585+ - (unsigned long)__per_cpu_start)8686+#endif75877688struct pcpu_chunk {7789 struct list_head list; /* linked to pcpu_slot lists */···10271013 * @get_page_fn: callback to fetch page pointer10281014 * @static_size: the size of static percpu area in bytes10291015 * @reserved_size: the size of reserved percpu area in bytes10301030- * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto10311016 * @dyn_size: free size for dynamic allocation in bytes, -1 for auto10171017+ * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto10321018 * @base_addr: mapped address, NULL for auto10331019 * @populate_pte_fn: callback to allocate pagetable, NULL if unnecessary10341020 *···10531039 * limited offset range for symbol relocations to guarantee module10541040 * percpu symbols fall inside the relocatable range.10551041 *10421042+ * @dyn_size, if non-negative, determines the number of bytes10431043+ * available for dynamic allocation in the first chunk. Specifying10441044+ * non-negative value makes percpu leave alone the area beyond10451045+ * @static_size + @reserved_size + @dyn_size.10461046+ *10561047 * @unit_size, if non-negative, specifies unit size and must be10571048 * aligned to PAGE_SIZE and equal to or larger than @static_size +10581058- * @reserved_size + @dyn_size.10591059- *10601060- * @dyn_size, if non-negative, limits the number of bytes available10611061- * for dynamic allocation in the first chunk. Specifying non-negative10621062- * value make percpu leave alone the area beyond @static_size +10631063- * @reserved_size + @dyn_size.10491049+ * @reserved_size + if non-negative, @dyn_size.10641050 *10651051 * Non-null @base_addr means that the caller already allocated virtual10661052 * region for the first chunk and mapped it. percpu must not mess···10831069 */10841070size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,10851071 size_t static_size, size_t reserved_size,10861086- ssize_t unit_size, ssize_t dyn_size,10721072+ ssize_t dyn_size, ssize_t unit_size,10871073 void *base_addr,10881074 pcpu_populate_pte_fn_t populate_pte_fn)10891075{10901076 static struct vm_struct first_vm;10911077 static int smap[2], dmap[2];10781078+ size_t size_sum = static_size + reserved_size +10791079+ (dyn_size >= 0 ? dyn_size : 0);10921080 struct pcpu_chunk *schunk, *dchunk = NULL;10931081 unsigned int cpu;10941082 int nr_pages;···11011085 ARRAY_SIZE(dmap) >= PCPU_DFL_MAP_ALLOC);11021086 BUG_ON(!static_size);11031087 if (unit_size >= 0) {11041104- BUG_ON(unit_size < static_size + reserved_size +11051105- (dyn_size >= 0 ? dyn_size : 0));10881088+ BUG_ON(unit_size < size_sum);11061089 BUG_ON(unit_size & ~PAGE_MASK);11071107- } else {11081108- BUG_ON(dyn_size >= 0);10901090+ BUG_ON(unit_size < PCPU_MIN_UNIT_SIZE);10911091+ } else11091092 BUG_ON(base_addr);11101110- }11111093 BUG_ON(base_addr && populate_pte_fn);1112109411131095 if (unit_size >= 0)11141096 pcpu_unit_pages = unit_size >> PAGE_SHIFT;11151097 else11161098 pcpu_unit_pages = max_t(int, PCPU_MIN_UNIT_SIZE >> PAGE_SHIFT,11171117- PFN_UP(static_size + reserved_size));10991099+ PFN_UP(size_sum));1118110011191101 pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;11201102 pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size;···12371223 /* we're done */12381224 pcpu_base_addr = (void *)pcpu_chunk_addr(schunk, 0, 0);12391225 return pcpu_unit_size;12261226+}12271227+12281228+/*12291229+ * Embedding first chunk setup helper.12301230+ */12311231+static void *pcpue_ptr __initdata;12321232+static size_t pcpue_size __initdata;12331233+static size_t pcpue_unit_size __initdata;12341234+12351235+static struct page * __init pcpue_get_page(unsigned int cpu, int pageno)12361236+{12371237+ size_t off = (size_t)pageno << PAGE_SHIFT;12381238+12391239+ if (off >= pcpue_size)12401240+ return NULL;12411241+12421242+ return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off);12431243+}12441244+12451245+/**12461246+ * pcpu_embed_first_chunk - embed the first percpu chunk into bootmem12471247+ * @static_size: the size of static percpu area in bytes12481248+ * @reserved_size: the size of reserved percpu area in bytes12491249+ * @dyn_size: free size for dynamic allocation in bytes, -1 for auto12501250+ * @unit_size: unit size in bytes, must be multiple of PAGE_SIZE, -1 for auto12511251+ *12521252+ * This is a helper to ease setting up embedded first percpu chunk and12531253+ * can be called where pcpu_setup_first_chunk() is expected.12541254+ *12551255+ * If this function is used to setup the first chunk, it is allocated12561256+ * as a contiguous area using bootmem allocator and used as-is without12571257+ * being mapped into vmalloc area. This enables the first chunk to12581258+ * piggy back on the linear physical mapping which often uses larger12591259+ * page size.12601260+ *12611261+ * When @dyn_size is positive, dynamic area might be larger than12621262+ * specified to fill page alignment. Also, when @dyn_size is auto,12631263+ * @dyn_size does not fill the whole first chunk but only what's12641264+ * necessary for page alignment after static and reserved areas.12651265+ *12661266+ * If the needed size is smaller than the minimum or specified unit12671267+ * size, the leftover is returned to the bootmem allocator.12681268+ *12691269+ * RETURNS:12701270+ * The determined pcpu_unit_size which can be used to initialize12711271+ * percpu access on success, -errno on failure.12721272+ */12731273+ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size,12741274+ ssize_t dyn_size, ssize_t unit_size)12751275+{12761276+ unsigned int cpu;12771277+12781278+ /* determine parameters and allocate */12791279+ pcpue_size = PFN_ALIGN(static_size + reserved_size +12801280+ (dyn_size >= 0 ? dyn_size : 0));12811281+ if (dyn_size != 0)12821282+ dyn_size = pcpue_size - static_size - reserved_size;12831283+12841284+ if (unit_size >= 0) {12851285+ BUG_ON(unit_size < pcpue_size);12861286+ pcpue_unit_size = unit_size;12871287+ } else12881288+ pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE);12891289+12901290+ pcpue_ptr = __alloc_bootmem_nopanic(12911291+ num_possible_cpus() * pcpue_unit_size,12921292+ PAGE_SIZE, __pa(MAX_DMA_ADDRESS));12931293+ if (!pcpue_ptr)12941294+ return -ENOMEM;12951295+12961296+ /* return the leftover and copy */12971297+ for_each_possible_cpu(cpu) {12981298+ void *ptr = pcpue_ptr + cpu * pcpue_unit_size;12991299+13001300+ free_bootmem(__pa(ptr + pcpue_size),13011301+ pcpue_unit_size - pcpue_size);13021302+ memcpy(ptr, __per_cpu_load, static_size);13031303+ }13041304+13051305+ /* we're ready, commit */13061306+ pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n",13071307+ pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size);13081308+13091309+ return pcpu_setup_first_chunk(pcpue_get_page, static_size,13101310+ reserved_size, dyn_size,13111311+ pcpue_unit_size, pcpue_ptr, NULL);12401312}