aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/setup_percpu.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index ef3a2cd3fe64..38e2b2a470a5 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -241,24 +241,31 @@ static ssize_t __init setup_pcpu_remap(size_t static_size)
241 * Embedding allocator 241 * Embedding allocator
242 * 242 *
243 * The first chunk is sized to just contain the static area plus 243 * The first chunk is sized to just contain the static area plus
244 * PERCPU_DYNAMIC_RESERVE and allocated as a contiguous area using 244 * module and dynamic reserves, and allocated as a contiguous area
245 * bootmem allocator and used as-is without being mapped into vmalloc 245 * using bootmem allocator and used as-is without being mapped into
246 * area. This enables the first chunk to piggy back on the linear 246 * vmalloc area. This enables the first chunk to piggy back on the
247 * physical PMD mapping and doesn't add any additional pressure to 247 * linear physical PMD mapping and doesn't add any additional pressure
248 * TLB. 248 * to TLB. Note that if the needed size is smaller than the minimum
249 * unit size, the leftover is returned to the bootmem allocator.
249 */ 250 */
250static void *pcpue_ptr __initdata; 251static void *pcpue_ptr __initdata;
252static size_t pcpue_size __initdata;
251static size_t pcpue_unit_size __initdata; 253static size_t pcpue_unit_size __initdata;
252 254
253static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) 255static struct page * __init pcpue_get_page(unsigned int cpu, int pageno)
254{ 256{
255 return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size 257 size_t off = (size_t)pageno << PAGE_SHIFT;
256 + ((size_t)pageno << PAGE_SHIFT)); 258
259 if (off >= pcpue_size)
260 return NULL;
261
262 return virt_to_page(pcpue_ptr + cpu * pcpue_unit_size + off);
257} 263}
258 264
259static ssize_t __init setup_pcpu_embed(size_t static_size) 265static ssize_t __init setup_pcpu_embed(size_t static_size)
260{ 266{
261 unsigned int cpu; 267 unsigned int cpu;
268 size_t dyn_size;
262 269
263 /* 270 /*
264 * If large page isn't supported, there's no benefit in doing 271 * If large page isn't supported, there's no benefit in doing
@@ -269,25 +276,30 @@ static ssize_t __init setup_pcpu_embed(size_t static_size)
269 return -EINVAL; 276 return -EINVAL;
270 277
271 /* allocate and copy */ 278 /* allocate and copy */
272 pcpue_unit_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE); 279 pcpue_size = PFN_ALIGN(static_size + PERCPU_DYNAMIC_RESERVE);
273 pcpue_unit_size = max_t(size_t, pcpue_unit_size, PCPU_MIN_UNIT_SIZE); 280 pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE);
281 dyn_size = pcpue_size - static_size;
282
274 pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size, 283 pcpue_ptr = pcpu_alloc_bootmem(0, num_possible_cpus() * pcpue_unit_size,
275 PAGE_SIZE); 284 PAGE_SIZE);
276 if (!pcpue_ptr) 285 if (!pcpue_ptr)
277 return -ENOMEM; 286 return -ENOMEM;
278 287
279 for_each_possible_cpu(cpu) 288 for_each_possible_cpu(cpu) {
280 memcpy(pcpue_ptr + cpu * pcpue_unit_size, __per_cpu_load, 289 void *ptr = pcpue_ptr + cpu * pcpue_unit_size;
281 static_size); 290
291 free_bootmem(__pa(ptr + pcpue_size),
292 pcpue_unit_size - pcpue_size);
293 memcpy(ptr, __per_cpu_load, static_size);
294 }
282 295
283 /* we're ready, commit */ 296 /* we're ready, commit */
284 pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n", 297 pr_info("PERCPU: Embedded %zu pages at %p, static data %zu bytes\n",
285 pcpue_unit_size >> PAGE_SHIFT, pcpue_ptr, static_size); 298 pcpue_size >> PAGE_SHIFT, pcpue_ptr, static_size);
286 299
287 return pcpu_setup_first_chunk(pcpue_get_page, static_size, 300 return pcpu_setup_first_chunk(pcpue_get_page, static_size,
288 pcpue_unit_size, 301 pcpue_unit_size, dyn_size,
289 pcpue_unit_size - static_size, pcpue_ptr, 302 pcpue_ptr, NULL);
290 NULL);
291} 303}
292 304
293/* 305/*