aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
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 /arch/x86
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>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/Kconfig26
-rw-r--r--arch/x86/kernel/setup.c80
2 files changed, 83 insertions, 23 deletions
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/*