aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-09-07 04:51:34 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-07 11:40:01 -0400
commit9f077871ce7237e2387fc76542b3b4033cb05e49 (patch)
treee9a32b88c71a86b478b61fe50d0cb66b10bad10c
parentbb577f980ef35e2b0d00aeed566724e5032aa5eb (diff)
x86: clean up memory corruption check and add more kernel parameters
The corruption check is enabled in Kconfig by default, but disabled at runtime. This patch adds several kernel parameters to control the corruption check's behaviour; these are documented in kernel-parameters.txt. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--Documentation/kernel-parameters.txt28
-rw-r--r--arch/x86/Kconfig26
-rw-r--r--arch/x86/kernel/setup.c80
3 files changed, 106 insertions, 28 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index df48af505d15..6a2629d00598 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -360,11 +360,6 @@ and is between 256 and 4096 characters. It is defined in the file
360 Format: <io>,<irq>,<mode> 360 Format: <io>,<irq>,<mode>
361 See header of drivers/net/hamradio/baycom_ser_hdx.c. 361 See header of drivers/net/hamradio/baycom_ser_hdx.c.
362 362
363 bios_corruption_check=0/1 [X86]
364 Some BIOSes seem to corrupt the first 64k of memory
365 when doing things like suspend/resume. Setting this
366 option will scan the memory looking for corruption.
367
368 boot_delay= Milliseconds to delay each printk during boot. 363 boot_delay= Milliseconds to delay each printk during boot.
369 Values larger than 10 seconds (10000) are changed to 364 Values larger than 10 seconds (10000) are changed to
370 no delay (0). 365 no delay (0).
@@ -1233,6 +1228,29 @@ and is between 256 and 4096 characters. It is defined in the file
1233 or 1228 or
1234 memmap=0x10000$0x18690000 1229 memmap=0x10000$0x18690000
1235 1230
1231 memory_corruption_check=0/1 [X86]
1232 Some BIOSes seem to corrupt the first 64k of
1233 memory when doing things like suspend/resume.
1234 Setting this option will scan the memory
1235 looking for corruption. Enabling this will
1236 both detect corruption and prevent the kernel
1237 from using the memory being corrupted.
1238 However, its intended as a diagnostic tool; if
1239 repeatable BIOS-originated corruption always
1240 affects the same memory, you can use memmap=
1241 to prevent the kernel from using that memory.
1242
1243 memory_corruption_check_size=size [X86]
1244 By default it checks for corruption in the low
1245 64k, making this memory unavailable for normal
1246 use. Use this parameter to scan for
1247 corruption in more or less memory.
1248
1249 memory_corruption_check_period=seconds [X86]
1250 By default it checks for corruption every 60
1251 seconds. Use this parameter to check at some
1252 other rate. 0 disables periodic checking.
1253
1236 memtest= [KNL,X86] Enable memtest 1254 memtest= [KNL,X86] Enable memtest
1237 Format: <integer> 1255 Format: <integer>
1238 range: 0,4 : pattern number 1256 range: 0,4 : pattern number
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1bb52e2ca02e..cbee4199689c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -201,9 +201,6 @@ config X86_TRAMPOLINE
201 depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP) 201 depends on X86_SMP || (X86_VOYAGER && SMP) || (64BIT && ACPI_SLEEP)
202 default y 202 default y
203 203
204config X86_CHECK_BIOS_CORRUPTION
205 def_bool y
206
207config KTIME_SCALAR 204config KTIME_SCALAR
208 def_bool X86_32 205 def_bool X86_32
209source "init/Kconfig" 206source "init/Kconfig"
@@ -1062,6 +1059,29 @@ config HIGHPTE
1062 low memory. Setting this option will put user-space page table 1059 low memory. Setting this option will put user-space page table
1063 entries in high memory. 1060 entries in high memory.
1064 1061
1062config X86_CHECK_BIOS_CORRUPTION
1063 bool "Check for low memory corruption"
1064 default y
1065 help
1066 Periodically check for memory corruption in low memory, which
1067 is suspected to be caused by BIOS. Even when enabled in the
1068 configuration, it is disabled at runtime. Enable it by
1069 setting "memory_corruption_check=1" on the kernel command
1070 line. By default it scans the low 64k of memory every 60
1071 seconds; see the memory_corruption_check_size and
1072 memory_corruption_check_period parameters in
1073 Documentation/kernel-parameters.txt to adjust this.
1074
1075 When enabled with the default parameters, this option has
1076 almost no overhead, as it reserves a relatively small amount
1077 of memory and scans it infrequently. It both detects corruption
1078 and prevents it from affecting the running system.
1079
1080 It is, however, intended as a diagnostic tool; if repeatable
1081 BIOS-originated corruption always affects the same memory,
1082 you can use memmap= to prevent the kernel from using that
1083 memory.
1084
1065config MATH_EMULATION 1085config MATH_EMULATION
1066 bool 1086 bool
1067 prompt "Math emulation" if X86_32 1087 prompt "Math emulation" if X86_32
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index c239b3780973..27ae91288855 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -586,22 +586,71 @@ struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
586 */ 586 */
587#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION 587#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
588#define MAX_SCAN_AREAS 8 588#define MAX_SCAN_AREAS 8
589
590static int __read_mostly memory_corruption_check = 0;
591static unsigned __read_mostly corruption_check_size = 64*1024;
592static unsigned __read_mostly corruption_check_period = 60; /* seconds */
593
589static struct e820entry scan_areas[MAX_SCAN_AREAS]; 594static struct e820entry scan_areas[MAX_SCAN_AREAS];
590static int num_scan_areas; 595static int num_scan_areas;
591 596
597
598static int set_corruption_check(char *arg)
599{
600 char *end;
601
602 memory_corruption_check = simple_strtol(arg, &end, 10);
603
604 return (*end == 0) ? 0 : -EINVAL;
605}
606early_param("memory_corruption_check", set_corruption_check);
607
608static int set_corruption_check_period(char *arg)
609{
610 char *end;
611
612 corruption_check_period = simple_strtoul(arg, &end, 10);
613
614 return (*end == 0) ? 0 : -EINVAL;
615}
616early_param("memory_corruption_check_period", set_corruption_check_period);
617
618static int set_corruption_check_size(char *arg)
619{
620 char *end;
621 unsigned size;
622
623 size = memparse(arg, &end);
624
625 if (*end == '\0')
626 corruption_check_size = size;
627
628 return (size == corruption_check_size) ? 0 : -EINVAL;
629}
630early_param("memory_corruption_check_size", set_corruption_check_size);
631
632
592static void __init setup_bios_corruption_check(void) 633static void __init setup_bios_corruption_check(void)
593{ 634{
594 u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ 635 u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */
595 636
596 while(addr < 0x10000 && num_scan_areas < MAX_SCAN_AREAS) { 637 if (corruption_check_size == 0)
638 memory_corruption_check = 0;
639
640 if (!memory_corruption_check)
641 return;
642
643 corruption_check_size = round_up(corruption_check_size, PAGE_SIZE);
644
645 while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) {
597 u64 size; 646 u64 size;
598 addr = find_e820_area_size(addr, &size, PAGE_SIZE); 647 addr = find_e820_area_size(addr, &size, PAGE_SIZE);
599 648
600 if (addr == 0) 649 if (addr == 0)
601 break; 650 break;
602 651
603 if ((addr + size) > 0x10000) 652 if ((addr + size) > corruption_check_size)
604 size = 0x10000 - addr; 653 size = corruption_check_size - addr;
605 654
606 if (size == 0) 655 if (size == 0)
607 break; 656 break;
@@ -617,12 +666,11 @@ static void __init setup_bios_corruption_check(void)
617 addr += size; 666 addr += size;
618 } 667 }
619 668
620 printk(KERN_INFO "scanning %d areas for BIOS corruption\n", 669 printk(KERN_INFO "Scanning %d areas for low memory corruption\n",
621 num_scan_areas); 670 num_scan_areas);
622 update_e820(); 671 update_e820();
623} 672}
624 673
625static int __read_mostly bios_corruption_check = 1;
626static struct timer_list periodic_check_timer; 674static struct timer_list periodic_check_timer;
627 675
628void check_for_bios_corruption(void) 676void check_for_bios_corruption(void)
@@ -630,7 +678,7 @@ void check_for_bios_corruption(void)
630 int i; 678 int i;
631 int corruption = 0; 679 int corruption = 0;
632 680
633 if (!bios_corruption_check) 681 if (!memory_corruption_check)
634 return; 682 return;
635 683
636 for(i = 0; i < num_scan_areas; i++) { 684 for(i = 0; i < num_scan_areas; i++) {
@@ -647,35 +695,27 @@ void check_for_bios_corruption(void)
647 } 695 }
648 } 696 }
649 697
650 if (corruption) 698 WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n");
651 dump_stack();
652} 699}
653 700
654static void periodic_check_for_corruption(unsigned long data) 701static void periodic_check_for_corruption(unsigned long data)
655{ 702{
656 check_for_bios_corruption(); 703 check_for_bios_corruption();
657 mod_timer(&periodic_check_timer, jiffies + 60*HZ); 704 mod_timer(&periodic_check_timer, jiffies + corruption_check_period*HZ);
658} 705}
659 706
660void start_periodic_check_for_corruption(void) 707void start_periodic_check_for_corruption(void)
661{ 708{
662 if (!bios_corruption_check) 709 if (!memory_corruption_check || corruption_check_period == 0)
663 return; 710 return;
664 711
712 printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
713 corruption_check_period);
714
665 init_timer(&periodic_check_timer); 715 init_timer(&periodic_check_timer);
666 periodic_check_timer.function = &periodic_check_for_corruption; 716 periodic_check_timer.function = &periodic_check_for_corruption;
667 periodic_check_for_corruption(0); 717 periodic_check_for_corruption(0);
668} 718}
669
670static int set_bios_corruption_check(char *arg)
671{
672 char *end;
673
674 bios_corruption_check = simple_strtol(arg, &end, 10);
675
676 return (*end == 0) ? 0 : -EINVAL;
677}
678early_param("bios_corruption_check", set_bios_corruption_check);
679#endif 719#endif
680 720
681/* 721/*