diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/Kconfig | 47 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 106 |
2 files changed, 58 insertions, 95 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a1bd569f6c5a..b8676498d8df 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -1341,25 +1341,34 @@ config X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK | |||
| 1341 | Set whether the default state of memory_corruption_check is | 1341 | Set whether the default state of memory_corruption_check is |
| 1342 | on or off. | 1342 | on or off. |
| 1343 | 1343 | ||
| 1344 | config X86_RESERVE_LOW_64K | 1344 | config X86_RESERVE_LOW |
| 1345 | bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" | 1345 | int "Amount of low memory, in kilobytes, to reserve for the BIOS" |
| 1346 | default y | 1346 | default 64 |
| 1347 | ---help--- | 1347 | range 4 640 |
| 1348 | Reserve the first 64K of physical RAM on BIOSes that are known | 1348 | ---help--- |
| 1349 | to potentially corrupt that memory range. A numbers of BIOSes are | 1349 | Specify the amount of low memory to reserve for the BIOS. |
| 1350 | known to utilize this area during suspend/resume, so it must not | 1350 | |
| 1351 | be used by the kernel. | 1351 | The first page contains BIOS data structures that the kernel |
| 1352 | 1352 | must not use, so that page must always be reserved. | |
| 1353 | Set this to N if you are absolutely sure that you trust the BIOS | 1353 | |
| 1354 | to get all its memory reservations and usages right. | 1354 | By default we reserve the first 64K of physical RAM, as a |
| 1355 | 1355 | number of BIOSes are known to corrupt that memory range | |
| 1356 | If you have doubts about the BIOS (e.g. suspend/resume does not | 1356 | during events such as suspend/resume or monitor cable |
| 1357 | work or there's kernel crashes after certain hardware hotplug | 1357 | insertion, so it must not be used by the kernel. |
| 1358 | events) and it's not AMI or Phoenix, then you might want to enable | 1358 | |
| 1359 | X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical | 1359 | You can set this to 4 if you are absolutely sure that you |
| 1360 | corruption patterns. | 1360 | trust the BIOS to get all its memory reservations and usages |
| 1361 | 1361 | right. If you know your BIOS have problems beyond the | |
| 1362 | Say Y if unsure. | 1362 | default 64K area, you can set this to 640 to avoid using the |
| 1363 | entire low memory range. | ||
| 1364 | |||
| 1365 | If you have doubts about the BIOS (e.g. suspend/resume does | ||
| 1366 | not work or there's kernel crashes after certain hardware | ||
| 1367 | hotplug events) then you might want to enable | ||
| 1368 | X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check | ||
| 1369 | typical corruption patterns. | ||
| 1370 | |||
| 1371 | Leave this to the default value of 64 if you are unsure. | ||
| 1363 | 1372 | ||
| 1364 | config MATH_EMULATION | 1373 | config MATH_EMULATION |
| 1365 | bool | 1374 | bool |
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. |
