aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-03-04 14:40:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-03-04 14:40:16 -0500
commit7225a442788e20ee108ef2cb97d511375e20acf9 (patch)
tree98b2ecf1b606bd843356a8df7826a2e1c78d1eca
parent4c4ce3022dc7352d05de4d8e1602c9a2a14458bf (diff)
parent945fd17ab6bab8a4d05da6c3170519fbcfe62ddb (diff)
Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/pti fixes from Thomas Gleixner: "Three fixes related to melted spectrum: - Sync the cpu_entry_area page table to initial_page_table on 32 bit. Otherwise suspend/resume fails because resume uses initial_page_table and triggers a triple fault when accessing the cpu entry area. - Zero the SPEC_CTL MRS on XEN before suspend to address a shortcoming in the hypervisor. - Fix another switch table detection issue in objtool" * 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpu_entry_area: Sync cpu_entry_area to initial_page_table objtool: Fix another switch table detection issue x86/xen: Zero MSR_IA32_SPEC_CTRL before suspend
-rw-r--r--arch/x86/include/asm/pgtable_32.h1
-rw-r--r--arch/x86/include/asm/pgtable_64.h1
-rw-r--r--arch/x86/kernel/setup.c17
-rw-r--r--arch/x86/kernel/setup_percpu.c17
-rw-r--r--arch/x86/mm/cpu_entry_area.c6
-rw-r--r--arch/x86/mm/init_32.c15
-rw-r--r--arch/x86/xen/suspend.c16
-rw-r--r--tools/objtool/check.c6
8 files changed, 53 insertions, 26 deletions
diff --git a/arch/x86/include/asm/pgtable_32.h b/arch/x86/include/asm/pgtable_32.h
index e55466760ff8..b3ec519e3982 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -32,6 +32,7 @@ extern pmd_t initial_pg_pmd[];
32static inline void pgtable_cache_init(void) { } 32static inline void pgtable_cache_init(void) { }
33static inline void check_pgt_cache(void) { } 33static inline void check_pgt_cache(void) { }
34void paging_init(void); 34void paging_init(void);
35void sync_initial_page_table(void);
35 36
36/* 37/*
37 * Define this if things work differently on an i386 and an i486: 38 * Define this if things work differently on an i386 and an i486:
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 81462e9a34f6..1149d2112b2e 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -28,6 +28,7 @@ extern pgd_t init_top_pgt[];
28#define swapper_pg_dir init_top_pgt 28#define swapper_pg_dir init_top_pgt
29 29
30extern void paging_init(void); 30extern void paging_init(void);
31static inline void sync_initial_page_table(void) { }
31 32
32#define pte_ERROR(e) \ 33#define pte_ERROR(e) \
33 pr_err("%s:%d: bad pte %p(%016lx)\n", \ 34 pr_err("%s:%d: bad pte %p(%016lx)\n", \
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1ae67e982af7..4c616be28506 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1204,20 +1204,13 @@ void __init setup_arch(char **cmdline_p)
1204 1204
1205 kasan_init(); 1205 kasan_init();
1206 1206
1207#ifdef CONFIG_X86_32
1208 /* sync back kernel address range */
1209 clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
1210 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
1211 KERNEL_PGD_PTRS);
1212
1213 /* 1207 /*
1214 * sync back low identity map too. It is used for example 1208 * Sync back kernel address range.
1215 * in the 32-bit EFI stub. 1209 *
1210 * FIXME: Can the later sync in setup_cpu_entry_areas() replace
1211 * this call?
1216 */ 1212 */
1217 clone_pgd_range(initial_page_table, 1213 sync_initial_page_table();
1218 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
1219 min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
1220#endif
1221 1214
1222 tboot_probe(); 1215 tboot_probe();
1223 1216
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 497aa766fab3..ea554f812ee1 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -287,24 +287,15 @@ void __init setup_per_cpu_areas(void)
287 /* Setup cpu initialized, callin, callout masks */ 287 /* Setup cpu initialized, callin, callout masks */
288 setup_cpu_local_masks(); 288 setup_cpu_local_masks();
289 289
290#ifdef CONFIG_X86_32
291 /* 290 /*
292 * Sync back kernel address range again. We already did this in 291 * Sync back kernel address range again. We already did this in
293 * setup_arch(), but percpu data also needs to be available in 292 * setup_arch(), but percpu data also needs to be available in
294 * the smpboot asm. We can't reliably pick up percpu mappings 293 * the smpboot asm. We can't reliably pick up percpu mappings
295 * using vmalloc_fault(), because exception dispatch needs 294 * using vmalloc_fault(), because exception dispatch needs
296 * percpu data. 295 * percpu data.
296 *
297 * FIXME: Can the later sync in setup_cpu_entry_areas() replace
298 * this call?
297 */ 299 */
298 clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, 300 sync_initial_page_table();
299 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
300 KERNEL_PGD_PTRS);
301
302 /*
303 * sync back low identity map too. It is used for example
304 * in the 32-bit EFI stub.
305 */
306 clone_pgd_range(initial_page_table,
307 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
308 min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
309#endif
310} 301}
diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c
index b9283cc27622..476d810639a8 100644
--- a/arch/x86/mm/cpu_entry_area.c
+++ b/arch/x86/mm/cpu_entry_area.c
@@ -163,4 +163,10 @@ void __init setup_cpu_entry_areas(void)
163 163
164 for_each_possible_cpu(cpu) 164 for_each_possible_cpu(cpu)
165 setup_cpu_entry_area(cpu); 165 setup_cpu_entry_area(cpu);
166
167 /*
168 * This is the last essential update to swapper_pgdir which needs
169 * to be synchronized to initial_page_table on 32bit.
170 */
171 sync_initial_page_table();
166} 172}
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 79cb066f40c0..396e1f0151ac 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -453,6 +453,21 @@ static inline void permanent_kmaps_init(pgd_t *pgd_base)
453} 453}
454#endif /* CONFIG_HIGHMEM */ 454#endif /* CONFIG_HIGHMEM */
455 455
456void __init sync_initial_page_table(void)
457{
458 clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
459 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
460 KERNEL_PGD_PTRS);
461
462 /*
463 * sync back low identity map too. It is used for example
464 * in the 32-bit EFI stub.
465 */
466 clone_pgd_range(initial_page_table,
467 swapper_pg_dir + KERNEL_PGD_BOUNDARY,
468 min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
469}
470
456void __init native_pagetable_init(void) 471void __init native_pagetable_init(void)
457{ 472{
458 unsigned long pfn, va; 473 unsigned long pfn, va;
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index d9f96cc5d743..1d83152c761b 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -1,12 +1,15 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/types.h> 2#include <linux/types.h>
3#include <linux/tick.h> 3#include <linux/tick.h>
4#include <linux/percpu-defs.h>
4 5
5#include <xen/xen.h> 6#include <xen/xen.h>
6#include <xen/interface/xen.h> 7#include <xen/interface/xen.h>
7#include <xen/grant_table.h> 8#include <xen/grant_table.h>
8#include <xen/events.h> 9#include <xen/events.h>
9 10
11#include <asm/cpufeatures.h>
12#include <asm/msr-index.h>
10#include <asm/xen/hypercall.h> 13#include <asm/xen/hypercall.h>
11#include <asm/xen/page.h> 14#include <asm/xen/page.h>
12#include <asm/fixmap.h> 15#include <asm/fixmap.h>
@@ -15,6 +18,8 @@
15#include "mmu.h" 18#include "mmu.h"
16#include "pmu.h" 19#include "pmu.h"
17 20
21static DEFINE_PER_CPU(u64, spec_ctrl);
22
18void xen_arch_pre_suspend(void) 23void xen_arch_pre_suspend(void)
19{ 24{
20 xen_save_time_memory_area(); 25 xen_save_time_memory_area();
@@ -35,6 +40,9 @@ void xen_arch_post_suspend(int cancelled)
35 40
36static void xen_vcpu_notify_restore(void *data) 41static void xen_vcpu_notify_restore(void *data)
37{ 42{
43 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL))
44 wrmsrl(MSR_IA32_SPEC_CTRL, this_cpu_read(spec_ctrl));
45
38 /* Boot processor notified via generic timekeeping_resume() */ 46 /* Boot processor notified via generic timekeeping_resume() */
39 if (smp_processor_id() == 0) 47 if (smp_processor_id() == 0)
40 return; 48 return;
@@ -44,7 +52,15 @@ static void xen_vcpu_notify_restore(void *data)
44 52
45static void xen_vcpu_notify_suspend(void *data) 53static void xen_vcpu_notify_suspend(void *data)
46{ 54{
55 u64 tmp;
56
47 tick_suspend_local(); 57 tick_suspend_local();
58
59 if (xen_pv_domain() && boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
60 rdmsrl(MSR_IA32_SPEC_CTRL, tmp);
61 this_cpu_write(spec_ctrl, tmp);
62 wrmsrl(MSR_IA32_SPEC_CTRL, 0);
63 }
48} 64}
49 65
50void xen_arch_resume(void) 66void xen_arch_resume(void)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 472e64e95891..46c1d239cc1b 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -925,7 +925,11 @@ static struct rela *find_switch_table(struct objtool_file *file,
925 if (find_symbol_containing(file->rodata, text_rela->addend)) 925 if (find_symbol_containing(file->rodata, text_rela->addend))
926 continue; 926 continue;
927 927
928 return find_rela_by_dest(file->rodata, text_rela->addend); 928 rodata_rela = find_rela_by_dest(file->rodata, text_rela->addend);
929 if (!rodata_rela)
930 continue;
931
932 return rodata_rela;
929 } 933 }
930 934
931 return NULL; 935 return NULL;