aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/setup.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-02-26 20:35:44 -0500
committerH. Peter Anvin <hpa@zytor.com>2009-03-14 18:37:14 -0400
commit93dbda7cbcd70a0bd1a99f39f44a9ccde8ab9040 (patch)
tree132347cd952fb8281247c1fb38ec1c608c19a3f6 /arch/x86/kernel/setup.c
parentb9719a4d9cfa5d46fa6a1eb3e3fc2238e7981e4d (diff)
x86: add brk allocation for very, very early allocations
Impact: new interface Add a brk()-like allocator which effectively extends the bss in order to allow very early code to do dynamic allocations. This is better than using statically allocated arrays for data in subsystems which may never get used. The space for brk allocations is in the bss ELF segment, so that the space is mapped properly by the code which maps the kernel, and so that bootloaders keep the space free rather than putting a ramdisk or something into it. The bss itself, delimited by __bss_stop, ends before the brk area (__brk_base to __brk_limit). The kernel text, data and bss is reserved up to __bss_stop. Any brk-allocated data is reserved separately just before the kernel pagetable is built, as that code allocates from unreserved spaces in the e820 map, potentially allocating from any unused brk memory. Ultimately any unused memory in the brk area is used in the general kernel memory pool. Initially the brk space is set to 1MB, which is probably much larger than any user needs (the largest current user is i386 head_32.S's code to build the pagetables to map the kernel, which can get fairly large with a big kernel image and no PSE support). So long as the system has sufficient memory for the bootloader to reserve the kernel+1MB brk, there are no bad effects resulting from an over-large brk. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r--arch/x86/kernel/setup.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f28c56e6bf9..e6b742d2a3f 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -114,6 +114,9 @@
114 114
115unsigned int boot_cpu_id __read_mostly; 115unsigned int boot_cpu_id __read_mostly;
116 116
117static __initdata unsigned long _brk_start = (unsigned long)__brk_base;
118unsigned long _brk_end = (unsigned long)__brk_base;
119
117#ifdef CONFIG_X86_64 120#ifdef CONFIG_X86_64
118int default_cpu_present_to_apicid(int mps_cpu) 121int default_cpu_present_to_apicid(int mps_cpu)
119{ 122{
@@ -337,6 +340,34 @@ static void __init relocate_initrd(void)
337} 340}
338#endif 341#endif
339 342
343void * __init extend_brk(size_t size, size_t align)
344{
345 size_t mask = align - 1;
346 void *ret;
347
348 BUG_ON(_brk_start == 0);
349 BUG_ON(align & mask);
350
351 _brk_end = (_brk_end + mask) & ~mask;
352 BUG_ON((char *)(_brk_end + size) > __brk_limit);
353
354 ret = (void *)_brk_end;
355 _brk_end += size;
356
357 memset(ret, 0, size);
358
359 return ret;
360}
361
362static void __init reserve_brk(void)
363{
364 if (_brk_end > _brk_start)
365 reserve_early(__pa(_brk_start), __pa(_brk_end), "BRK");
366
367 /* Mark brk area as locked down and no longer taking any new allocations */
368 _brk_start = 0;
369}
370
340static void __init reserve_initrd(void) 371static void __init reserve_initrd(void)
341{ 372{
342 u64 ramdisk_image = boot_params.hdr.ramdisk_image; 373 u64 ramdisk_image = boot_params.hdr.ramdisk_image;
@@ -717,11 +748,7 @@ void __init setup_arch(char **cmdline_p)
717 init_mm.start_code = (unsigned long) _text; 748 init_mm.start_code = (unsigned long) _text;
718 init_mm.end_code = (unsigned long) _etext; 749 init_mm.end_code = (unsigned long) _etext;
719 init_mm.end_data = (unsigned long) _edata; 750 init_mm.end_data = (unsigned long) _edata;
720#ifdef CONFIG_X86_32 751 init_mm.brk = _brk_end;
721 init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
722#else
723 init_mm.brk = (unsigned long) &_end;
724#endif
725 752
726 code_resource.start = virt_to_phys(_text); 753 code_resource.start = virt_to_phys(_text);
727 code_resource.end = virt_to_phys(_etext)-1; 754 code_resource.end = virt_to_phys(_etext)-1;
@@ -842,6 +869,8 @@ void __init setup_arch(char **cmdline_p)
842 setup_bios_corruption_check(); 869 setup_bios_corruption_check();
843#endif 870#endif
844 871
872 reserve_brk();
873
845 /* max_pfn_mapped is updated here */ 874 /* max_pfn_mapped is updated here */
846 max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); 875 max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
847 max_pfn_mapped = max_low_pfn_mapped; 876 max_pfn_mapped = max_low_pfn_mapped;