aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/setup.c
diff options
context:
space:
mode:
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 362d4e7f2d38..ee89ebc5aabc 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;