diff options
| author | Zachary Amsden <zach@vmware.com> | 2008-12-13 15:36:58 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-14 19:24:38 -0500 |
| commit | ae8d04e2ecbb233926860e9ce145eac19c7835dc (patch) | |
| tree | c6553749f2428e6b828af9b5a165c0ce31cb71f6 | |
| parent | ca7e716c7833aeaeb8fedd6d004c5f5d5e14d325 (diff) | |
x86 Fix VMI crash on boot in 2.6.28-rc8
VMI initialiation can relocate the fixmap, causing early_ioremap to
malfunction if it is initialized before the relocation. To fix this,
VMI activation is split into two phases; the detection, which must
happen before setting up ioremap, and the activation, which must happen
after parsing early boot parameters.
This fixes a crash on boot when VMI is enabled under VMware.
Signed-off-by: Zachary Amsden <zach@vmware.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | arch/x86/include/asm/vmi.h | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/vmi_32.c | 16 |
4 files changed, 23 insertions, 15 deletions
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h index b7c0dea119fe..61e08c0a2907 100644 --- a/arch/x86/include/asm/vmi.h +++ b/arch/x86/include/asm/vmi.h | |||
| @@ -223,9 +223,15 @@ struct pci_header { | |||
| 223 | } __attribute__((packed)); | 223 | } __attribute__((packed)); |
| 224 | 224 | ||
| 225 | /* Function prototypes for bootstrapping */ | 225 | /* Function prototypes for bootstrapping */ |
| 226 | #ifdef CONFIG_VMI | ||
| 226 | extern void vmi_init(void); | 227 | extern void vmi_init(void); |
| 228 | extern void vmi_activate(void); | ||
| 227 | extern void vmi_bringup(void); | 229 | extern void vmi_bringup(void); |
| 228 | extern void vmi_apply_boot_page_allocations(void); | 230 | #else |
| 231 | static inline void vmi_init(void) {} | ||
| 232 | static inline void vmi_activate(void) {} | ||
| 233 | static inline void vmi_bringup(void) {} | ||
| 234 | #endif | ||
| 229 | 235 | ||
| 230 | /* State needed to start an application processor in an SMP system. */ | 236 | /* State needed to start an application processor in an SMP system. */ |
| 231 | struct vmi_ap_state { | 237 | struct vmi_ap_state { |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9d5674f7b6cc..bdec76e55594 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -794,6 +794,9 @@ void __init setup_arch(char **cmdline_p) | |||
| 794 | printk(KERN_INFO "Command line: %s\n", boot_command_line); | 794 | printk(KERN_INFO "Command line: %s\n", boot_command_line); |
| 795 | #endif | 795 | #endif |
| 796 | 796 | ||
| 797 | /* VMI may relocate the fixmap; do this before touching ioremap area */ | ||
| 798 | vmi_init(); | ||
| 799 | |||
| 797 | early_cpu_init(); | 800 | early_cpu_init(); |
| 798 | early_ioremap_init(); | 801 | early_ioremap_init(); |
| 799 | 802 | ||
| @@ -880,13 +883,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 880 | check_efer(); | 883 | check_efer(); |
| 881 | #endif | 884 | #endif |
| 882 | 885 | ||
| 883 | #if defined(CONFIG_VMI) && defined(CONFIG_X86_32) | 886 | /* Must be before kernel pagetables are setup */ |
| 884 | /* | 887 | vmi_activate(); |
| 885 | * Must be before kernel pagetables are setup | ||
| 886 | * or fixmap area is touched. | ||
| 887 | */ | ||
| 888 | vmi_init(); | ||
| 889 | #endif | ||
| 890 | 888 | ||
| 891 | /* after early param, so could get panic from serial */ | 889 | /* after early param, so could get panic from serial */ |
| 892 | reserve_early_setup_data(); | 890 | reserve_early_setup_data(); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7b1093397319..f71f96fc9e62 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -294,9 +294,7 @@ static void __cpuinit start_secondary(void *unused) | |||
| 294 | * fragile that we want to limit the things done here to the | 294 | * fragile that we want to limit the things done here to the |
| 295 | * most necessary things. | 295 | * most necessary things. |
| 296 | */ | 296 | */ |
| 297 | #ifdef CONFIG_VMI | ||
| 298 | vmi_bringup(); | 297 | vmi_bringup(); |
| 299 | #endif | ||
| 300 | cpu_init(); | 298 | cpu_init(); |
| 301 | preempt_disable(); | 299 | preempt_disable(); |
| 302 | smp_callin(); | 300 | smp_callin(); |
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 8b6c393ab9fd..22fd6577156a 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c | |||
| @@ -960,8 +960,6 @@ static inline int __init activate_vmi(void) | |||
| 960 | 960 | ||
| 961 | void __init vmi_init(void) | 961 | void __init vmi_init(void) |
| 962 | { | 962 | { |
| 963 | unsigned long flags; | ||
| 964 | |||
| 965 | if (!vmi_rom) | 963 | if (!vmi_rom) |
| 966 | probe_vmi_rom(); | 964 | probe_vmi_rom(); |
| 967 | else | 965 | else |
| @@ -973,13 +971,21 @@ void __init vmi_init(void) | |||
| 973 | 971 | ||
| 974 | reserve_top_address(-vmi_rom->virtual_top); | 972 | reserve_top_address(-vmi_rom->virtual_top); |
| 975 | 973 | ||
| 976 | local_irq_save(flags); | ||
| 977 | activate_vmi(); | ||
| 978 | |||
| 979 | #ifdef CONFIG_X86_IO_APIC | 974 | #ifdef CONFIG_X86_IO_APIC |
| 980 | /* This is virtual hardware; timer routing is wired correctly */ | 975 | /* This is virtual hardware; timer routing is wired correctly */ |
| 981 | no_timer_check = 1; | 976 | no_timer_check = 1; |
| 982 | #endif | 977 | #endif |
| 978 | } | ||
| 979 | |||
| 980 | void vmi_activate(void) | ||
| 981 | { | ||
| 982 | unsigned long flags; | ||
| 983 | |||
| 984 | if (!vmi_rom) | ||
| 985 | return; | ||
| 986 | |||
| 987 | local_irq_save(flags); | ||
| 988 | activate_vmi(); | ||
| 983 | local_irq_restore(flags & X86_EFLAGS_IF); | 989 | local_irq_restore(flags & X86_EFLAGS_IF); |
| 984 | } | 990 | } |
| 985 | 991 | ||
