diff options
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 168 |
1 files changed, 20 insertions, 148 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index bdec76e55594..a31223828597 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -98,6 +98,7 @@ | |||
98 | 98 | ||
99 | #include <mach_apic.h> | 99 | #include <mach_apic.h> |
100 | #include <asm/paravirt.h> | 100 | #include <asm/paravirt.h> |
101 | #include <asm/hypervisor.h> | ||
101 | 102 | ||
102 | #include <asm/percpu.h> | 103 | #include <asm/percpu.h> |
103 | #include <asm/topology.h> | 104 | #include <asm/topology.h> |
@@ -448,6 +449,7 @@ static void __init reserve_early_setup_data(void) | |||
448 | * @size: Size of the crashkernel memory to reserve. | 449 | * @size: Size of the crashkernel memory to reserve. |
449 | * Returns the base address on success, and -1ULL on failure. | 450 | * Returns the base address on success, and -1ULL on failure. |
450 | */ | 451 | */ |
452 | static | ||
451 | unsigned long long __init find_and_reserve_crashkernel(unsigned long long size) | 453 | unsigned long long __init find_and_reserve_crashkernel(unsigned long long size) |
452 | { | 454 | { |
453 | const unsigned long long alignment = 16<<20; /* 16M */ | 455 | const unsigned long long alignment = 16<<20; /* 16M */ |
@@ -583,161 +585,24 @@ static int __init setup_elfcorehdr(char *arg) | |||
583 | early_param("elfcorehdr", setup_elfcorehdr); | 585 | early_param("elfcorehdr", setup_elfcorehdr); |
584 | #endif | 586 | #endif |
585 | 587 | ||
586 | static struct x86_quirks default_x86_quirks __initdata; | 588 | static int __init default_update_genapic(void) |
587 | |||
588 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; | ||
589 | |||
590 | /* | ||
591 | * Some BIOSes seem to corrupt the low 64k of memory during events | ||
592 | * like suspend/resume and unplugging an HDMI cable. Reserve all | ||
593 | * remaining free memory in that area and fill it with a distinct | ||
594 | * pattern. | ||
595 | */ | ||
596 | #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION | ||
597 | #define MAX_SCAN_AREAS 8 | ||
598 | |||
599 | static int __read_mostly memory_corruption_check = -1; | ||
600 | |||
601 | static unsigned __read_mostly corruption_check_size = 64*1024; | ||
602 | static unsigned __read_mostly corruption_check_period = 60; /* seconds */ | ||
603 | |||
604 | static struct e820entry scan_areas[MAX_SCAN_AREAS]; | ||
605 | static int num_scan_areas; | ||
606 | |||
607 | |||
608 | static int set_corruption_check(char *arg) | ||
609 | { | ||
610 | char *end; | ||
611 | |||
612 | memory_corruption_check = simple_strtol(arg, &end, 10); | ||
613 | |||
614 | return (*end == 0) ? 0 : -EINVAL; | ||
615 | } | ||
616 | early_param("memory_corruption_check", set_corruption_check); | ||
617 | |||
618 | static int set_corruption_check_period(char *arg) | ||
619 | { | ||
620 | char *end; | ||
621 | |||
622 | corruption_check_period = simple_strtoul(arg, &end, 10); | ||
623 | |||
624 | return (*end == 0) ? 0 : -EINVAL; | ||
625 | } | ||
626 | early_param("memory_corruption_check_period", set_corruption_check_period); | ||
627 | |||
628 | static int set_corruption_check_size(char *arg) | ||
629 | { | 589 | { |
630 | char *end; | 590 | #ifdef CONFIG_X86_SMP |
631 | unsigned size; | 591 | # if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64) |
632 | 592 | genapic->wakeup_cpu = wakeup_secondary_cpu_via_init; | |
633 | size = memparse(arg, &end); | 593 | # endif |
634 | |||
635 | if (*end == '\0') | ||
636 | corruption_check_size = size; | ||
637 | |||
638 | return (size == corruption_check_size) ? 0 : -EINVAL; | ||
639 | } | ||
640 | early_param("memory_corruption_check_size", set_corruption_check_size); | ||
641 | |||
642 | |||
643 | static void __init setup_bios_corruption_check(void) | ||
644 | { | ||
645 | u64 addr = PAGE_SIZE; /* assume first page is reserved anyway */ | ||
646 | |||
647 | if (memory_corruption_check == -1) { | ||
648 | memory_corruption_check = | ||
649 | #ifdef CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK | ||
650 | 1 | ||
651 | #else | ||
652 | 0 | ||
653 | #endif | 594 | #endif |
654 | ; | ||
655 | } | ||
656 | |||
657 | if (corruption_check_size == 0) | ||
658 | memory_corruption_check = 0; | ||
659 | |||
660 | if (!memory_corruption_check) | ||
661 | return; | ||
662 | |||
663 | corruption_check_size = round_up(corruption_check_size, PAGE_SIZE); | ||
664 | 595 | ||
665 | while(addr < corruption_check_size && num_scan_areas < MAX_SCAN_AREAS) { | 596 | return 0; |
666 | u64 size; | ||
667 | addr = find_e820_area_size(addr, &size, PAGE_SIZE); | ||
668 | |||
669 | if (addr == 0) | ||
670 | break; | ||
671 | |||
672 | if ((addr + size) > corruption_check_size) | ||
673 | size = corruption_check_size - addr; | ||
674 | |||
675 | if (size == 0) | ||
676 | break; | ||
677 | |||
678 | e820_update_range(addr, size, E820_RAM, E820_RESERVED); | ||
679 | scan_areas[num_scan_areas].addr = addr; | ||
680 | scan_areas[num_scan_areas].size = size; | ||
681 | num_scan_areas++; | ||
682 | |||
683 | /* Assume we've already mapped this early memory */ | ||
684 | memset(__va(addr), 0, size); | ||
685 | |||
686 | addr += size; | ||
687 | } | ||
688 | |||
689 | printk(KERN_INFO "Scanning %d areas for low memory corruption\n", | ||
690 | num_scan_areas); | ||
691 | update_e820(); | ||
692 | } | ||
693 | |||
694 | static struct timer_list periodic_check_timer; | ||
695 | |||
696 | void check_for_bios_corruption(void) | ||
697 | { | ||
698 | int i; | ||
699 | int corruption = 0; | ||
700 | |||
701 | if (!memory_corruption_check) | ||
702 | return; | ||
703 | |||
704 | for(i = 0; i < num_scan_areas; i++) { | ||
705 | unsigned long *addr = __va(scan_areas[i].addr); | ||
706 | unsigned long size = scan_areas[i].size; | ||
707 | |||
708 | for(; size; addr++, size -= sizeof(unsigned long)) { | ||
709 | if (!*addr) | ||
710 | continue; | ||
711 | printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n", | ||
712 | addr, __pa(addr), *addr); | ||
713 | corruption = 1; | ||
714 | *addr = 0; | ||
715 | } | ||
716 | } | ||
717 | |||
718 | WARN(corruption, KERN_ERR "Memory corruption detected in low memory\n"); | ||
719 | } | ||
720 | |||
721 | static void periodic_check_for_corruption(unsigned long data) | ||
722 | { | ||
723 | check_for_bios_corruption(); | ||
724 | mod_timer(&periodic_check_timer, round_jiffies(jiffies + corruption_check_period*HZ)); | ||
725 | } | 597 | } |
726 | 598 | ||
727 | void start_periodic_check_for_corruption(void) | 599 | static struct x86_quirks default_x86_quirks __initdata = { |
728 | { | 600 | .update_genapic = default_update_genapic, |
729 | if (!memory_corruption_check || corruption_check_period == 0) | 601 | }; |
730 | return; | ||
731 | |||
732 | printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n", | ||
733 | corruption_check_period); | ||
734 | 602 | ||
735 | init_timer(&periodic_check_timer); | 603 | struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; |
736 | periodic_check_timer.function = &periodic_check_for_corruption; | ||
737 | periodic_check_for_corruption(0); | ||
738 | } | ||
739 | #endif | ||
740 | 604 | ||
605 | #ifdef CONFIG_X86_RESERVE_LOW_64K | ||
741 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) | 606 | static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) |
742 | { | 607 | { |
743 | printk(KERN_NOTICE | 608 | printk(KERN_NOTICE |
@@ -749,6 +614,7 @@ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) | |||
749 | 614 | ||
750 | return 0; | 615 | return 0; |
751 | } | 616 | } |
617 | #endif | ||
752 | 618 | ||
753 | /* List of systems that have known low memory corruption BIOS problems */ | 619 | /* List of systems that have known low memory corruption BIOS problems */ |
754 | static struct dmi_system_id __initdata bad_bios_dmi_table[] = { | 620 | static struct dmi_system_id __initdata bad_bios_dmi_table[] = { |
@@ -907,6 +773,12 @@ void __init setup_arch(char **cmdline_p) | |||
907 | 773 | ||
908 | dmi_check_system(bad_bios_dmi_table); | 774 | dmi_check_system(bad_bios_dmi_table); |
909 | 775 | ||
776 | /* | ||
777 | * VMware detection requires dmi to be available, so this | ||
778 | * needs to be done after dmi_scan_machine, for the BP. | ||
779 | */ | ||
780 | init_hypervisor(&boot_cpu_data); | ||
781 | |||
910 | #ifdef CONFIG_X86_32 | 782 | #ifdef CONFIG_X86_32 |
911 | probe_roms(); | 783 | probe_roms(); |
912 | #endif | 784 | #endif |