aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/boot/header.S5
-rw-r--r--arch/x86/kernel/setup_32.c130
-rw-r--r--arch/x86/mm/discontig_32.c4
3 files changed, 112 insertions, 27 deletions
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 4cc5b0411db5..64ad9016585a 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -195,10 +195,13 @@ cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
195 # can be located anywhere in 195 # can be located anywhere in
196 # low memory 0x10000 or higher. 196 # low memory 0x10000 or higher.
197 197
198ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff 198ramdisk_max: .long 0x7fffffff
199 # (Header version 0x0203 or later) 199 # (Header version 0x0203 or later)
200 # The highest safe address for 200 # The highest safe address for
201 # the contents of an initrd 201 # the contents of an initrd
202 # The current kernel allows up to 4 GB,
203 # but leave it at 2 GB to avoid
204 # possible bootloader bugs.
202 205
203kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 206kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
204 #required for protected mode 207 #required for protected mode
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 3bce4af60bb6..6802a383077d 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -188,9 +188,9 @@ extern int root_mountflags;
188 188
189unsigned long saved_videomode; 189unsigned long saved_videomode;
190 190
191#define RAMDISK_IMAGE_START_MASK 0x07FF 191#define RAMDISK_IMAGE_START_MASK 0x07FF
192#define RAMDISK_PROMPT_FLAG 0x8000 192#define RAMDISK_PROMPT_FLAG 0x8000
193#define RAMDISK_LOAD_FLAG 0x4000 193#define RAMDISK_LOAD_FLAG 0x4000
194 194
195static char __initdata command_line[COMMAND_LINE_SIZE]; 195static char __initdata command_line[COMMAND_LINE_SIZE];
196 196
@@ -252,7 +252,7 @@ static int __init parse_mem(char *arg)
252 * trim the existing memory map. 252 * trim the existing memory map.
253 */ 253 */
254 unsigned long long mem_size; 254 unsigned long long mem_size;
255 255
256 mem_size = memparse(arg, &arg); 256 mem_size = memparse(arg, &arg);
257 limit_regions(mem_size); 257 limit_regions(mem_size);
258 user_defined_memmap = 1; 258 user_defined_memmap = 1;
@@ -391,7 +391,7 @@ static void __init reserve_ebda_region(void)
391 unsigned int addr; 391 unsigned int addr;
392 addr = get_bios_ebda(); 392 addr = get_bios_ebda();
393 if (addr) 393 if (addr)
394 reserve_bootmem(addr, PAGE_SIZE); 394 reserve_bootmem(addr, PAGE_SIZE);
395} 395}
396 396
397#ifndef CONFIG_NEED_MULTIPLE_NODES 397#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -496,6 +496,100 @@ static inline void __init reserve_crashkernel(void)
496{} 496{}
497#endif 497#endif
498 498
499#ifdef CONFIG_BLK_DEV_INITRD
500
501static bool do_relocate_initrd = false;
502
503static void __init reserve_initrd(void)
504{
505 unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
506 unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
507 unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
508 unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
509 unsigned long ramdisk_here;
510
511 initrd_start = 0;
512
513 if (!boot_params.hdr.type_of_loader ||
514 !ramdisk_image || !ramdisk_size)
515 return; /* No initrd provided by bootloader */
516
517 if (ramdisk_end < ramdisk_image) {
518 printk(KERN_ERR "initrd wraps around end of memory, "
519 "disabling initrd\n");
520 return;
521 }
522 if (ramdisk_size >= end_of_lowmem/2) {
523 printk(KERN_ERR "initrd too large to handle, "
524 "disabling initrd\n");
525 return;
526 }
527 if (ramdisk_end <= end_of_lowmem) {
528 /* All in lowmem, easy case */
529 reserve_bootmem(ramdisk_image, ramdisk_size);
530 initrd_start = ramdisk_image + PAGE_OFFSET;
531 initrd_end = initrd_start+ramdisk_size;
532 return;
533 }
534
535 /* We need to move the initrd down into lowmem */
536 ramdisk_here = (end_of_lowmem - ramdisk_size) & PAGE_MASK;
537
538 /* Note: this includes all the lowmem currently occupied by
539 the initrd, we rely on that fact to keep the data intact. */
540 reserve_bootmem(ramdisk_here, ramdisk_size);
541 initrd_start = ramdisk_here + PAGE_OFFSET;
542 initrd_end = initrd_start + ramdisk_size;
543
544 do_relocate_initrd = true;
545}
546
547#define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
548
549static void __init relocate_initrd(void)
550{
551 unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
552 unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
553 unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
554 unsigned long ramdisk_here;
555 unsigned long slop, clen, mapaddr;
556 char *p, *q;
557
558 if (!do_relocate_initrd)
559 return;
560
561 ramdisk_here = initrd_start - PAGE_OFFSET;
562
563 q = (char *)initrd_start;
564
565 /* Copy any lowmem portion of the initrd */
566 if (ramdisk_image < end_of_lowmem) {
567 clen = end_of_lowmem - ramdisk_image;
568 p = (char *)__va(ramdisk_image);
569 memcpy(q, p, clen);
570 q += clen;
571 ramdisk_image += clen;
572 ramdisk_size -= clen;
573 }
574
575 /* Copy the highmem portion of the initrd */
576 while (ramdisk_size) {
577 slop = ramdisk_image & ~PAGE_MASK;
578 clen = ramdisk_size;
579 if (clen > MAX_MAP_CHUNK-slop)
580 clen = MAX_MAP_CHUNK-slop;
581 mapaddr = ramdisk_image & PAGE_MASK;
582 p = bt_ioremap(mapaddr, clen+slop);
583 memcpy(q, p+slop, clen);
584 bt_iounmap(p, clen+slop);
585 q += clen;
586 ramdisk_image += clen;
587 ramdisk_size -= clen;
588 }
589}
590
591#endif /* CONFIG_BLK_DEV_INITRD */
592
499void __init setup_bootmem_allocator(void) 593void __init setup_bootmem_allocator(void)
500{ 594{
501 unsigned long bootmap_size; 595 unsigned long bootmap_size;
@@ -551,26 +645,10 @@ void __init setup_bootmem_allocator(void)
551 */ 645 */
552 find_smp_config(); 646 find_smp_config();
553#endif 647#endif
554 numa_kva_reserve();
555#ifdef CONFIG_BLK_DEV_INITRD 648#ifdef CONFIG_BLK_DEV_INITRD
556 if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) { 649 reserve_initrd();
557 unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
558 unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
559 unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
560 unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT;
561
562 if (ramdisk_end <= end_of_lowmem) {
563 reserve_bootmem(ramdisk_image, ramdisk_size);
564 initrd_start = ramdisk_image + PAGE_OFFSET;
565 initrd_end = initrd_start+ramdisk_size;
566 } else {
567 printk(KERN_ERR "initrd extends beyond end of memory "
568 "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
569 ramdisk_end, end_of_lowmem);
570 initrd_start = 0;
571 }
572 }
573#endif 650#endif
651 numa_kva_reserve();
574 reserve_crashkernel(); 652 reserve_crashkernel();
575} 653}
576 654
@@ -713,15 +791,19 @@ void __init setup_arch(char **cmdline_p)
713 * NOTE: at this point the bootmem allocator is fully available. 791 * NOTE: at this point the bootmem allocator is fully available.
714 */ 792 */
715 793
794#ifdef CONFIG_BLK_DEV_INITRD
795 relocate_initrd();
796#endif
797
716 paravirt_post_allocator_init(); 798 paravirt_post_allocator_init();
717 799
718 dmi_scan_machine(); 800 dmi_scan_machine();
719 801
720 io_delay_init();; 802 io_delay_init();
721 803
722#ifdef CONFIG_X86_GENERICARCH 804#ifdef CONFIG_X86_GENERICARCH
723 generic_apic_probe(); 805 generic_apic_probe();
724#endif 806#endif
725 if (efi_enabled) 807 if (efi_enabled)
726 efi_map_memmap(); 808 efi_map_memmap();
727 809
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
index 13a474d3c6e9..88a7499e8e48 100644
--- a/arch/x86/mm/discontig_32.c
+++ b/arch/x86/mm/discontig_32.c
@@ -288,8 +288,8 @@ unsigned long __init setup_memory(void)
288 288
289#ifdef CONFIG_BLK_DEV_INITRD 289#ifdef CONFIG_BLK_DEV_INITRD
290 /* Numa kva area is below the initrd */ 290 /* Numa kva area is below the initrd */
291 if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) 291 if (initrd_start)
292 kva_start_pfn = PFN_DOWN(boot_params.hdr.ramdisk_image) 292 kva_start_pfn = PFN_DOWN(initrd_start - PAGE_OFFSET)
293 - kva_pages; 293 - kva_pages;
294#endif 294#endif
295 kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1); 295 kva_start_pfn -= kva_start_pfn & (PTRS_PER_PTE-1);