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 | } | ||