diff options
Diffstat (limited to 'arch/x86/kernel/setup_32.c')
-rw-r--r-- | arch/x86/kernel/setup_32.c | 109 |
1 files changed, 23 insertions, 86 deletions
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 5faeab69edd9..fed482c62450 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c | |||
@@ -359,56 +359,6 @@ unsigned long __init find_max_low_pfn(void) | |||
359 | return max_low_pfn; | 359 | return max_low_pfn; |
360 | } | 360 | } |
361 | 361 | ||
362 | #define BIOS_LOWMEM_KILOBYTES 0x413 | ||
363 | |||
364 | /* | ||
365 | * The BIOS places the EBDA/XBDA at the top of conventional | ||
366 | * memory, and usually decreases the reported amount of | ||
367 | * conventional memory (int 0x12) too. This also contains a | ||
368 | * workaround for Dell systems that neglect to reserve EBDA. | ||
369 | * The same workaround also avoids a problem with the AMD768MPX | ||
370 | * chipset: reserve a page before VGA to prevent PCI prefetch | ||
371 | * into it (errata #56). Usually the page is reserved anyways, | ||
372 | * unless you have no PS/2 mouse plugged in. | ||
373 | */ | ||
374 | static void __init reserve_ebda_region(void) | ||
375 | { | ||
376 | unsigned int lowmem, ebda_addr; | ||
377 | |||
378 | /* To determine the position of the EBDA and the */ | ||
379 | /* end of conventional memory, we need to look at */ | ||
380 | /* the BIOS data area. In a paravirtual environment */ | ||
381 | /* that area is absent. We'll just have to assume */ | ||
382 | /* that the paravirt case can handle memory setup */ | ||
383 | /* correctly, without our help. */ | ||
384 | if (paravirt_enabled()) | ||
385 | return; | ||
386 | |||
387 | /* end of low (conventional) memory */ | ||
388 | lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES); | ||
389 | lowmem <<= 10; | ||
390 | |||
391 | /* start of EBDA area */ | ||
392 | ebda_addr = get_bios_ebda(); | ||
393 | |||
394 | /* Fixup: bios puts an EBDA in the top 64K segment */ | ||
395 | /* of conventional memory, but does not adjust lowmem. */ | ||
396 | if ((lowmem - ebda_addr) <= 0x10000) | ||
397 | lowmem = ebda_addr; | ||
398 | |||
399 | /* Fixup: bios does not report an EBDA at all. */ | ||
400 | /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ | ||
401 | if ((ebda_addr == 0) && (lowmem >= 0x9f000)) | ||
402 | lowmem = 0x9f000; | ||
403 | |||
404 | /* Paranoia: should never happen, but... */ | ||
405 | if ((lowmem == 0) || (lowmem >= 0x100000)) | ||
406 | lowmem = 0x9f000; | ||
407 | |||
408 | /* reserve all memory between lowmem and the 1MB mark */ | ||
409 | reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT); | ||
410 | } | ||
411 | |||
412 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 362 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
413 | static void __init setup_bootmem_allocator(void); | 363 | static void __init setup_bootmem_allocator(void); |
414 | static unsigned long __init setup_memory(void) | 364 | static unsigned long __init setup_memory(void) |
@@ -522,25 +472,32 @@ static void __init reserve_initrd(void) | |||
522 | unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT; | 472 | unsigned long end_of_lowmem = max_low_pfn << PAGE_SHIFT; |
523 | unsigned long ramdisk_here; | 473 | unsigned long ramdisk_here; |
524 | 474 | ||
525 | initrd_start = 0; | ||
526 | |||
527 | if (!boot_params.hdr.type_of_loader || | 475 | if (!boot_params.hdr.type_of_loader || |
528 | !ramdisk_image || !ramdisk_size) | 476 | !ramdisk_image || !ramdisk_size) |
529 | return; /* No initrd provided by bootloader */ | 477 | return; /* No initrd provided by bootloader */ |
530 | 478 | ||
479 | initrd_start = 0; | ||
480 | |||
531 | if (ramdisk_end < ramdisk_image) { | 481 | if (ramdisk_end < ramdisk_image) { |
482 | free_bootmem(ramdisk_image, ramdisk_size); | ||
532 | printk(KERN_ERR "initrd wraps around end of memory, " | 483 | printk(KERN_ERR "initrd wraps around end of memory, " |
533 | "disabling initrd\n"); | 484 | "disabling initrd\n"); |
534 | return; | 485 | return; |
535 | } | 486 | } |
536 | if (ramdisk_size >= end_of_lowmem/2) { | 487 | if (ramdisk_size >= end_of_lowmem/2) { |
488 | free_bootmem(ramdisk_image, ramdisk_size); | ||
537 | printk(KERN_ERR "initrd too large to handle, " | 489 | printk(KERN_ERR "initrd too large to handle, " |
538 | "disabling initrd\n"); | 490 | "disabling initrd\n"); |
539 | return; | 491 | return; |
540 | } | 492 | } |
493 | |||
541 | if (ramdisk_end <= end_of_lowmem) { | 494 | if (ramdisk_end <= end_of_lowmem) { |
542 | /* All in lowmem, easy case */ | 495 | /* All in lowmem, easy case */ |
543 | reserve_bootmem(ramdisk_image, ramdisk_size, BOOTMEM_DEFAULT); | 496 | /* |
497 | * don't need to reserve again, already reserved early | ||
498 | * in i386_start_kernel, and early_res_to_bootmem | ||
499 | * convert that to reserved in bootmem | ||
500 | */ | ||
544 | initrd_start = ramdisk_image + PAGE_OFFSET; | 501 | initrd_start = ramdisk_image + PAGE_OFFSET; |
545 | initrd_end = initrd_start+ramdisk_size; | 502 | initrd_end = initrd_start+ramdisk_size; |
546 | return; | 503 | return; |
@@ -582,6 +539,8 @@ static void __init relocate_initrd(void) | |||
582 | p = (char *)__va(ramdisk_image); | 539 | p = (char *)__va(ramdisk_image); |
583 | memcpy(q, p, clen); | 540 | memcpy(q, p, clen); |
584 | q += clen; | 541 | q += clen; |
542 | /* need to free these low pages...*/ | ||
543 | free_bootmem(ramdisk_image, clen); | ||
585 | ramdisk_image += clen; | 544 | ramdisk_image += clen; |
586 | ramdisk_size -= clen; | 545 | ramdisk_size -= clen; |
587 | } | 546 | } |
@@ -600,47 +559,28 @@ static void __init relocate_initrd(void) | |||
600 | ramdisk_image += clen; | 559 | ramdisk_image += clen; |
601 | ramdisk_size -= clen; | 560 | ramdisk_size -= clen; |
602 | } | 561 | } |
562 | /* high pages is not converted by early_res_to_bootmem */ | ||
603 | } | 563 | } |
604 | 564 | ||
605 | #endif /* CONFIG_BLK_DEV_INITRD */ | 565 | #endif /* CONFIG_BLK_DEV_INITRD */ |
606 | 566 | ||
607 | void __init setup_bootmem_allocator(void) | 567 | void __init setup_bootmem_allocator(void) |
608 | { | 568 | { |
609 | unsigned long bootmap_size; | 569 | unsigned long bootmap_size, bootmap; |
610 | /* | 570 | /* |
611 | * Initialize the boot-time allocator (with low memory only): | 571 | * Initialize the boot-time allocator (with low memory only): |
612 | */ | 572 | */ |
613 | bootmap_size = init_bootmem(min_low_pfn, max_low_pfn); | 573 | bootmap_size = bootmem_bootmap_pages(max_low_pfn)<<PAGE_SHIFT; |
614 | 574 | bootmap = find_e820_area(min_low_pfn<<PAGE_SHIFT, | |
575 | max_low_pfn<<PAGE_SHIFT, bootmap_size, | ||
576 | PAGE_SIZE); | ||
577 | if (bootmap == -1L) | ||
578 | panic("Cannot find bootmem map of size %ld\n", bootmap_size); | ||
579 | bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, max_low_pfn); | ||
615 | register_bootmem_low_pages(max_low_pfn); | 580 | register_bootmem_low_pages(max_low_pfn); |
581 | early_res_to_bootmem(0, max_low_pfn<<PAGE_SHIFT); | ||
582 | reserve_bootmem(bootmap, bootmap_size, BOOTMEM_DEFAULT); | ||
616 | 583 | ||
617 | /* | ||
618 | * Reserve the bootmem bitmap itself as well. We do this in two | ||
619 | * steps (first step was init_bootmem()) because this catches | ||
620 | * the (very unlikely) case of us accidentally initializing the | ||
621 | * bootmem allocator with an invalid RAM area. | ||
622 | */ | ||
623 | reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) + | ||
624 | bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text), | ||
625 | BOOTMEM_DEFAULT); | ||
626 | |||
627 | /* | ||
628 | * reserve physical page 0 - it's a special BIOS page on many boxes, | ||
629 | * enabling clean reboots, SMP operation, laptop functions. | ||
630 | */ | ||
631 | reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT); | ||
632 | |||
633 | /* reserve EBDA region */ | ||
634 | reserve_ebda_region(); | ||
635 | |||
636 | #ifdef CONFIG_SMP | ||
637 | /* | ||
638 | * But first pinch a few for the stack/trampoline stuff | ||
639 | * FIXME: Don't need the extra page at 4K, but need to fix | ||
640 | * trampoline before removing it. (see the GDT stuff) | ||
641 | */ | ||
642 | reserve_bootmem(PAGE_SIZE, PAGE_SIZE, BOOTMEM_DEFAULT); | ||
643 | #endif | ||
644 | #ifdef CONFIG_ACPI_SLEEP | 584 | #ifdef CONFIG_ACPI_SLEEP |
645 | /* | 585 | /* |
646 | * Reserve low memory region for sleep support. | 586 | * Reserve low memory region for sleep support. |
@@ -803,9 +743,6 @@ void __init setup_arch(char **cmdline_p) | |||
803 | * not to exceed the 8Mb limit. | 743 | * not to exceed the 8Mb limit. |
804 | */ | 744 | */ |
805 | 745 | ||
806 | #ifdef CONFIG_SMP | ||
807 | smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ | ||
808 | #endif | ||
809 | paging_init(); | 746 | paging_init(); |
810 | 747 | ||
811 | /* | 748 | /* |