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