diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-15 12:32:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-15 12:32:59 -0500 |
commit | bba072dfd7bf87f0712e569a78ae9c0e91e0a8df (patch) | |
tree | 12b89e5c5b24183c21988129ef3a837edd925b4b | |
parent | 511601bdbcacd3ab615564941409bf012435b23d (diff) | |
parent | 04633df0c43d710e5f696b06539c100898678235 (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner:
"A couple of fixes and updates related to x86:
- Fix the W+X check regression on XEN
- The real fix for the low identity map trainwreck
- Probe legacy PIC early instead of unconditionally allocating legacy
irqs
- Add cpu verification to long mode entry
- Adjust the cache topology to AMD Fam17H systems
- Let Merrifield use the TSC across S3"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/cpu: Call verify_cpu() after having entered long mode too
x86/setup: Fix low identity map for >= 2GB kernel range
x86/mm: Skip the hypervisor range when walking PGD
x86/AMD: Fix last level cache topology for AMD Fam17h systems
x86/irq: Probe for PIC presence before allocating descs for legacy IRQs
x86/cpu/intel: Enable X86_FEATURE_NONSTOP_TSC_S3 for Merrifield
-rw-r--r-- | arch/x86/include/asm/i8259.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/vector.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/amd.c | 13 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/intel.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/head_64.S | 8 | ||||
-rw-r--r-- | arch/x86/kernel/i8259.c | 29 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/verify_cpu.S | 12 | ||||
-rw-r--r-- | arch/x86/mm/dump_pagetables.c | 17 |
9 files changed, 73 insertions, 16 deletions
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h index ccffa53750a8..39bcefc20de7 100644 --- a/arch/x86/include/asm/i8259.h +++ b/arch/x86/include/asm/i8259.h | |||
@@ -60,6 +60,7 @@ struct legacy_pic { | |||
60 | void (*mask_all)(void); | 60 | void (*mask_all)(void); |
61 | void (*restore_mask)(void); | 61 | void (*restore_mask)(void); |
62 | void (*init)(int auto_eoi); | 62 | void (*init)(int auto_eoi); |
63 | int (*probe)(void); | ||
63 | int (*irq_pending)(unsigned int irq); | 64 | int (*irq_pending)(unsigned int irq); |
64 | void (*make_irq)(unsigned int irq); | 65 | void (*make_irq)(unsigned int irq); |
65 | }; | 66 | }; |
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 836d11b92811..861bc59c8f25 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
@@ -361,7 +361,11 @@ int __init arch_probe_nr_irqs(void) | |||
361 | if (nr < nr_irqs) | 361 | if (nr < nr_irqs) |
362 | nr_irqs = nr; | 362 | nr_irqs = nr; |
363 | 363 | ||
364 | return nr_legacy_irqs(); | 364 | /* |
365 | * We don't know if PIC is present at this point so we need to do | ||
366 | * probe() to get the right number of legacy IRQs. | ||
367 | */ | ||
368 | return legacy_pic->probe(); | ||
365 | } | 369 | } |
366 | 370 | ||
367 | #ifdef CONFIG_X86_IO_APIC | 371 | #ifdef CONFIG_X86_IO_APIC |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 4a70fc6d400a..a8816b325162 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -352,6 +352,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c) | |||
352 | #ifdef CONFIG_SMP | 352 | #ifdef CONFIG_SMP |
353 | unsigned bits; | 353 | unsigned bits; |
354 | int cpu = smp_processor_id(); | 354 | int cpu = smp_processor_id(); |
355 | unsigned int socket_id, core_complex_id; | ||
355 | 356 | ||
356 | bits = c->x86_coreid_bits; | 357 | bits = c->x86_coreid_bits; |
357 | /* Low order bits define the core id (index of core in socket) */ | 358 | /* Low order bits define the core id (index of core in socket) */ |
@@ -361,6 +362,18 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c) | |||
361 | /* use socket ID also for last level cache */ | 362 | /* use socket ID also for last level cache */ |
362 | per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; | 363 | per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; |
363 | amd_get_topology(c); | 364 | amd_get_topology(c); |
365 | |||
366 | /* | ||
367 | * Fix percpu cpu_llc_id here as LLC topology is different | ||
368 | * for Fam17h systems. | ||
369 | */ | ||
370 | if (c->x86 != 0x17 || !cpuid_edx(0x80000006)) | ||
371 | return; | ||
372 | |||
373 | socket_id = (c->apicid >> bits) - 1; | ||
374 | core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3; | ||
375 | |||
376 | per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id; | ||
364 | #endif | 377 | #endif |
365 | } | 378 | } |
366 | 379 | ||
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 98a13db5f4be..209ac1e7d1f0 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -97,6 +97,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) | |||
97 | switch (c->x86_model) { | 97 | switch (c->x86_model) { |
98 | case 0x27: /* Penwell */ | 98 | case 0x27: /* Penwell */ |
99 | case 0x35: /* Cloverview */ | 99 | case 0x35: /* Cloverview */ |
100 | case 0x4a: /* Merrifield */ | ||
100 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3); | 101 | set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3); |
101 | break; | 102 | break; |
102 | default: | 103 | default: |
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 1d40ca8a73f2..ffdc0e860390 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
@@ -65,6 +65,9 @@ startup_64: | |||
65 | * tables and then reload them. | 65 | * tables and then reload them. |
66 | */ | 66 | */ |
67 | 67 | ||
68 | /* Sanitize CPU configuration */ | ||
69 | call verify_cpu | ||
70 | |||
68 | /* | 71 | /* |
69 | * Compute the delta between the address I am compiled to run at and the | 72 | * Compute the delta between the address I am compiled to run at and the |
70 | * address I am actually running at. | 73 | * address I am actually running at. |
@@ -174,6 +177,9 @@ ENTRY(secondary_startup_64) | |||
174 | * after the boot processor executes this code. | 177 | * after the boot processor executes this code. |
175 | */ | 178 | */ |
176 | 179 | ||
180 | /* Sanitize CPU configuration */ | ||
181 | call verify_cpu | ||
182 | |||
177 | movq $(init_level4_pgt - __START_KERNEL_map), %rax | 183 | movq $(init_level4_pgt - __START_KERNEL_map), %rax |
178 | 1: | 184 | 1: |
179 | 185 | ||
@@ -288,6 +294,8 @@ ENTRY(secondary_startup_64) | |||
288 | pushq %rax # target address in negative space | 294 | pushq %rax # target address in negative space |
289 | lretq | 295 | lretq |
290 | 296 | ||
297 | #include "verify_cpu.S" | ||
298 | |||
291 | #ifdef CONFIG_HOTPLUG_CPU | 299 | #ifdef CONFIG_HOTPLUG_CPU |
292 | /* | 300 | /* |
293 | * Boot CPU0 entry point. It's called from play_dead(). Everything has been set | 301 | * Boot CPU0 entry point. It's called from play_dead(). Everything has been set |
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index 16cb827a5b27..be22f5a2192e 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
@@ -295,16 +295,11 @@ static void unmask_8259A(void) | |||
295 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | 295 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
296 | } | 296 | } |
297 | 297 | ||
298 | static void init_8259A(int auto_eoi) | 298 | static int probe_8259A(void) |
299 | { | 299 | { |
300 | unsigned long flags; | 300 | unsigned long flags; |
301 | unsigned char probe_val = ~(1 << PIC_CASCADE_IR); | 301 | unsigned char probe_val = ~(1 << PIC_CASCADE_IR); |
302 | unsigned char new_val; | 302 | unsigned char new_val; |
303 | |||
304 | i8259A_auto_eoi = auto_eoi; | ||
305 | |||
306 | raw_spin_lock_irqsave(&i8259A_lock, flags); | ||
307 | |||
308 | /* | 303 | /* |
309 | * Check to see if we have a PIC. | 304 | * Check to see if we have a PIC. |
310 | * Mask all except the cascade and read | 305 | * Mask all except the cascade and read |
@@ -312,16 +307,28 @@ static void init_8259A(int auto_eoi) | |||
312 | * have a PIC, we will read 0xff as opposed to the | 307 | * have a PIC, we will read 0xff as opposed to the |
313 | * value we wrote. | 308 | * value we wrote. |
314 | */ | 309 | */ |
310 | raw_spin_lock_irqsave(&i8259A_lock, flags); | ||
311 | |||
315 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ | 312 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
316 | outb(probe_val, PIC_MASTER_IMR); | 313 | outb(probe_val, PIC_MASTER_IMR); |
317 | new_val = inb(PIC_MASTER_IMR); | 314 | new_val = inb(PIC_MASTER_IMR); |
318 | if (new_val != probe_val) { | 315 | if (new_val != probe_val) { |
319 | printk(KERN_INFO "Using NULL legacy PIC\n"); | 316 | printk(KERN_INFO "Using NULL legacy PIC\n"); |
320 | legacy_pic = &null_legacy_pic; | 317 | legacy_pic = &null_legacy_pic; |
321 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | ||
322 | return; | ||
323 | } | 318 | } |
324 | 319 | ||
320 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | ||
321 | return nr_legacy_irqs(); | ||
322 | } | ||
323 | |||
324 | static void init_8259A(int auto_eoi) | ||
325 | { | ||
326 | unsigned long flags; | ||
327 | |||
328 | i8259A_auto_eoi = auto_eoi; | ||
329 | |||
330 | raw_spin_lock_irqsave(&i8259A_lock, flags); | ||
331 | |||
325 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 332 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
326 | 333 | ||
327 | /* | 334 | /* |
@@ -379,6 +386,10 @@ static int legacy_pic_irq_pending_noop(unsigned int irq) | |||
379 | { | 386 | { |
380 | return 0; | 387 | return 0; |
381 | } | 388 | } |
389 | static int legacy_pic_probe(void) | ||
390 | { | ||
391 | return 0; | ||
392 | } | ||
382 | 393 | ||
383 | struct legacy_pic null_legacy_pic = { | 394 | struct legacy_pic null_legacy_pic = { |
384 | .nr_legacy_irqs = 0, | 395 | .nr_legacy_irqs = 0, |
@@ -388,6 +399,7 @@ struct legacy_pic null_legacy_pic = { | |||
388 | .mask_all = legacy_pic_noop, | 399 | .mask_all = legacy_pic_noop, |
389 | .restore_mask = legacy_pic_noop, | 400 | .restore_mask = legacy_pic_noop, |
390 | .init = legacy_pic_int_noop, | 401 | .init = legacy_pic_int_noop, |
402 | .probe = legacy_pic_probe, | ||
391 | .irq_pending = legacy_pic_irq_pending_noop, | 403 | .irq_pending = legacy_pic_irq_pending_noop, |
392 | .make_irq = legacy_pic_uint_noop, | 404 | .make_irq = legacy_pic_uint_noop, |
393 | }; | 405 | }; |
@@ -400,6 +412,7 @@ struct legacy_pic default_legacy_pic = { | |||
400 | .mask_all = mask_8259A, | 412 | .mask_all = mask_8259A, |
401 | .restore_mask = unmask_8259A, | 413 | .restore_mask = unmask_8259A, |
402 | .init = init_8259A, | 414 | .init = init_8259A, |
415 | .probe = probe_8259A, | ||
403 | .irq_pending = i8259A_irq_pending, | 416 | .irq_pending = i8259A_irq_pending, |
404 | .make_irq = make_8259A_irq, | 417 | .make_irq = make_8259A_irq, |
405 | }; | 418 | }; |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a1e4da98c8f0..29db25f9a745 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -1188,7 +1188,7 @@ void __init setup_arch(char **cmdline_p) | |||
1188 | */ | 1188 | */ |
1189 | clone_pgd_range(initial_page_table, | 1189 | clone_pgd_range(initial_page_table, |
1190 | swapper_pg_dir + KERNEL_PGD_BOUNDARY, | 1190 | swapper_pg_dir + KERNEL_PGD_BOUNDARY, |
1191 | KERNEL_PGD_PTRS); | 1191 | min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); |
1192 | #endif | 1192 | #endif |
1193 | 1193 | ||
1194 | tboot_probe(); | 1194 | tboot_probe(); |
diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S index b9242bacbe59..4cf401f581e7 100644 --- a/arch/x86/kernel/verify_cpu.S +++ b/arch/x86/kernel/verify_cpu.S | |||
@@ -34,10 +34,11 @@ | |||
34 | #include <asm/msr-index.h> | 34 | #include <asm/msr-index.h> |
35 | 35 | ||
36 | verify_cpu: | 36 | verify_cpu: |
37 | pushfl # Save caller passed flags | 37 | pushf # Save caller passed flags |
38 | pushl $0 # Kill any dangerous flags | 38 | push $0 # Kill any dangerous flags |
39 | popfl | 39 | popf |
40 | 40 | ||
41 | #ifndef __x86_64__ | ||
41 | pushfl # standard way to check for cpuid | 42 | pushfl # standard way to check for cpuid |
42 | popl %eax | 43 | popl %eax |
43 | movl %eax,%ebx | 44 | movl %eax,%ebx |
@@ -48,6 +49,7 @@ verify_cpu: | |||
48 | popl %eax | 49 | popl %eax |
49 | cmpl %eax,%ebx | 50 | cmpl %eax,%ebx |
50 | jz verify_cpu_no_longmode # cpu has no cpuid | 51 | jz verify_cpu_no_longmode # cpu has no cpuid |
52 | #endif | ||
51 | 53 | ||
52 | movl $0x0,%eax # See if cpuid 1 is implemented | 54 | movl $0x0,%eax # See if cpuid 1 is implemented |
53 | cpuid | 55 | cpuid |
@@ -130,10 +132,10 @@ verify_cpu_sse_test: | |||
130 | jmp verify_cpu_sse_test # try again | 132 | jmp verify_cpu_sse_test # try again |
131 | 133 | ||
132 | verify_cpu_no_longmode: | 134 | verify_cpu_no_longmode: |
133 | popfl # Restore caller passed flags | 135 | popf # Restore caller passed flags |
134 | movl $1,%eax | 136 | movl $1,%eax |
135 | ret | 137 | ret |
136 | verify_cpu_sse_ok: | 138 | verify_cpu_sse_ok: |
137 | popfl # Restore caller passed flags | 139 | popf # Restore caller passed flags |
138 | xorl %eax, %eax | 140 | xorl %eax, %eax |
139 | ret | 141 | ret |
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 1bf417e9cc13..a035c2aa7801 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c | |||
@@ -358,6 +358,21 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr, | |||
358 | #define pgd_none(a) pud_none(__pud(pgd_val(a))) | 358 | #define pgd_none(a) pud_none(__pud(pgd_val(a))) |
359 | #endif | 359 | #endif |
360 | 360 | ||
361 | #ifdef CONFIG_X86_64 | ||
362 | static inline bool is_hypervisor_range(int idx) | ||
363 | { | ||
364 | /* | ||
365 | * ffff800000000000 - ffff87ffffffffff is reserved for | ||
366 | * the hypervisor. | ||
367 | */ | ||
368 | return paravirt_enabled() && | ||
369 | (idx >= pgd_index(__PAGE_OFFSET) - 16) && | ||
370 | (idx < pgd_index(__PAGE_OFFSET)); | ||
371 | } | ||
372 | #else | ||
373 | static inline bool is_hypervisor_range(int idx) { return false; } | ||
374 | #endif | ||
375 | |||
361 | static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, | 376 | static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, |
362 | bool checkwx) | 377 | bool checkwx) |
363 | { | 378 | { |
@@ -381,7 +396,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, | |||
381 | 396 | ||
382 | for (i = 0; i < PTRS_PER_PGD; i++) { | 397 | for (i = 0; i < PTRS_PER_PGD; i++) { |
383 | st.current_address = normalize_addr(i * PGD_LEVEL_MULT); | 398 | st.current_address = normalize_addr(i * PGD_LEVEL_MULT); |
384 | if (!pgd_none(*start)) { | 399 | if (!pgd_none(*start) && !is_hypervisor_range(i)) { |
385 | if (pgd_large(*start) || !pgd_present(*start)) { | 400 | if (pgd_large(*start) || !pgd_present(*start)) { |
386 | prot = pgd_flags(*start); | 401 | prot = pgd_flags(*start); |
387 | note_page(m, &st, __pgprot(prot), 1); | 402 | note_page(m, &st, __pgprot(prot), 1); |