diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-20 17:25:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-20 17:25:08 -0400 |
| commit | 36423a5ed5e4ea95ceedb68fad52965033e11639 (patch) | |
| tree | 6835f907a07b5d5d4861455e8b46398da652a3d4 | |
| parent | f6143a9b732977859cb6e04c604d04976aa5ccbd (diff) | |
| parent | 05e407603e527f9d808dd3866d3a17c2ce4dfcc5 (diff) | |
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, apic: Fix apic=debug boot crash
x86, hotplug: Serialize CPU hotplug to avoid bringup concurrency issues
x86-32: Fix dummy trampoline-related inline stubs
x86-32: Separate 1:1 pagetables from swapper_pg_dir
x86, cpu: Fix regression in AMD errata checking code
| -rw-r--r-- | arch/x86/Kconfig | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/pgtable_32.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/trampoline.h | 5 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/head_32.S | 8 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/smpboot.c | 51 | ||||
| -rw-r--r-- | arch/x86/kernel/trampoline.c | 18 |
9 files changed, 72 insertions, 22 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a84fc34c8f77..ac7827fc0823 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -245,6 +245,11 @@ config ARCH_HWEIGHT_CFLAGS | |||
| 245 | 245 | ||
| 246 | config KTIME_SCALAR | 246 | config KTIME_SCALAR |
| 247 | def_bool X86_32 | 247 | def_bool X86_32 |
| 248 | |||
| 249 | config ARCH_CPU_PROBE_RELEASE | ||
| 250 | def_bool y | ||
| 251 | depends on HOTPLUG_CPU | ||
| 252 | |||
| 248 | source "init/Kconfig" | 253 | source "init/Kconfig" |
| 249 | source "kernel/Kconfig.freezer" | 254 | source "kernel/Kconfig.freezer" |
| 250 | 255 | ||
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h index 2984a25ff383..f686f49e8b7b 100644 --- a/arch/x86/include/asm/pgtable_32.h +++ b/arch/x86/include/asm/pgtable_32.h | |||
| @@ -26,6 +26,7 @@ struct mm_struct; | |||
| 26 | struct vm_area_struct; | 26 | struct vm_area_struct; |
| 27 | 27 | ||
| 28 | extern pgd_t swapper_pg_dir[1024]; | 28 | extern pgd_t swapper_pg_dir[1024]; |
| 29 | extern pgd_t trampoline_pg_dir[1024]; | ||
| 29 | 30 | ||
| 30 | static inline void pgtable_cache_init(void) { } | 31 | static inline void pgtable_cache_init(void) { } |
| 31 | static inline void check_pgt_cache(void) { } | 32 | static inline void check_pgt_cache(void) { } |
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index cb507bb05d79..4dde797c0578 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h | |||
| @@ -13,14 +13,17 @@ extern unsigned char *trampoline_base; | |||
| 13 | 13 | ||
| 14 | extern unsigned long init_rsp; | 14 | extern unsigned long init_rsp; |
| 15 | extern unsigned long initial_code; | 15 | extern unsigned long initial_code; |
| 16 | extern unsigned long initial_page_table; | ||
| 16 | extern unsigned long initial_gs; | 17 | extern unsigned long initial_gs; |
| 17 | 18 | ||
| 18 | #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) | 19 | #define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) |
| 19 | 20 | ||
| 20 | extern unsigned long setup_trampoline(void); | 21 | extern unsigned long setup_trampoline(void); |
| 22 | extern void __init setup_trampoline_page_table(void); | ||
| 21 | extern void __init reserve_trampoline_memory(void); | 23 | extern void __init reserve_trampoline_memory(void); |
| 22 | #else | 24 | #else |
| 23 | static inline void reserve_trampoline_memory(void) {}; | 25 | static inline void setup_trampoline_page_table(void) {} |
| 26 | static inline void reserve_trampoline_memory(void) {} | ||
| 24 | #endif /* CONFIG_X86_TRAMPOLINE */ | 27 | #endif /* CONFIG_X86_TRAMPOLINE */ |
| 25 | 28 | ||
| 26 | #endif /* __ASSEMBLY__ */ | 29 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 4dc0084ec1b1..f1efebaf5510 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -1728,6 +1728,8 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
| 1728 | struct irq_pin_list *entry; | 1728 | struct irq_pin_list *entry; |
| 1729 | 1729 | ||
| 1730 | cfg = desc->chip_data; | 1730 | cfg = desc->chip_data; |
| 1731 | if (!cfg) | ||
| 1732 | continue; | ||
| 1731 | entry = cfg->irq_2_pin; | 1733 | entry = cfg->irq_2_pin; |
| 1732 | if (!entry) | 1734 | if (!entry) |
| 1733 | continue; | 1735 | continue; |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 60a57b13082d..ba5f62f45f01 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
| @@ -669,7 +669,7 @@ bool cpu_has_amd_erratum(const int *erratum) | |||
| 669 | } | 669 | } |
| 670 | 670 | ||
| 671 | /* OSVW unavailable or ID unknown, match family-model-stepping range */ | 671 | /* OSVW unavailable or ID unknown, match family-model-stepping range */ |
| 672 | ms = (cpu->x86_model << 8) | cpu->x86_mask; | 672 | ms = (cpu->x86_model << 4) | cpu->x86_mask; |
| 673 | while ((range = *erratum++)) | 673 | while ((range = *erratum++)) |
| 674 | if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && | 674 | if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) && |
| 675 | (ms >= AMD_MODEL_RANGE_START(range)) && | 675 | (ms >= AMD_MODEL_RANGE_START(range)) && |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index ff4c453e13f3..fa8c1b8e09fb 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
| @@ -334,7 +334,7 @@ ENTRY(startup_32_smp) | |||
| 334 | /* | 334 | /* |
| 335 | * Enable paging | 335 | * Enable paging |
| 336 | */ | 336 | */ |
| 337 | movl $pa(swapper_pg_dir),%eax | 337 | movl pa(initial_page_table), %eax |
| 338 | movl %eax,%cr3 /* set the page table pointer.. */ | 338 | movl %eax,%cr3 /* set the page table pointer.. */ |
| 339 | movl %cr0,%eax | 339 | movl %cr0,%eax |
| 340 | orl $X86_CR0_PG,%eax | 340 | orl $X86_CR0_PG,%eax |
| @@ -614,6 +614,8 @@ ignore_int: | |||
| 614 | .align 4 | 614 | .align 4 |
| 615 | ENTRY(initial_code) | 615 | ENTRY(initial_code) |
| 616 | .long i386_start_kernel | 616 | .long i386_start_kernel |
| 617 | ENTRY(initial_page_table) | ||
| 618 | .long pa(swapper_pg_dir) | ||
| 617 | 619 | ||
| 618 | /* | 620 | /* |
| 619 | * BSS section | 621 | * BSS section |
| @@ -629,6 +631,10 @@ ENTRY(swapper_pg_dir) | |||
| 629 | #endif | 631 | #endif |
| 630 | swapper_pg_fixmap: | 632 | swapper_pg_fixmap: |
| 631 | .fill 1024,4,0 | 633 | .fill 1024,4,0 |
| 634 | #ifdef CONFIG_X86_TRAMPOLINE | ||
| 635 | ENTRY(trampoline_pg_dir) | ||
| 636 | .fill 1024,4,0 | ||
| 637 | #endif | ||
| 632 | ENTRY(empty_zero_page) | 638 | ENTRY(empty_zero_page) |
| 633 | .fill 4096,1,0 | 639 | .fill 4096,1,0 |
| 634 | 640 | ||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index b008e7883207..c3a4fbb2b996 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -1014,6 +1014,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 1014 | paging_init(); | 1014 | paging_init(); |
| 1015 | x86_init.paging.pagetable_setup_done(swapper_pg_dir); | 1015 | x86_init.paging.pagetable_setup_done(swapper_pg_dir); |
| 1016 | 1016 | ||
| 1017 | setup_trampoline_page_table(); | ||
| 1018 | |||
| 1017 | tboot_probe(); | 1019 | tboot_probe(); |
| 1018 | 1020 | ||
| 1019 | #ifdef CONFIG_X86_64 | 1021 | #ifdef CONFIG_X86_64 |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index a5e928b0cb5f..8b3bfc4dd708 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -73,7 +73,6 @@ | |||
| 73 | 73 | ||
| 74 | #ifdef CONFIG_X86_32 | 74 | #ifdef CONFIG_X86_32 |
| 75 | u8 apicid_2_node[MAX_APICID]; | 75 | u8 apicid_2_node[MAX_APICID]; |
| 76 | static int low_mappings; | ||
| 77 | #endif | 76 | #endif |
| 78 | 77 | ||
| 79 | /* State of each CPU */ | 78 | /* State of each CPU */ |
| @@ -91,6 +90,25 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 }; | |||
| 91 | static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); | 90 | static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); |
| 92 | #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) | 91 | #define get_idle_for_cpu(x) (per_cpu(idle_thread_array, x)) |
| 93 | #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) | 92 | #define set_idle_for_cpu(x, p) (per_cpu(idle_thread_array, x) = (p)) |
| 93 | |||
| 94 | /* | ||
| 95 | * We need this for trampoline_base protection from concurrent accesses when | ||
| 96 | * off- and onlining cores wildly. | ||
| 97 | */ | ||
| 98 | static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex); | ||
| 99 | |||
| 100 | void cpu_hotplug_driver_lock() | ||
| 101 | { | ||
| 102 | mutex_lock(&x86_cpu_hotplug_driver_mutex); | ||
| 103 | } | ||
| 104 | |||
| 105 | void cpu_hotplug_driver_unlock() | ||
| 106 | { | ||
| 107 | mutex_unlock(&x86_cpu_hotplug_driver_mutex); | ||
| 108 | } | ||
| 109 | |||
| 110 | ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } | ||
| 111 | ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } | ||
| 94 | #else | 112 | #else |
| 95 | static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; | 113 | static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; |
| 96 | #define get_idle_for_cpu(x) (idle_thread_array[(x)]) | 114 | #define get_idle_for_cpu(x) (idle_thread_array[(x)]) |
| @@ -281,6 +299,18 @@ notrace static void __cpuinit start_secondary(void *unused) | |||
| 281 | * fragile that we want to limit the things done here to the | 299 | * fragile that we want to limit the things done here to the |
| 282 | * most necessary things. | 300 | * most necessary things. |
| 283 | */ | 301 | */ |
| 302 | |||
| 303 | #ifdef CONFIG_X86_32 | ||
| 304 | /* | ||
| 305 | * Switch away from the trampoline page-table | ||
| 306 | * | ||
| 307 | * Do this before cpu_init() because it needs to access per-cpu | ||
| 308 | * data which may not be mapped in the trampoline page-table. | ||
| 309 | */ | ||
| 310 | load_cr3(swapper_pg_dir); | ||
| 311 | __flush_tlb_all(); | ||
| 312 | #endif | ||
| 313 | |||
| 284 | vmi_bringup(); | 314 | vmi_bringup(); |
| 285 | cpu_init(); | 315 | cpu_init(); |
| 286 | preempt_disable(); | 316 | preempt_disable(); |
| @@ -299,12 +329,6 @@ notrace static void __cpuinit start_secondary(void *unused) | |||
| 299 | legacy_pic->chip->unmask(0); | 329 | legacy_pic->chip->unmask(0); |
| 300 | } | 330 | } |
| 301 | 331 | ||
| 302 | #ifdef CONFIG_X86_32 | ||
| 303 | while (low_mappings) | ||
| 304 | cpu_relax(); | ||
| 305 | __flush_tlb_all(); | ||
| 306 | #endif | ||
| 307 | |||
| 308 | /* This must be done before setting cpu_online_mask */ | 332 | /* This must be done before setting cpu_online_mask */ |
| 309 | set_cpu_sibling_map(raw_smp_processor_id()); | 333 | set_cpu_sibling_map(raw_smp_processor_id()); |
| 310 | wmb(); | 334 | wmb(); |
| @@ -750,6 +774,7 @@ do_rest: | |||
| 750 | #ifdef CONFIG_X86_32 | 774 | #ifdef CONFIG_X86_32 |
| 751 | /* Stack for startup_32 can be just as for start_secondary onwards */ | 775 | /* Stack for startup_32 can be just as for start_secondary onwards */ |
| 752 | irq_ctx_init(cpu); | 776 | irq_ctx_init(cpu); |
| 777 | initial_page_table = __pa(&trampoline_pg_dir); | ||
| 753 | #else | 778 | #else |
| 754 | clear_tsk_thread_flag(c_idle.idle, TIF_FORK); | 779 | clear_tsk_thread_flag(c_idle.idle, TIF_FORK); |
| 755 | initial_gs = per_cpu_offset(cpu); | 780 | initial_gs = per_cpu_offset(cpu); |
| @@ -897,20 +922,8 @@ int __cpuinit native_cpu_up(unsigned int cpu) | |||
| 897 | 922 | ||
| 898 | per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; | 923 | per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; |
| 899 | 924 | ||
| 900 | #ifdef CONFIG_X86_32 | ||
| 901 | /* init low mem mapping */ | ||
| 902 | clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, | ||
| 903 | min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); | ||
| 904 | flush_tlb_all(); | ||
| 905 | low_mappings = 1; | ||
| 906 | |||
| 907 | err = do_boot_cpu(apicid, cpu); | 925 | err = do_boot_cpu(apicid, cpu); |
| 908 | 926 | ||
| 909 | zap_low_mappings(false); | ||
| 910 | low_mappings = 0; | ||
| 911 | #else | ||
| 912 | err = do_boot_cpu(apicid, cpu); | ||
| 913 | #endif | ||
| 914 | if (err) { | 927 | if (err) { |
| 915 | pr_debug("do_boot_cpu failed %d\n", err); | 928 | pr_debug("do_boot_cpu failed %d\n", err); |
| 916 | return -EIO; | 929 | return -EIO; |
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c index c652ef62742d..a874495b3673 100644 --- a/arch/x86/kernel/trampoline.c +++ b/arch/x86/kernel/trampoline.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/io.h> | 1 | #include <linux/io.h> |
| 2 | 2 | ||
| 3 | #include <asm/trampoline.h> | 3 | #include <asm/trampoline.h> |
| 4 | #include <asm/pgtable.h> | ||
| 4 | #include <asm/e820.h> | 5 | #include <asm/e820.h> |
| 5 | 6 | ||
| 6 | #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP) | 7 | #if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP) |
| @@ -37,3 +38,20 @@ unsigned long __trampinit setup_trampoline(void) | |||
| 37 | memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE); | 38 | memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE); |
| 38 | return virt_to_phys(trampoline_base); | 39 | return virt_to_phys(trampoline_base); |
| 39 | } | 40 | } |
| 41 | |||
| 42 | void __init setup_trampoline_page_table(void) | ||
| 43 | { | ||
| 44 | #ifdef CONFIG_X86_32 | ||
| 45 | /* Copy kernel address range */ | ||
| 46 | clone_pgd_range(trampoline_pg_dir + KERNEL_PGD_BOUNDARY, | ||
| 47 | swapper_pg_dir + KERNEL_PGD_BOUNDARY, | ||
| 48 | min_t(unsigned long, KERNEL_PGD_PTRS, | ||
| 49 | KERNEL_PGD_BOUNDARY)); | ||
| 50 | |||
| 51 | /* Initialize low mappings */ | ||
| 52 | clone_pgd_range(trampoline_pg_dir, | ||
| 53 | swapper_pg_dir + KERNEL_PGD_BOUNDARY, | ||
| 54 | min_t(unsigned long, KERNEL_PGD_PTRS, | ||
| 55 | KERNEL_PGD_BOUNDARY)); | ||
| 56 | #endif | ||
| 57 | } | ||
