diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-22 14:40:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-22 14:40:52 -0400 |
commit | 37a535edd72cacf73b456d4e9272ff2ee4bf7405 (patch) | |
tree | 0d856238eea6293d4cb2d3a00dd17736a2f3c506 | |
parent | c1e9dae0a9bf3394818abafaf376a34248c5f638 (diff) | |
parent | 05189820da23fc87ee2a7d87c20257f298af27f4 (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 small set of fixes for x86:
- Prevent X2APIC ID 0xFFFFFFFF from being treated as valid, which
causes the possible CPU count to be wrong.
- Prevent 32bit truncation in calc_hpet_ref() which causes the TSC
calibration to fail
- Fix the page table setup for temporary text mappings in the resume
code which causes resume failures
- Make the page table dump code handle HIGHPTE correctly instead of
oopsing
- Support for topologies where NUMA nodes share an LLC to prevent a
invalid topology warning and further malfunction on such systems.
- Remove the now unused pci-nommu code
- Remove stale function declarations"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/power/64: Fix page-table setup for temporary text mapping
x86/mm: Prevent kernel Oops in PTDUMP code with HIGHPTE=y
x86,sched: Allow topologies where NUMA nodes share an LLC
x86/processor: Remove two unused function declarations
x86/acpi: Prevent X2APIC id 0xffffffff from being accounted
x86/tsc: Prevent 32bit truncation in calc_hpet_ref()
x86: Remove pci-nommu.c
-rw-r--r-- | arch/x86/include/asm/processor.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/pci-nommu.c | 90 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 45 | ||||
-rw-r--r-- | arch/x86/kernel/tsc.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/dump_pagetables.c | 11 | ||||
-rw-r--r-- | arch/x86/power/hibernate_64.c | 2 |
7 files changed, 52 insertions, 104 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 4fa4206029e3..21a114914ba4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -749,13 +749,11 @@ enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT, | |||
749 | extern void enable_sep_cpu(void); | 749 | extern void enable_sep_cpu(void); |
750 | extern int sysenter_setup(void); | 750 | extern int sysenter_setup(void); |
751 | 751 | ||
752 | extern void early_trap_init(void); | ||
753 | void early_trap_pf_init(void); | 752 | void early_trap_pf_init(void); |
754 | 753 | ||
755 | /* Defined in head.S */ | 754 | /* Defined in head.S */ |
756 | extern struct desc_ptr early_gdt_descr; | 755 | extern struct desc_ptr early_gdt_descr; |
757 | 756 | ||
758 | extern void cpu_set_gdt(int); | ||
759 | extern void switch_to_new_gdt(int); | 757 | extern void switch_to_new_gdt(int); |
760 | extern void load_direct_gdt(int); | 758 | extern void load_direct_gdt(int); |
761 | extern void load_fixmap_gdt(int); | 759 | extern void load_fixmap_gdt(int); |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index dde444f932c1..3b20607d581b 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -215,6 +215,10 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) | |||
215 | apic_id = processor->local_apic_id; | 215 | apic_id = processor->local_apic_id; |
216 | enabled = processor->lapic_flags & ACPI_MADT_ENABLED; | 216 | enabled = processor->lapic_flags & ACPI_MADT_ENABLED; |
217 | 217 | ||
218 | /* Ignore invalid ID */ | ||
219 | if (apic_id == 0xffffffff) | ||
220 | return 0; | ||
221 | |||
218 | /* | 222 | /* |
219 | * We need to register disabled CPU as well to permit | 223 | * We need to register disabled CPU as well to permit |
220 | * counting disabled CPUs. This allows us to size | 224 | * counting disabled CPUs. This allows us to size |
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c deleted file mode 100644 index ac7ea3a8242f..000000000000 --- a/arch/x86/kernel/pci-nommu.c +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* Fallback functions when the main IOMMU code is not compiled in. This | ||
3 | code is roughly equivalent to i386. */ | ||
4 | #include <linux/dma-direct.h> | ||
5 | #include <linux/scatterlist.h> | ||
6 | #include <linux/string.h> | ||
7 | #include <linux/gfp.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/mm.h> | ||
10 | |||
11 | #include <asm/processor.h> | ||
12 | #include <asm/iommu.h> | ||
13 | #include <asm/dma.h> | ||
14 | |||
15 | #define NOMMU_MAPPING_ERROR 0 | ||
16 | |||
17 | static int | ||
18 | check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size) | ||
19 | { | ||
20 | if (hwdev && !dma_capable(hwdev, bus, size)) { | ||
21 | if (*hwdev->dma_mask >= DMA_BIT_MASK(32)) | ||
22 | printk(KERN_ERR | ||
23 | "nommu_%s: overflow %Lx+%zu of device mask %Lx\n", | ||
24 | name, (long long)bus, size, | ||
25 | (long long)*hwdev->dma_mask); | ||
26 | return 0; | ||
27 | } | ||
28 | return 1; | ||
29 | } | ||
30 | |||
31 | static dma_addr_t nommu_map_page(struct device *dev, struct page *page, | ||
32 | unsigned long offset, size_t size, | ||
33 | enum dma_data_direction dir, | ||
34 | unsigned long attrs) | ||
35 | { | ||
36 | dma_addr_t bus = phys_to_dma(dev, page_to_phys(page)) + offset; | ||
37 | WARN_ON(size == 0); | ||
38 | if (!check_addr("map_single", dev, bus, size)) | ||
39 | return NOMMU_MAPPING_ERROR; | ||
40 | return bus; | ||
41 | } | ||
42 | |||
43 | /* Map a set of buffers described by scatterlist in streaming | ||
44 | * mode for DMA. This is the scatter-gather version of the | ||
45 | * above pci_map_single interface. Here the scatter gather list | ||
46 | * elements are each tagged with the appropriate dma address | ||
47 | * and length. They are obtained via sg_dma_{address,length}(SG). | ||
48 | * | ||
49 | * NOTE: An implementation may be able to use a smaller number of | ||
50 | * DMA address/length pairs than there are SG table elements. | ||
51 | * (for example via virtual mapping capabilities) | ||
52 | * The routine returns the number of addr/length pairs actually | ||
53 | * used, at most nents. | ||
54 | * | ||
55 | * Device ownership issues as mentioned above for pci_map_single are | ||
56 | * the same here. | ||
57 | */ | ||
58 | static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, | ||
59 | int nents, enum dma_data_direction dir, | ||
60 | unsigned long attrs) | ||
61 | { | ||
62 | struct scatterlist *s; | ||
63 | int i; | ||
64 | |||
65 | WARN_ON(nents == 0 || sg[0].length == 0); | ||
66 | |||
67 | for_each_sg(sg, s, nents, i) { | ||
68 | BUG_ON(!sg_page(s)); | ||
69 | s->dma_address = sg_phys(s); | ||
70 | if (!check_addr("map_sg", hwdev, s->dma_address, s->length)) | ||
71 | return 0; | ||
72 | s->dma_length = s->length; | ||
73 | } | ||
74 | return nents; | ||
75 | } | ||
76 | |||
77 | static int nommu_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
78 | { | ||
79 | return dma_addr == NOMMU_MAPPING_ERROR; | ||
80 | } | ||
81 | |||
82 | const struct dma_map_ops nommu_dma_ops = { | ||
83 | .alloc = dma_generic_alloc_coherent, | ||
84 | .free = dma_generic_free_coherent, | ||
85 | .map_sg = nommu_map_sg, | ||
86 | .map_page = nommu_map_page, | ||
87 | .is_phys = 1, | ||
88 | .mapping_error = nommu_mapping_error, | ||
89 | .dma_supported = x86_dma_supported, | ||
90 | }; | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index ff99e2b6fc54..45175b81dd5b 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -77,6 +77,8 @@ | |||
77 | #include <asm/i8259.h> | 77 | #include <asm/i8259.h> |
78 | #include <asm/misc.h> | 78 | #include <asm/misc.h> |
79 | #include <asm/qspinlock.h> | 79 | #include <asm/qspinlock.h> |
80 | #include <asm/intel-family.h> | ||
81 | #include <asm/cpu_device_id.h> | ||
80 | 82 | ||
81 | /* Number of siblings per CPU package */ | 83 | /* Number of siblings per CPU package */ |
82 | int smp_num_siblings = 1; | 84 | int smp_num_siblings = 1; |
@@ -390,15 +392,47 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) | |||
390 | return false; | 392 | return false; |
391 | } | 393 | } |
392 | 394 | ||
395 | /* | ||
396 | * Define snc_cpu[] for SNC (Sub-NUMA Cluster) CPUs. | ||
397 | * | ||
398 | * These are Intel CPUs that enumerate an LLC that is shared by | ||
399 | * multiple NUMA nodes. The LLC on these systems is shared for | ||
400 | * off-package data access but private to the NUMA node (half | ||
401 | * of the package) for on-package access. | ||
402 | * | ||
403 | * CPUID (the source of the information about the LLC) can only | ||
404 | * enumerate the cache as being shared *or* unshared, but not | ||
405 | * this particular configuration. The CPU in this case enumerates | ||
406 | * the cache to be shared across the entire package (spanning both | ||
407 | * NUMA nodes). | ||
408 | */ | ||
409 | |||
410 | static const struct x86_cpu_id snc_cpu[] = { | ||
411 | { X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X }, | ||
412 | {} | ||
413 | }; | ||
414 | |||
393 | static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) | 415 | static bool match_llc(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) |
394 | { | 416 | { |
395 | int cpu1 = c->cpu_index, cpu2 = o->cpu_index; | 417 | int cpu1 = c->cpu_index, cpu2 = o->cpu_index; |
396 | 418 | ||
397 | if (per_cpu(cpu_llc_id, cpu1) != BAD_APICID && | 419 | /* Do not match if we do not have a valid APICID for cpu: */ |
398 | per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) | 420 | if (per_cpu(cpu_llc_id, cpu1) == BAD_APICID) |
399 | return topology_sane(c, o, "llc"); | 421 | return false; |
400 | 422 | ||
401 | return false; | 423 | /* Do not match if LLC id does not match: */ |
424 | if (per_cpu(cpu_llc_id, cpu1) != per_cpu(cpu_llc_id, cpu2)) | ||
425 | return false; | ||
426 | |||
427 | /* | ||
428 | * Allow the SNC topology without warning. Return of false | ||
429 | * means 'c' does not share the LLC of 'o'. This will be | ||
430 | * reflected to userspace. | ||
431 | */ | ||
432 | if (!topology_same_node(c, o) && x86_match_cpu(snc_cpu)) | ||
433 | return false; | ||
434 | |||
435 | return topology_sane(c, o, "llc"); | ||
402 | } | 436 | } |
403 | 437 | ||
404 | /* | 438 | /* |
@@ -456,7 +490,8 @@ static struct sched_domain_topology_level x86_topology[] = { | |||
456 | 490 | ||
457 | /* | 491 | /* |
458 | * Set if a package/die has multiple NUMA nodes inside. | 492 | * Set if a package/die has multiple NUMA nodes inside. |
459 | * AMD Magny-Cours and Intel Cluster-on-Die have this. | 493 | * AMD Magny-Cours, Intel Cluster-on-Die, and Intel |
494 | * Sub-NUMA Clustering have this. | ||
460 | */ | 495 | */ |
461 | static bool x86_has_numa_in_package; | 496 | static bool x86_has_numa_in_package; |
462 | 497 | ||
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index ef32297ff17e..91e6da48cbb6 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -317,7 +317,7 @@ static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, u64 hpet2) | |||
317 | hpet2 -= hpet1; | 317 | hpet2 -= hpet1; |
318 | tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); | 318 | tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); |
319 | do_div(tmp, 1000000); | 319 | do_div(tmp, 1000000); |
320 | do_div(deltatsc, tmp); | 320 | deltatsc = div64_u64(deltatsc, tmp); |
321 | 321 | ||
322 | return (unsigned long) deltatsc; | 322 | return (unsigned long) deltatsc; |
323 | } | 323 | } |
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 62a7e9f65dec..cc7ff5957194 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/highmem.h> | ||
21 | 22 | ||
22 | #include <asm/pgtable.h> | 23 | #include <asm/pgtable.h> |
23 | 24 | ||
@@ -334,16 +335,16 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr, | |||
334 | pgprotval_t eff_in, unsigned long P) | 335 | pgprotval_t eff_in, unsigned long P) |
335 | { | 336 | { |
336 | int i; | 337 | int i; |
337 | pte_t *start; | 338 | pte_t *pte; |
338 | pgprotval_t prot, eff; | 339 | pgprotval_t prot, eff; |
339 | 340 | ||
340 | start = (pte_t *)pmd_page_vaddr(addr); | ||
341 | for (i = 0; i < PTRS_PER_PTE; i++) { | 341 | for (i = 0; i < PTRS_PER_PTE; i++) { |
342 | prot = pte_flags(*start); | ||
343 | eff = effective_prot(eff_in, prot); | ||
344 | st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); | 342 | st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); |
343 | pte = pte_offset_map(&addr, st->current_address); | ||
344 | prot = pte_flags(*pte); | ||
345 | eff = effective_prot(eff_in, prot); | ||
345 | note_page(m, st, __pgprot(prot), eff, 5); | 346 | note_page(m, st, __pgprot(prot), eff, 5); |
346 | start++; | 347 | pte_unmap(pte); |
347 | } | 348 | } |
348 | } | 349 | } |
349 | #ifdef CONFIG_KASAN | 350 | #ifdef CONFIG_KASAN |
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index 48b14b534897..ccf4a49bb065 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c | |||
@@ -98,7 +98,7 @@ static int set_up_temporary_text_mapping(pgd_t *pgd) | |||
98 | set_pgd(pgd + pgd_index(restore_jump_address), new_pgd); | 98 | set_pgd(pgd + pgd_index(restore_jump_address), new_pgd); |
99 | } else { | 99 | } else { |
100 | /* No p4d for 4-level paging: point the pgd to the pud page table */ | 100 | /* No p4d for 4-level paging: point the pgd to the pud page table */ |
101 | pgd_t new_pgd = __pgd(__pa(p4d) | pgprot_val(pgtable_prot)); | 101 | pgd_t new_pgd = __pgd(__pa(pud) | pgprot_val(pgtable_prot)); |
102 | set_pgd(pgd + pgd_index(restore_jump_address), new_pgd); | 102 | set_pgd(pgd + pgd_index(restore_jump_address), new_pgd); |
103 | } | 103 | } |
104 | 104 | ||