diff options
author | Andy Lutomirski <luto@kernel.org> | 2017-09-17 12:03:51 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-09-17 12:59:09 -0400 |
commit | 4ba55e65f471d011d3ba2ac2022180ea0877d68e (patch) | |
tree | 1f2760ddbd6d5e8b97f824206b506ee9a892e2c4 | |
parent | b8b7abaed7a49b350f8ba659ddc264b04931d581 (diff) |
x86/mm/32: Load a sane CR3 before cpu_init() on secondary CPUs
For unknown historical reasons (i.e. Borislav doesn't recall),
32-bit kernels invoke cpu_init() on secondary CPUs with
initial_page_table loaded into CR3. Then they set
current->active_mm to &init_mm and call enter_lazy_tlb() before
fixing CR3. This means that the x86 TLB code gets invoked while CR3
is inconsistent, and, with the improved PCID sanity checks I added,
we warn.
Fix it by loading swapper_pg_dir (i.e. init_mm.pgd) earlier.
Reported-by: Paul Menzel <pmenzel@molgen.mpg.de>
Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bpetkov@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 72c0098d92ce ("x86/mm: Reinitialize TLB state on hotplug and resume")
Link: http://lkml.kernel.org/r/30cdfea504682ba3b9012e77717800a91c22097f.1505663533.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/smpboot.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 0854ff169274..ad59edd84de7 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -232,12 +232,6 @@ static void notrace start_secondary(void *unused) | |||
232 | */ | 232 | */ |
233 | if (boot_cpu_has(X86_FEATURE_PCID)) | 233 | if (boot_cpu_has(X86_FEATURE_PCID)) |
234 | __write_cr4(__read_cr4() | X86_CR4_PCIDE); | 234 | __write_cr4(__read_cr4() | X86_CR4_PCIDE); |
235 | cpu_init(); | ||
236 | x86_cpuinit.early_percpu_clock_init(); | ||
237 | preempt_disable(); | ||
238 | smp_callin(); | ||
239 | |||
240 | enable_start_cpu0 = 0; | ||
241 | 235 | ||
242 | #ifdef CONFIG_X86_32 | 236 | #ifdef CONFIG_X86_32 |
243 | /* switch away from the initial page table */ | 237 | /* switch away from the initial page table */ |
@@ -245,6 +239,13 @@ static void notrace start_secondary(void *unused) | |||
245 | __flush_tlb_all(); | 239 | __flush_tlb_all(); |
246 | #endif | 240 | #endif |
247 | 241 | ||
242 | cpu_init(); | ||
243 | x86_cpuinit.early_percpu_clock_init(); | ||
244 | preempt_disable(); | ||
245 | smp_callin(); | ||
246 | |||
247 | enable_start_cpu0 = 0; | ||
248 | |||
248 | /* otherwise gcc will move up smp_processor_id before the cpu_init */ | 249 | /* otherwise gcc will move up smp_processor_id before the cpu_init */ |
249 | barrier(); | 250 | barrier(); |
250 | /* | 251 | /* |