aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/setup_percpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/setup_percpu.c')
-rw-r--r--arch/x86/kernel/setup_percpu.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index dd4eabc747c8..efa615f2bf43 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -42,6 +42,19 @@ unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = {
42}; 42};
43EXPORT_SYMBOL(__per_cpu_offset); 43EXPORT_SYMBOL(__per_cpu_offset);
44 44
45/*
46 * On x86_64 symbols referenced from code should be reachable using
47 * 32bit relocations. Reserve space for static percpu variables in
48 * modules so that they are always served from the first chunk which
49 * is located at the percpu segment base. On x86_32, anything can
50 * address anywhere. No need to reserve space in the first chunk.
51 */
52#ifdef CONFIG_X86_64
53#define PERCPU_FIRST_CHUNK_RESERVE PERCPU_MODULE_RESERVE
54#else
55#define PERCPU_FIRST_CHUNK_RESERVE 0
56#endif
57
45/** 58/**
46 * pcpu_need_numa - determine percpu allocation needs to consider NUMA 59 * pcpu_need_numa - determine percpu allocation needs to consider NUMA
47 * 60 *
@@ -141,7 +154,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size)
141{ 154{
142 static struct vm_struct vm; 155 static struct vm_struct vm;
143 pg_data_t *last; 156 pg_data_t *last;
144 size_t ptrs_size; 157 size_t ptrs_size, dyn_size;
145 unsigned int cpu; 158 unsigned int cpu;
146 ssize_t ret; 159 ssize_t ret;
147 160
@@ -169,12 +182,14 @@ proceed:
169 * Currently supports only single page. Supporting multiple 182 * Currently supports only single page. Supporting multiple
170 * pages won't be too difficult if it ever becomes necessary. 183 * pages won't be too difficult if it ever becomes necessary.
171 */ 184 */
172 pcpur_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); 185 pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
186 PERCPU_DYNAMIC_RESERVE);
173 if (pcpur_size > PMD_SIZE) { 187 if (pcpur_size > PMD_SIZE) {
174 pr_warning("PERCPU: static data is larger than large page, " 188 pr_warning("PERCPU: static data is larger than large page, "
175 "can't use large page\n"); 189 "can't use large page\n");
176 return -EINVAL; 190 return -EINVAL;
177 } 191 }
192 dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
178 193
179 /* allocate pointer array and alloc large pages */ 194 /* allocate pointer array and alloc large pages */
180 ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); 195 ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
@@ -217,8 +232,9 @@ proceed:
217 pr_info("PERCPU: Remapped at %p with large pages, static data " 232 pr_info("PERCPU: Remapped at %p with large pages, static data "
218 "%zu bytes\n", vm.addr, static_size); 233 "%zu bytes\n", vm.addr, static_size);
219 234
220 ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, 0, PMD_SIZE, 235 ret = pcpu_setup_first_chunk(pcpur_get_page, static_size,
221 pcpur_size - static_size, vm.addr, NULL); 236 PERCPU_FIRST_CHUNK_RESERVE,
237 PMD_SIZE, dyn_size, vm.addr, NULL);
222 goto out_free_ar; 238 goto out_free_ar;
223 239
224enomem: 240enomem:
@@ -276,9 +292,10 @@ static ssize_t __init setup_pcpu_embed(size_t static_size)
276 return -EINVAL; 292 return -EINVAL;
277 293
278 /* allocate and copy */ 294 /* allocate and copy */
279 pcpue_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); 295 pcpue_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
296 PERCPU_DYNAMIC_RESERVE);
280 pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); 297 pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE);
281 dyn_size = pcpue_size - static_size; 298 dyn_size = pcpue_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
282 299
283 pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, 300 pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size,
284 PAGE_SIZE); 301 PAGE_SIZE);
@@ -297,7 +314,8 @@ static ssize_t __init setup_pcpu_embed(size_t static_size)
297 pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", 314 pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n",
298 pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size); 315 pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size);
299 316
300 return pcpu_setup_first_chunk(pcpue_get_page, static_size, 0, 317 return pcpu_setup_first_chunk(pcpue_get_page, static_size,
318 PERCPU_FIRST_CHUNK_RESERVE,
301 pcpue_unit_size, dyn_size, 319 pcpue_unit_size, dyn_size,
302 pcpue_ptr, NULL); 320 pcpue_ptr, NULL);
303} 321}
@@ -356,8 +374,9 @@ static ssize_t __init setup_pcpu_4k(size_t static_size)
356 pr_info("PERCPU: Allocated %d 4k pages, static data %zu bytes\n", 374 pr_info("PERCPU: Allocated %d 4k pages, static data %zu bytes\n",
357 pcpu4k_nr_static_pages, static_size); 375 pcpu4k_nr_static_pages, static_size);
358 376
359 ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size, 0, -1, -1, 377 ret = pcpu_setup_first_chunk(pcpu4k_get_page, static_size,
360 NULL, pcpu4k_populate_pte); 378 PERCPU_FIRST_CHUNK_RESERVE, -1, -1, NULL,
379 pcpu4k_populate_pte);
361 goto out_free_ar; 380 goto out_free_ar;
362 381
363enomem: 382enomem: