diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2008-09-07 04:51:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-07 11:40:01 -0400 |
commit | 9f077871ce7237e2387fc76542b3b4033cb05e49 (patch) | |
tree | e9a32b88c71a86b478b61fe50d0cb66b10bad10c /arch/x86/kernel/setup.c | |
parent | bb577f980ef35e2b0d00aeed566724e5032aa5eb (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/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 80 |
1 files changed, 60 insertions, 20 deletions
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 | |||
590 | static int __read_mostly memory_corruption_check = 0; | ||
591 | static unsigned __read_mostly corruption_check_size = 64*1024; | ||
592 | static unsigned __read_mostly corruption_check_period = 60; /* seconds */ | ||
593 | |||
589 | static struct e820entry scan_areas[MAX_SCAN_AREAS]; | 594 | static struct e820entry scan_areas[MAX_SCAN_AREAS]; |
590 | static int num_scan_areas; | 595 | static int num_scan_areas; |
591 | 596 | ||
597 | |||
598 | static 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 | } | ||
606 | early_param("memory_corruption_check", set_corruption_check); | ||
607 | |||
608 | static 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 | } | ||
616 | early_param("memory_corruption_check_period", set_corruption_check_period); | ||
617 | |||
618 | static 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 | } | ||
630 | early_param("memory_corruption_check_size", set_corruption_check_size); | ||
631 | |||
632 | |||
592 | static void __init setup_bios_corruption_check(void) | 633 | static 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 | ||
625 | static int __read_mostly bios_corruption_check = 1; | ||
626 | static struct timer_list periodic_check_timer; | 674 | static struct timer_list periodic_check_timer; |
627 | 675 | ||
628 | void check_for_bios_corruption(void) | 676 | void 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 | ||
654 | static void periodic_check_for_corruption(unsigned long data) | 701 | static 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 | ||
660 | void start_periodic_check_for_corruption(void) | 707 | void 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 | |||
670 | static 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 | } | ||
678 | early_param("bios_corruption_check", set_bios_corruption_check); | ||
679 | #endif | 719 | #endif |
680 | 720 | ||
681 | /* | 721 | /* |