diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 16:06:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-21 16:06:49 -0400 |
commit | 781c5a67f152c17c3e4a9ed9647f8c0be6ea5ae9 (patch) | |
tree | 5cba2f98482e4612e4daf8e57e4e50a24a273fe9 /arch/x86/kernel/setup.c | |
parent | e990c77d06dbacc8e5c5edd2c4a1005d318a4fa6 (diff) | |
parent | 9ea77bdb39b62c9bf9fd3cdd1c25a9420bccd380 (diff) |
Merge branch 'x86-bios-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-bios-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, bios: Make the x86 early memory reservation a kernel option
x86, bios: By default, reserve the low 64K for all BIOSes
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 106 |
1 files changed, 30 insertions, 76 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index df770ad99b3e..6154701a5fd3 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -619,79 +619,7 @@ static __init void reserve_ibft_region(void) | |||
619 | reserve_early_overlap_ok(addr, addr + size, "ibft"); | 619 | reserve_early_overlap_ok(addr, addr + size, "ibft"); |
620 | } | 620 | } |
621 | 621 | ||
622 | #ifdef CONFIG_X86_RESERVE_LOW_64K | 622 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; |
623 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) | ||
624 | { | ||
625 | printk(KERN_NOTICE | ||
626 | "%s detected: BIOS may corrupt low RAM, working around it.\n", | ||
627 | d->ident); | ||
628 | |||
629 | e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED); | ||
630 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
631 | |||
632 | return 0; | ||
633 | } | ||
634 | #endif | ||
635 | |||
636 | /* List of systems that have known low memory corruption BIOS problems */ | ||
637 | static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | ||
638 | #ifdef CONFIG_X86_RESERVE_LOW_64K | ||
639 | { | ||
640 | .callback = dmi_low_memory_corruption, | ||
641 | .ident = "AMI BIOS", | ||
642 | .matches = { | ||
643 | DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), | ||
644 | }, | ||
645 | }, | ||
646 | { | ||
647 | .callback = dmi_low_memory_corruption, | ||
648 | .ident = "Phoenix BIOS", | ||
649 | .matches = { | ||
650 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"), | ||
651 | }, | ||
652 | }, | ||
653 | { | ||
654 | .callback = dmi_low_memory_corruption, | ||
655 | .ident = "Phoenix/MSC BIOS", | ||
656 | .matches = { | ||
657 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix/MSC"), | ||
658 | }, | ||
659 | }, | ||
660 | /* | ||
661 | * AMI BIOS with low memory corruption was found on Intel DG45ID and | ||
662 | * DG45FC boards. | ||
663 | * It has a different DMI_BIOS_VENDOR = "Intel Corp.", for now we will | ||
664 | * match only DMI_BOARD_NAME and see if there is more bad products | ||
665 | * with this vendor. | ||
666 | */ | ||
667 | { | ||
668 | .callback = dmi_low_memory_corruption, | ||
669 | .ident = "AMI BIOS", | ||
670 | .matches = { | ||
671 | DMI_MATCH(DMI_BOARD_NAME, "DG45ID"), | ||
672 | }, | ||
673 | }, | ||
674 | { | ||
675 | .callback = dmi_low_memory_corruption, | ||
676 | .ident = "AMI BIOS", | ||
677 | .matches = { | ||
678 | DMI_MATCH(DMI_BOARD_NAME, "DG45FC"), | ||
679 | }, | ||
680 | }, | ||
681 | /* | ||
682 | * The Dell Inspiron Mini 1012 has DMI_BIOS_VENDOR = "Dell Inc.", so | ||
683 | * match on the product name. | ||
684 | */ | ||
685 | { | ||
686 | .callback = dmi_low_memory_corruption, | ||
687 | .ident = "Phoenix BIOS", | ||
688 | .matches = { | ||
689 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"), | ||
690 | }, | ||
691 | }, | ||
692 | #endif | ||
693 | {} | ||
694 | }; | ||
695 | 623 | ||
696 | static void __init trim_bios_range(void) | 624 | static void __init trim_bios_range(void) |
697 | { | 625 | { |
@@ -699,8 +627,14 @@ static void __init trim_bios_range(void) | |||
699 | * A special case is the first 4Kb of memory; | 627 | * A special case is the first 4Kb of memory; |
700 | * This is a BIOS owned area, not kernel ram, but generally | 628 | * This is a BIOS owned area, not kernel ram, but generally |
701 | * not listed as such in the E820 table. | 629 | * not listed as such in the E820 table. |
630 | * | ||
631 | * This typically reserves additional memory (64KiB by default) | ||
632 | * since some BIOSes are known to corrupt low memory. See the | ||
633 | * Kconfig help text for X86_RESERVE_LOW. | ||
702 | */ | 634 | */ |
703 | e820_update_range(0, PAGE_SIZE, E820_RAM, E820_RESERVED); | 635 | e820_update_range(0, ALIGN(reserve_low, PAGE_SIZE), |
636 | E820_RAM, E820_RESERVED); | ||
637 | |||
704 | /* | 638 | /* |
705 | * special case: Some BIOSen report the PC BIOS | 639 | * special case: Some BIOSen report the PC BIOS |
706 | * area (640->1Mb) as ram even though it is not. | 640 | * area (640->1Mb) as ram even though it is not. |
@@ -710,6 +644,28 @@ static void __init trim_bios_range(void) | |||
710 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 644 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
711 | } | 645 | } |
712 | 646 | ||
647 | static int __init parse_reservelow(char *p) | ||
648 | { | ||
649 | unsigned long long size; | ||
650 | |||
651 | if (!p) | ||
652 | return -EINVAL; | ||
653 | |||
654 | size = memparse(p, &p); | ||
655 | |||
656 | if (size < 4096) | ||
657 | size = 4096; | ||
658 | |||
659 | if (size > 640*1024) | ||
660 | size = 640*1024; | ||
661 | |||
662 | reserve_low = size; | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | early_param("reservelow", parse_reservelow); | ||
668 | |||
713 | /* | 669 | /* |
714 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 670 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
715 | * passed the efi memmap, systab, etc., so we should use these data structures | 671 | * passed the efi memmap, systab, etc., so we should use these data structures |
@@ -865,8 +821,6 @@ void __init setup_arch(char **cmdline_p) | |||
865 | 821 | ||
866 | dmi_scan_machine(); | 822 | dmi_scan_machine(); |
867 | 823 | ||
868 | dmi_check_system(bad_bios_dmi_table); | ||
869 | |||
870 | /* | 824 | /* |
871 | * VMware detection requires dmi to be available, so this | 825 | * VMware detection requires dmi to be available, so this |
872 | * needs to be done after dmi_scan_machine, for the BP. | 826 | * needs to be done after dmi_scan_machine, for the BP. |