aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/setup.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2008-09-07 04:51:32 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-07 11:39:59 -0400
commit5394f80f92642c61fc2a95385be85f2fdcfb5adb (patch)
tree313dd51430cf7ff7f7161019bb3d3bf89320357c /arch/x86/kernel/setup.c
parent7686ad5606f08d9dfb33a2087a36c8366366015b (diff)
x86: check for and defend against BIOS memory corruption
Some BIOSes have been observed to corrupt memory in the low 64k. This change: - Reserves all memory which does not have to be in that area, to prevent it from being used as general memory by the kernel. Things like the SMP trampoline are still in the memory, however. - Clears the reserved memory so we can observe changes to it. - Adds a function check_for_bios_corruption() which checks and reports on memory becoming unexpectedly non-zero. Currently it's called in the x86 fault handler, and the powermanagement debug output. Signed-off-by: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r--arch/x86/kernel/setup.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 362d4e7f2d3..ee89ebc5aab 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -579,6 +579,89 @@ static struct x86_quirks default_x86_quirks __initdata;
579struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; 579struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
580 580
581/* 581/*
582 * Some BIOSes seem to corrupt the low 64k of memory during events
583 * like suspend/resume and unplugging an HDMI cable. Reserve all
584 * remaining free memory in that area and fill it with a distinct
585 * pattern.
586 */
587#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
588#define MAX_SCAN_AREAS 8
589static struct e820entry scan_areas[MAX_SCAN_AREAS];
590static int num_scan_areas;
591
592static void __init setup_bios_corruption_check(void)
593{
594 u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */
595
596 while(addr < 0x10000 && num_scan_areas < MAX_SCAN_AREAS) {
597 u64 size;
598 addr = find_e820_area_size(addr, &size, PAGE_SIZE);
599
600 if (addr == 0)
601 break;
602
603 if ((addr + size) > 0x10000)
604 size = 0x10000 - addr;
605
606 if (size == 0)
607 break;
608
609 e820_update_range(addr, size, E820_RAM, E820_RESERVED);
610 scan_areas[num_scan_areas].addr = addr;
611 scan_areas[num_scan_areas].size = size;
612 num_scan_areas++;
613
614 /* Assume we've already mapped this early memory */
615 memset(__va(addr), 0, size);
616
617 addr += size;
618 }
619
620 printk(KERN_INFO "scanning %d areas for BIOS corruption\n",
621 num_scan_areas);
622 update_e820();
623}
624
625static int __read_mostly bios_corruption_check = 1;
626
627void check_for_bios_corruption(void)
628{
629 int i;
630 int corruption = 0;
631
632 if (!bios_corruption_check)
633 return;
634
635 for(i = 0; i < num_scan_areas; i++) {
636 unsigned long *addr = __va(scan_areas[i].addr);
637 unsigned long size = scan_areas[i].size;
638
639 for(; size; addr++, size -= sizeof(unsigned long)) {
640 if (!*addr)
641 continue;
642 printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n",
643 addr, __pa(addr), *addr);
644 corruption = 1;
645 *addr = 0;
646 }
647 }
648
649 if (corruption)
650 dump_stack();
651}
652
653static int set_bios_corruption_check(char *arg)
654{
655 char *end;
656
657 bios_corruption_check = simple_strtol(arg, &end, 10);
658
659 return (*end == 0) ? 0 : -EINVAL;
660}
661early_param("bios_corruption_check", set_bios_corruption_check);
662#endif
663
664/*
582 * Determine if we were loaded by an EFI loader. If so, then we have also been 665 * Determine if we were loaded by an EFI loader. If so, then we have also been
583 * passed the efi memmap, systab, etc., so we should use these data structures 666 * passed the efi memmap, systab, etc., so we should use these data structures
584 * for initialization. Note, the efi init code path is determined by the 667 * for initialization. Note, the efi init code path is determined by the
@@ -750,6 +833,10 @@ void __init setup_arch(char **cmdline_p)
750 high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1; 833 high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
751#endif 834#endif
752 835
836#ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
837 setup_bios_corruption_check();
838#endif
839
753 /* max_pfn_mapped is updated here */ 840 /* max_pfn_mapped is updated here */
754 max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); 841 max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
755 max_pfn_mapped = max_low_pfn_mapped; 842 max_pfn_mapped = max_low_pfn_mapped;