diff options
Diffstat (limited to 'mm/percpu.c')
-rw-r--r-- | mm/percpu.c | 85 |
1 files changed, 47 insertions, 38 deletions
diff --git a/mm/percpu.c b/mm/percpu.c index e0aa8ae7bde7..bd4130a69bbc 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
@@ -76,6 +76,11 @@ | |||
76 | #include <asm/tlbflush.h> | 76 | #include <asm/tlbflush.h> |
77 | #include <asm/io.h> | 77 | #include <asm/io.h> |
78 | 78 | ||
79 | #define CREATE_TRACE_POINTS | ||
80 | #include <trace/events/percpu.h> | ||
81 | |||
82 | #include "percpu-internal.h" | ||
83 | |||
79 | #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ | 84 | #define PCPU_SLOT_BASE_SHIFT 5 /* 1-31 shares the same slot */ |
80 | #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ | 85 | #define PCPU_DFL_MAP_ALLOC 16 /* start a map with 16 ents */ |
81 | #define PCPU_ATOMIC_MAP_MARGIN_LOW 32 | 86 | #define PCPU_ATOMIC_MAP_MARGIN_LOW 32 |
@@ -103,53 +108,35 @@ | |||
103 | #define __pcpu_ptr_to_addr(ptr) (void __force *)(ptr) | 108 | #define __pcpu_ptr_to_addr(ptr) (void __force *)(ptr) |
104 | #endif /* CONFIG_SMP */ | 109 | #endif /* CONFIG_SMP */ |
105 | 110 | ||
106 | struct pcpu_chunk { | 111 | static int pcpu_unit_pages __ro_after_init; |
107 | struct list_head list; /* linked to pcpu_slot lists */ | 112 | static int pcpu_unit_size __ro_after_init; |
108 | int free_size; /* free bytes in the chunk */ | 113 | static int pcpu_nr_units __ro_after_init; |
109 | int contig_hint; /* max contiguous size hint */ | 114 | static int pcpu_atom_size __ro_after_init; |
110 | void *base_addr; /* base address of this chunk */ | 115 | int pcpu_nr_slots __ro_after_init; |
111 | 116 | static size_t pcpu_chunk_struct_size __ro_after_init; | |
112 | int map_used; /* # of map entries used before the sentry */ | ||
113 | int map_alloc; /* # of map entries allocated */ | ||
114 | int *map; /* allocation map */ | ||
115 | struct list_head map_extend_list;/* on pcpu_map_extend_chunks */ | ||
116 | |||
117 | void *data; /* chunk data */ | ||
118 | int first_free; /* no free below this */ | ||
119 | bool immutable; /* no [de]population allowed */ | ||
120 | int nr_populated; /* # of populated pages */ | ||
121 | unsigned long populated[]; /* populated bitmap */ | ||
122 | }; | ||
123 | |||
124 | static int pcpu_unit_pages __read_mostly; | ||
125 | static int pcpu_unit_size __read_mostly; | ||
126 | static int pcpu_nr_units __read_mostly; | ||
127 | static int pcpu_atom_size __read_mostly; | ||
128 | static int pcpu_nr_slots __read_mostly; | ||
129 | static size_t pcpu_chunk_struct_size __read_mostly; | ||
130 | 117 | ||
131 | /* cpus with the lowest and highest unit addresses */ | 118 | /* cpus with the lowest and highest unit addresses */ |
132 | static unsigned int pcpu_low_unit_cpu __read_mostly; | 119 | static unsigned int pcpu_low_unit_cpu __ro_after_init; |
133 | static unsigned int pcpu_high_unit_cpu __read_mostly; | 120 | static unsigned int pcpu_high_unit_cpu __ro_after_init; |
134 | 121 | ||
135 | /* the address of the first chunk which starts with the kernel static area */ | 122 | /* the address of the first chunk which starts with the kernel static area */ |
136 | void *pcpu_base_addr __read_mostly; | 123 | void *pcpu_base_addr __ro_after_init; |
137 | EXPORT_SYMBOL_GPL(pcpu_base_addr); | 124 | EXPORT_SYMBOL_GPL(pcpu_base_addr); |
138 | 125 | ||
139 | static const int *pcpu_unit_map __read_mostly; /* cpu -> unit */ | 126 | static const int *pcpu_unit_map __ro_after_init; /* cpu -> unit */ |
140 | const unsigned long *pcpu_unit_offsets __read_mostly; /* cpu -> unit offset */ | 127 | const unsigned long *pcpu_unit_offsets __ro_after_init; /* cpu -> unit offset */ |
141 | 128 | ||
142 | /* group information, used for vm allocation */ | 129 | /* group information, used for vm allocation */ |
143 | static int pcpu_nr_groups __read_mostly; | 130 | static int pcpu_nr_groups __ro_after_init; |
144 | static const unsigned long *pcpu_group_offsets __read_mostly; | 131 | static const unsigned long *pcpu_group_offsets __ro_after_init; |
145 | static const size_t *pcpu_group_sizes __read_mostly; | 132 | static const size_t *pcpu_group_sizes __ro_after_init; |
146 | 133 | ||
147 | /* | 134 | /* |
148 | * The first chunk which always exists. Note that unlike other | 135 | * The first chunk which always exists. Note that unlike other |
149 | * chunks, this one can be allocated and mapped in several different | 136 | * chunks, this one can be allocated and mapped in several different |
150 | * ways and thus often doesn't live in the vmalloc area. | 137 | * ways and thus often doesn't live in the vmalloc area. |
151 | */ | 138 | */ |
152 | static struct pcpu_chunk *pcpu_first_chunk; | 139 | struct pcpu_chunk *pcpu_first_chunk __ro_after_init; |
153 | 140 | ||
154 | /* | 141 | /* |
155 | * Optional reserved chunk. This chunk reserves part of the first | 142 | * Optional reserved chunk. This chunk reserves part of the first |
@@ -158,13 +145,13 @@ static struct pcpu_chunk *pcpu_first_chunk; | |||
158 | * area doesn't exist, the following variables contain NULL and 0 | 145 | * area doesn't exist, the following variables contain NULL and 0 |
159 | * respectively. | 146 | * respectively. |
160 | */ | 147 | */ |
161 | static struct pcpu_chunk *pcpu_reserved_chunk; | 148 | struct pcpu_chunk *pcpu_reserved_chunk __ro_after_init; |
162 | static int pcpu_reserved_chunk_limit; | 149 | static int pcpu_reserved_chunk_limit __ro_after_init; |
163 | 150 | ||
164 | static DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */ | 151 | DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */ |
165 | static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */ | 152 | static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */ |
166 | 153 | ||
167 | static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */ | 154 | struct list_head *pcpu_slot __ro_after_init; /* chunk list slots */ |
168 | 155 | ||
169 | /* chunks which need their map areas extended, protected by pcpu_lock */ | 156 | /* chunks which need their map areas extended, protected by pcpu_lock */ |
170 | static LIST_HEAD(pcpu_map_extend_chunks); | 157 | static LIST_HEAD(pcpu_map_extend_chunks); |
@@ -672,6 +659,9 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme, | |||
672 | int to_free = 0; | 659 | int to_free = 0; |
673 | int *p; | 660 | int *p; |
674 | 661 | ||
662 | lockdep_assert_held(&pcpu_lock); | ||
663 | pcpu_stats_area_dealloc(chunk); | ||
664 | |||
675 | freeme |= 1; /* we are searching for <given offset, in use> pair */ | 665 | freeme |= 1; /* we are searching for <given offset, in use> pair */ |
676 | 666 | ||
677 | i = 0; | 667 | i = 0; |
@@ -735,6 +725,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void) | |||
735 | chunk->map[0] = 0; | 725 | chunk->map[0] = 0; |
736 | chunk->map[1] = pcpu_unit_size | 1; | 726 | chunk->map[1] = pcpu_unit_size | 1; |
737 | chunk->map_used = 1; | 727 | chunk->map_used = 1; |
728 | chunk->has_reserved = false; | ||
738 | 729 | ||
739 | INIT_LIST_HEAD(&chunk->list); | 730 | INIT_LIST_HEAD(&chunk->list); |
740 | INIT_LIST_HEAD(&chunk->map_extend_list); | 731 | INIT_LIST_HEAD(&chunk->map_extend_list); |
@@ -965,8 +956,10 @@ restart: | |||
965 | * tasks to create chunks simultaneously. Serialize and create iff | 956 | * tasks to create chunks simultaneously. Serialize and create iff |
966 | * there's still no empty chunk after grabbing the mutex. | 957 | * there's still no empty chunk after grabbing the mutex. |
967 | */ | 958 | */ |
968 | if (is_atomic) | 959 | if (is_atomic) { |
960 | err = "atomic alloc failed, no space left"; | ||
969 | goto fail; | 961 | goto fail; |
962 | } | ||
970 | 963 | ||
971 | if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) { | 964 | if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) { |
972 | chunk = pcpu_create_chunk(); | 965 | chunk = pcpu_create_chunk(); |
@@ -984,6 +977,7 @@ restart: | |||
984 | goto restart; | 977 | goto restart; |
985 | 978 | ||
986 | area_found: | 979 | area_found: |
980 | pcpu_stats_area_alloc(chunk, size); | ||
987 | spin_unlock_irqrestore(&pcpu_lock, flags); | 981 | spin_unlock_irqrestore(&pcpu_lock, flags); |
988 | 982 | ||
989 | /* populate if not all pages are already there */ | 983 | /* populate if not all pages are already there */ |
@@ -1026,11 +1020,17 @@ area_found: | |||
1026 | 1020 | ||
1027 | ptr = __addr_to_pcpu_ptr(chunk->base_addr + off); | 1021 | ptr = __addr_to_pcpu_ptr(chunk->base_addr + off); |
1028 | kmemleak_alloc_percpu(ptr, size, gfp); | 1022 | kmemleak_alloc_percpu(ptr, size, gfp); |
1023 | |||
1024 | trace_percpu_alloc_percpu(reserved, is_atomic, size, align, | ||
1025 | chunk->base_addr, off, ptr); | ||
1026 | |||
1029 | return ptr; | 1027 | return ptr; |
1030 | 1028 | ||
1031 | fail_unlock: | 1029 | fail_unlock: |
1032 | spin_unlock_irqrestore(&pcpu_lock, flags); | 1030 | spin_unlock_irqrestore(&pcpu_lock, flags); |
1033 | fail: | 1031 | fail: |
1032 | trace_percpu_alloc_percpu_fail(reserved, is_atomic, size, align); | ||
1033 | |||
1034 | if (!is_atomic && warn_limit) { | 1034 | if (!is_atomic && warn_limit) { |
1035 | pr_warn("allocation failed, size=%zu align=%zu atomic=%d, %s\n", | 1035 | pr_warn("allocation failed, size=%zu align=%zu atomic=%d, %s\n", |
1036 | size, align, is_atomic, err); | 1036 | size, align, is_atomic, err); |
@@ -1280,6 +1280,8 @@ void free_percpu(void __percpu *ptr) | |||
1280 | } | 1280 | } |
1281 | } | 1281 | } |
1282 | 1282 | ||
1283 | trace_percpu_free_percpu(chunk->base_addr, off, ptr); | ||
1284 | |||
1283 | spin_unlock_irqrestore(&pcpu_lock, flags); | 1285 | spin_unlock_irqrestore(&pcpu_lock, flags); |
1284 | } | 1286 | } |
1285 | EXPORT_SYMBOL_GPL(free_percpu); | 1287 | EXPORT_SYMBOL_GPL(free_percpu); |
@@ -1656,6 +1658,8 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, | |||
1656 | pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) + | 1658 | pcpu_chunk_struct_size = sizeof(struct pcpu_chunk) + |
1657 | BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long); | 1659 | BITS_TO_LONGS(pcpu_unit_pages) * sizeof(unsigned long); |
1658 | 1660 | ||
1661 | pcpu_stats_save_ai(ai); | ||
1662 | |||
1659 | /* | 1663 | /* |
1660 | * Allocate chunk slots. The additional last slot is for | 1664 | * Allocate chunk slots. The additional last slot is for |
1661 | * empty chunks. | 1665 | * empty chunks. |
@@ -1699,6 +1703,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, | |||
1699 | if (schunk->free_size) | 1703 | if (schunk->free_size) |
1700 | schunk->map[++schunk->map_used] = ai->static_size + schunk->free_size; | 1704 | schunk->map[++schunk->map_used] = ai->static_size + schunk->free_size; |
1701 | schunk->map[schunk->map_used] |= 1; | 1705 | schunk->map[schunk->map_used] |= 1; |
1706 | schunk->has_reserved = true; | ||
1702 | 1707 | ||
1703 | /* init dynamic chunk if necessary */ | 1708 | /* init dynamic chunk if necessary */ |
1704 | if (dyn_size) { | 1709 | if (dyn_size) { |
@@ -1717,6 +1722,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, | |||
1717 | dchunk->map[1] = pcpu_reserved_chunk_limit; | 1722 | dchunk->map[1] = pcpu_reserved_chunk_limit; |
1718 | dchunk->map[2] = (pcpu_reserved_chunk_limit + dchunk->free_size) | 1; | 1723 | dchunk->map[2] = (pcpu_reserved_chunk_limit + dchunk->free_size) | 1; |
1719 | dchunk->map_used = 2; | 1724 | dchunk->map_used = 2; |
1725 | dchunk->has_reserved = true; | ||
1720 | } | 1726 | } |
1721 | 1727 | ||
1722 | /* link the first chunk in */ | 1728 | /* link the first chunk in */ |
@@ -1725,6 +1731,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, | |||
1725 | pcpu_count_occupied_pages(pcpu_first_chunk, 1); | 1731 | pcpu_count_occupied_pages(pcpu_first_chunk, 1); |
1726 | pcpu_chunk_relocate(pcpu_first_chunk, -1); | 1732 | pcpu_chunk_relocate(pcpu_first_chunk, -1); |
1727 | 1733 | ||
1734 | pcpu_stats_chunk_alloc(); | ||
1735 | trace_percpu_create_chunk(base_addr); | ||
1736 | |||
1728 | /* we're done */ | 1737 | /* we're done */ |
1729 | pcpu_base_addr = base_addr; | 1738 | pcpu_base_addr = base_addr; |
1730 | return 0; | 1739 | return 0; |