Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | #ifndef __LINUX_PERCPU_H |
| 2 | #define __LINUX_PERCPU_H |
Martin Peschke | 7ff6f08 | 2006-09-25 23:31:21 -0700 | [diff] [blame] | 3 | |
Sasha Levin | 309381fea | 2014-01-23 15:52:54 -0800 | [diff] [blame] | 4 | #include <linux/mmdebug.h> |
Robert P. J. Day | 0a3021f | 2007-07-15 23:39:57 -0700 | [diff] [blame] | 5 | #include <linux/preempt.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6 | #include <linux/smp.h> |
Martin Peschke | 7ff6f08 | 2006-09-25 23:31:21 -0700 | [diff] [blame] | 7 | #include <linux/cpumask.h> |
Steven Rostedt (Red Hat) | 04b74b2 | 2014-11-21 09:16:58 -0500 | [diff] [blame] | 8 | #include <linux/printk.h> |
Tejun Heo | 6a24290 | 2009-03-06 14:33:58 +0900 | [diff] [blame] | 9 | #include <linux/pfn.h> |
Tejun Heo | de380b5 | 2010-03-24 17:06:43 +0900 | [diff] [blame] | 10 | #include <linux/init.h> |
Martin Peschke | 7ff6f08 | 2006-09-25 23:31:21 -0700 | [diff] [blame] | 11 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 12 | #include <asm/percpu.h> |
| 13 | |
Tejun Heo | 6a24290 | 2009-03-06 14:33:58 +0900 | [diff] [blame] | 14 | /* enough to cover all DEFINE_PER_CPUs in modules */ |
Jeremy Fitzhardinge | b00742d3 | 2007-05-02 19:27:11 +0200 | [diff] [blame] | 15 | #ifdef CONFIG_MODULES |
Tejun Heo | 6a24290 | 2009-03-06 14:33:58 +0900 | [diff] [blame] | 16 | #define PERCPU_MODULE_RESERVE (8 << 10) |
Jeremy Fitzhardinge | b00742d3 | 2007-05-02 19:27:11 +0200 | [diff] [blame] | 17 | #else |
Tejun Heo | 6a24290 | 2009-03-06 14:33:58 +0900 | [diff] [blame] | 18 | #define PERCPU_MODULE_RESERVE 0 |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 19 | #endif |
| 20 | |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 21 | /* minimum unit size, also is the maximum supported allocation size */ |
Tejun Heo | 6abad5a | 2010-09-03 18:22:47 +0200 | [diff] [blame] | 22 | #define PCPU_MIN_UNIT_SIZE PFN_ALIGN(32 << 10) |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 23 | |
| 24 | /* |
Tejun Heo | 099a19d | 2010-06-27 18:50:00 +0200 | [diff] [blame] | 25 | * Percpu allocator can serve percpu allocations before slab is |
| 26 | * initialized which allows slab to depend on the percpu allocator. |
| 27 | * The following two parameters decide how much resource to |
| 28 | * preallocate for this. Keep PERCPU_DYNAMIC_RESERVE equal to or |
| 29 | * larger than PERCPU_DYNAMIC_EARLY_SIZE. |
| 30 | */ |
| 31 | #define PERCPU_DYNAMIC_EARLY_SLOTS 128 |
| 32 | #define PERCPU_DYNAMIC_EARLY_SIZE (12 << 10) |
| 33 | |
| 34 | /* |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 35 | * PERCPU_DYNAMIC_RESERVE indicates the amount of free area to piggy |
Tejun Heo | 6b19b0c | 2009-03-06 14:33:59 +0900 | [diff] [blame] | 36 | * back on the first chunk for dynamic percpu allocation if arch is |
| 37 | * manually allocating and mapping it for faster access (as a part of |
| 38 | * large page mapping for example). |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 39 | * |
Tejun Heo | 6b19b0c | 2009-03-06 14:33:59 +0900 | [diff] [blame] | 40 | * The following values give between one and two pages of free space |
| 41 | * after typical minimal boot (2-way SMP, single disk and NIC) with |
| 42 | * both defconfig and a distro config on x86_64 and 32. More |
| 43 | * intelligent way to determine this would be nice. |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 44 | */ |
Tejun Heo | 6b19b0c | 2009-03-06 14:33:59 +0900 | [diff] [blame] | 45 | #if BITS_PER_LONG > 32 |
Tejun Heo | 1a4d760 | 2014-09-02 14:46:05 -0400 | [diff] [blame] | 46 | #define PERCPU_DYNAMIC_RESERVE (28 << 10) |
Tejun Heo | 6b19b0c | 2009-03-06 14:33:59 +0900 | [diff] [blame] | 47 | #else |
Tejun Heo | 1a4d760 | 2014-09-02 14:46:05 -0400 | [diff] [blame] | 48 | #define PERCPU_DYNAMIC_RESERVE (20 << 10) |
Tejun Heo | 6b19b0c | 2009-03-06 14:33:59 +0900 | [diff] [blame] | 49 | #endif |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 50 | |
Tejun Heo | fbf59bc | 2009-02-20 16:29:08 +0900 | [diff] [blame] | 51 | extern void *pcpu_base_addr; |
Tejun Heo | fb435d5 | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 52 | extern const unsigned long *pcpu_unit_offsets; |
Tejun Heo | fbf59bc | 2009-02-20 16:29:08 +0900 | [diff] [blame] | 53 | |
Tejun Heo | fd1e8a1 | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 54 | struct pcpu_group_info { |
| 55 | int nr_units; /* aligned # of units */ |
| 56 | unsigned long base_offset; /* base address offset */ |
| 57 | unsigned int *cpu_map; /* unit->cpu map, empty |
| 58 | * entries contain NR_CPUS */ |
| 59 | }; |
| 60 | |
| 61 | struct pcpu_alloc_info { |
| 62 | size_t static_size; |
| 63 | size_t reserved_size; |
| 64 | size_t dyn_size; |
| 65 | size_t unit_size; |
| 66 | size_t atom_size; |
| 67 | size_t alloc_size; |
| 68 | size_t __ai_size; /* internal, don't use */ |
| 69 | int nr_groups; /* 0 if grouping unnecessary */ |
| 70 | struct pcpu_group_info groups[]; |
| 71 | }; |
| 72 | |
Tejun Heo | f58dc01 | 2009-08-14 15:00:50 +0900 | [diff] [blame] | 73 | enum pcpu_fc { |
| 74 | PCPU_FC_AUTO, |
| 75 | PCPU_FC_EMBED, |
| 76 | PCPU_FC_PAGE, |
Tejun Heo | f58dc01 | 2009-08-14 15:00:50 +0900 | [diff] [blame] | 77 | |
| 78 | PCPU_FC_NR, |
| 79 | }; |
Andi Kleen | 17f3609 | 2012-10-04 17:12:07 -0700 | [diff] [blame] | 80 | extern const char * const pcpu_fc_names[PCPU_FC_NR]; |
Tejun Heo | f58dc01 | 2009-08-14 15:00:50 +0900 | [diff] [blame] | 81 | |
| 82 | extern enum pcpu_fc pcpu_chosen_fc; |
| 83 | |
Tejun Heo | 3cbc856 | 2009-08-14 15:00:50 +0900 | [diff] [blame] | 84 | typedef void * (*pcpu_fc_alloc_fn_t)(unsigned int cpu, size_t size, |
| 85 | size_t align); |
Tejun Heo | d4b95f8 | 2009-07-04 08:10:59 +0900 | [diff] [blame] | 86 | typedef void (*pcpu_fc_free_fn_t)(void *ptr, size_t size); |
| 87 | typedef void (*pcpu_fc_populate_pte_fn_t)(unsigned long addr); |
Tejun Heo | a530b79 | 2009-07-04 08:11:00 +0900 | [diff] [blame] | 88 | typedef int (pcpu_fc_cpu_distance_fn_t)(unsigned int from, unsigned int to); |
Tejun Heo | fbf59bc | 2009-02-20 16:29:08 +0900 | [diff] [blame] | 89 | |
Tejun Heo | fd1e8a1 | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 90 | extern struct pcpu_alloc_info * __init pcpu_alloc_alloc_info(int nr_groups, |
| 91 | int nr_units); |
| 92 | extern void __init pcpu_free_alloc_info(struct pcpu_alloc_info *ai); |
Tejun Heo | 033e48f | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 93 | |
Tejun Heo | fb435d5 | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 94 | extern int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, |
| 95 | void *base_addr); |
Tejun Heo | 8d408b4 | 2009-02-24 11:57:21 +0900 | [diff] [blame] | 96 | |
Tejun Heo | 08fc458 | 2009-08-14 15:00:49 +0900 | [diff] [blame] | 97 | #ifdef CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK |
Tejun Heo | 4ba6ce2 | 2010-06-27 18:49:59 +0200 | [diff] [blame] | 98 | extern int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size, |
Tejun Heo | c8826dd | 2009-08-14 15:00:52 +0900 | [diff] [blame] | 99 | size_t atom_size, |
| 100 | pcpu_fc_cpu_distance_fn_t cpu_distance_fn, |
| 101 | pcpu_fc_alloc_fn_t alloc_fn, |
| 102 | pcpu_fc_free_fn_t free_fn); |
Tejun Heo | 08fc458 | 2009-08-14 15:00:49 +0900 | [diff] [blame] | 103 | #endif |
Tejun Heo | 66c3a75 | 2009-03-10 16:27:48 +0900 | [diff] [blame] | 104 | |
Tejun Heo | 08fc458 | 2009-08-14 15:00:49 +0900 | [diff] [blame] | 105 | #ifdef CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK |
Tejun Heo | fb435d5 | 2009-08-14 15:00:51 +0900 | [diff] [blame] | 106 | extern int __init pcpu_page_first_chunk(size_t reserved_size, |
Tejun Heo | d4b95f8 | 2009-07-04 08:10:59 +0900 | [diff] [blame] | 107 | pcpu_fc_alloc_fn_t alloc_fn, |
| 108 | pcpu_fc_free_fn_t free_fn, |
| 109 | pcpu_fc_populate_pte_fn_t populate_pte_fn); |
Tejun Heo | 08fc458 | 2009-08-14 15:00:49 +0900 | [diff] [blame] | 110 | #endif |
Tejun Heo | d4b95f8 | 2009-07-04 08:10:59 +0900 | [diff] [blame] | 111 | |
Rusty Russell | e0fdb0e | 2009-10-29 22:34:15 +0900 | [diff] [blame] | 112 | extern void __percpu *__alloc_reserved_percpu(size_t size, size_t align); |
Thomas Gleixner | 383776f | 2017-02-27 15:37:36 +0100 | [diff] [blame] | 113 | extern bool __is_kernel_percpu_address(unsigned long addr, unsigned long *can_addr); |
Tejun Heo | 10fad5e | 2010-03-10 18:57:54 +0900 | [diff] [blame] | 114 | extern bool is_kernel_percpu_address(unsigned long addr); |
Tejun Heo | f2a8205 | 2009-02-20 16:29:08 +0900 | [diff] [blame] | 115 | |
Tejun Heo | bbddff0 | 2010-09-03 18:22:48 +0200 | [diff] [blame] | 116 | #if !defined(CONFIG_SMP) || !defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) |
Tejun Heo | e74e396 | 2009-03-30 19:07:44 +0900 | [diff] [blame] | 117 | extern void __init setup_per_cpu_areas(void); |
| 118 | #endif |
Tejun Heo | 099a19d | 2010-06-27 18:50:00 +0200 | [diff] [blame] | 119 | extern void __init percpu_init_late(void); |
Tejun Heo | e74e396 | 2009-03-30 19:07:44 +0900 | [diff] [blame] | 120 | |
Tejun Heo | 5835d96 | 2014-09-02 14:46:04 -0400 | [diff] [blame] | 121 | extern void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp); |
Tejun Heo | de380b5 | 2010-03-24 17:06:43 +0900 | [diff] [blame] | 122 | extern void __percpu *__alloc_percpu(size_t size, size_t align); |
| 123 | extern void free_percpu(void __percpu *__pdata); |
| 124 | extern phys_addr_t per_cpu_ptr_to_phys(void *addr); |
| 125 | |
Tejun Heo | 5835d96 | 2014-09-02 14:46:04 -0400 | [diff] [blame] | 126 | #define alloc_percpu_gfp(type, gfp) \ |
| 127 | (typeof(type) __percpu *)__alloc_percpu_gfp(sizeof(type), \ |
| 128 | __alignof__(type), gfp) |
| 129 | #define alloc_percpu(type) \ |
| 130 | (typeof(type) __percpu *)__alloc_percpu(sizeof(type), \ |
| 131 | __alignof__(type)) |
Tejun Heo | f2a8205 | 2009-02-20 16:29:08 +0900 | [diff] [blame] | 132 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 133 | #endif /* __LINUX_PERCPU_H */ |