aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yhlu.kernel@gmail.com>2008-08-19 23:49:45 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-16 10:52:03 -0400
commit1f8ff037a871690c762d267d8a052529d3102fc9 (patch)
tree1b0ce2fdcca21c06fc2b806964670ee0a3ffeab4
parent1f3fcd4b1adc972d5c6a34cfed98931c46575b49 (diff)
x86: alloc dyn_array all together
so could spare some memory with small alignment in bootmem also tighten the alignment checking, and make print out less debug info. Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/setup_percpu.c16
-rw-r--r--include/linux/init.h2
-rw-r--r--init/main.c65
3 files changed, 62 insertions, 21 deletions
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 13ba7a83808d..2b7dab699e83 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -140,26 +140,31 @@ static void __init setup_cpu_pda_map(void)
140 */ 140 */
141void __init setup_per_cpu_areas(void) 141void __init setup_per_cpu_areas(void)
142{ 142{
143 ssize_t size, old_size; 143 ssize_t size, old_size, da_size;
144 char *ptr; 144 char *ptr;
145 int cpu; 145 int cpu;
146 unsigned long align = 1;
146 147
147 /* Setup cpu_pda map */ 148 /* Setup cpu_pda map */
148 setup_cpu_pda_map(); 149 setup_cpu_pda_map();
149 150
150 /* Copy section for each CPU (we discard the original) */ 151 /* Copy section for each CPU (we discard the original) */
151 old_size = PERCPU_ENOUGH_ROOM; 152 old_size = PERCPU_ENOUGH_ROOM;
152 size = old_size + per_cpu_dyn_array_size(); 153 da_size = per_cpu_dyn_array_size(&align);
154 align = max_t(unsigned long, PAGE_SIZE, align);
155 size = roundup(old_size + da_size, align);
153 printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n", 156 printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
154 size); 157 size);
155 158
156 for_each_possible_cpu(cpu) { 159 for_each_possible_cpu(cpu) {
157#ifndef CONFIG_NEED_MULTIPLE_NODES 160#ifndef CONFIG_NEED_MULTIPLE_NODES
158 ptr = alloc_bootmem_pages(size); 161 ptr = __alloc_bootmem(size, align,
162 __pa(MAX_DMA_ADDRESS));
159#else 163#else
160 int node = early_cpu_to_node(cpu); 164 int node = early_cpu_to_node(cpu);
161 if (!node_online(node) || !NODE_DATA(node)) { 165 if (!node_online(node) || !NODE_DATA(node)) {
162 ptr = alloc_bootmem_pages(size); 166 ptr = __alloc_bootmem(size, align,
167 __pa(MAX_DMA_ADDRESS));
163 printk(KERN_INFO 168 printk(KERN_INFO
164 "cpu %d has no node %d or node-local memory\n", 169 "cpu %d has no node %d or node-local memory\n",
165 cpu, node); 170 cpu, node);
@@ -168,7 +173,8 @@ void __init setup_per_cpu_areas(void)
168 cpu, __pa(ptr)); 173 cpu, __pa(ptr));
169 } 174 }
170 else { 175 else {
171 ptr = alloc_bootmem_pages_node(NODE_DATA(node), size); 176 ptr = __alloc_bootmem_node(NODE_DATA(node), size, align,
177 __pa(MAX_DMA_ADDRESS));
172 if (ptr) 178 if (ptr)
173 printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n", 179 printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
174 cpu, node, __pa(ptr)); 180 cpu, node, __pa(ptr));
diff --git a/include/linux/init.h b/include/linux/init.h
index 332806826b8e..59fbb4aaba6a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -288,7 +288,7 @@ extern struct dyn_array *__per_cpu_dyn_array_start[], *__per_cpu_dyn_array_end[]
288 DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, nameX, nrX, alignX, init_workX) 288 DEFINE_PER_CPU_DYN_ARRAY_ADDR(nameX, nameX, nrX, alignX, init_workX)
289 289
290extern void pre_alloc_dyn_array(void); 290extern void pre_alloc_dyn_array(void);
291extern unsigned long per_cpu_dyn_array_size(void); 291extern unsigned long per_cpu_dyn_array_size(unsigned long *align);
292extern void per_cpu_alloc_dyn_array(int cpu, char *ptr); 292extern void per_cpu_alloc_dyn_array(int cpu, char *ptr);
293#endif /* __ASSEMBLY__ */ 293#endif /* __ASSEMBLY__ */
294 294
diff --git a/init/main.c b/init/main.c
index 416bca4f734f..ab97d0877acc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -394,10 +394,14 @@ static void __init setup_per_cpu_areas(void)
394 unsigned long size, i, old_size; 394 unsigned long size, i, old_size;
395 char *ptr; 395 char *ptr;
396 unsigned long nr_possible_cpus = num_possible_cpus(); 396 unsigned long nr_possible_cpus = num_possible_cpus();
397 unsigned long align = 1;
398 unsigned da_size;
397 399
398 /* Copy section for each CPU (we discard the original) */ 400 /* Copy section for each CPU (we discard the original) */
399 old_size = PERCPU_ENOUGH_ROOM; 401 old_size = PERCPU_ENOUGH_ROOM;
400 size = ALIGN(old_size + per_cpu_dyn_array_size(), PAGE_SIZE); 402 da_size = per_cpu_dyn_array_size(&align);
403 align = max_t(unsigned long, PAGE_SIZE, align);
404 size = ALIGN(old_size + da_size, align);
401 ptr = alloc_bootmem_pages(size * nr_possible_cpus); 405 ptr = alloc_bootmem_pages(size * nr_possible_cpus);
402 406
403 for_each_possible_cpu(i) { 407 for_each_possible_cpu(i) {
@@ -541,45 +545,78 @@ void __init __weak thread_info_cache_init(void)
541void pre_alloc_dyn_array(void) 545void pre_alloc_dyn_array(void)
542{ 546{
543#ifdef CONFIG_HAVE_DYN_ARRAY 547#ifdef CONFIG_HAVE_DYN_ARRAY
544 unsigned long size, phys = 0; 548 unsigned long total_size = 0, size, phys;
549 unsigned long max_align = 1;
545 struct dyn_array **daa; 550 struct dyn_array **daa;
551 char *ptr;
546 552
553 /* get the total size at first */
547 for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) { 554 for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
548 struct dyn_array *da = *daa; 555 struct dyn_array *da = *daa;
549 556
550 size = da->size * (*da->nr); 557 size = da->size * (*da->nr);
551 print_fn_descriptor_symbol("dyna_array %s ", da->name); 558 print_fn_descriptor_symbol("dyn_array %s ", da->name);
552 printk(KERN_CONT "size:%#lx nr:%d align:%#lx", 559 printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
553 da->size, *da->nr, da->align); 560 da->size, *da->nr, da->align);
554 *da->name = __alloc_bootmem(size, da->align, phys); 561 total_size += roundup(size, da->align);
555 phys = virt_to_phys(*da->name); 562 if (da->align > max_align)
563 max_align = da->align;
564 }
565 if (total_size)
566 printk(KERN_DEBUG "dyn_array total_size: %#lx\n",
567 total_size);
568 else
569 return;
570
571 /* allocate them all together */
572 max_align = max_t(unsigned long, max_align, PAGE_SIZE);
573 ptr = __alloc_bootmem_nopanic(total_size, max_align, 0);
574 if (!ptr)
575 panic("Can not alloc dyn_alloc\n");
576
577 phys = virt_to_phys(ptr);
578 for (daa = __dyn_array_start ; daa < __dyn_array_end; daa++) {
579 struct dyn_array *da = *daa;
580
581 size = da->size * (*da->nr);
582 print_fn_descriptor_symbol("dyn_array %s ", da->name);
583
584 phys = roundup(phys, da->align);
585 *da->name = phys_to_virt(phys);
556 printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size); 586 printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
557 587
588 phys += size;
589
558 if (da->init_work) 590 if (da->init_work)
559 da->init_work(da); 591 da->init_work(da);
560 } 592 }
561#endif 593#endif
562} 594}
563 595
564unsigned long per_cpu_dyn_array_size(void) 596unsigned long per_cpu_dyn_array_size(unsigned long *align)
565{ 597{
566 unsigned long total_size = 0; 598 unsigned long total_size = 0;
567#ifdef CONFIG_HAVE_DYN_ARRAY 599#ifdef CONFIG_HAVE_DYN_ARRAY
568 unsigned long size; 600 unsigned long size;
569 struct dyn_array **daa; 601 struct dyn_array **daa;
602 unsigned max_align = 1;
570 603
571 for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { 604 for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
572 struct dyn_array *da = *daa; 605 struct dyn_array *da = *daa;
573 606
574 size = da->size * (*da->nr); 607 size = da->size * (*da->nr);
575 print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name); 608 print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);
576 printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n", 609 printk(KERN_CONT "size:%#lx nr:%d align:%#lx\n",
577 da->size, *da->nr, da->align); 610 da->size, *da->nr, da->align);
578 total_size += roundup(size, da->align); 611 total_size += roundup(size, da->align);
612 if (da->align > max_align)
613 max_align = da->align;
579 } 614 }
580 if (total_size) 615 if (total_size) {
581 printk(KERN_DEBUG "per_cpu_dyna_array total_size: %#lx\n", 616 printk(KERN_DEBUG "per_cpu_dyn_array total_size: %#lx\n",
582 total_size); 617 total_size);
618 *align = max_align;
619 }
583#endif 620#endif
584 return total_size; 621 return total_size;
585} 622}
@@ -593,14 +630,11 @@ void per_cpu_alloc_dyn_array(int cpu, char *ptr)
593 void **array; 630 void **array;
594 631
595 phys = virt_to_phys(ptr); 632 phys = virt_to_phys(ptr);
596
597 for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) { 633 for (daa = __per_cpu_dyn_array_start ; daa < __per_cpu_dyn_array_end; daa++) {
598 struct dyn_array *da = *daa; 634 struct dyn_array *da = *daa;
599 635
600 size = da->size * (*da->nr); 636 size = da->size * (*da->nr);
601 print_fn_descriptor_symbol("per_cpu_dyna_array %s ", da->name); 637 print_fn_descriptor_symbol("per_cpu_dyn_array %s ", da->name);
602 printk(KERN_CONT "size:%#lx nr:%d align:%#lx",
603 da->size, *da->nr, da->align);
604 638
605 phys = roundup(phys, da->align); 639 phys = roundup(phys, da->align);
606 addr = (unsigned long)da->name; 640 addr = (unsigned long)da->name;
@@ -608,7 +642,8 @@ void per_cpu_alloc_dyn_array(int cpu, char *ptr)
608 array = (void **)addr; 642 array = (void **)addr;
609 *array = phys_to_virt(phys); 643 *array = phys_to_virt(phys);
610 *da->name = *array; /* so init_work could use it directly */ 644 *da->name = *array; /* so init_work could use it directly */
611 printk(KERN_CONT " %p ==> [%#lx - %#lx]\n", array, phys, phys + size); 645 printk(KERN_CONT " ==> [%#lx - %#lx]\n", phys, phys + size);
646
612 phys += size; 647 phys += size;
613 648
614 if (da->init_work) { 649 if (da->init_work) {