Commit 18bc7bd523e0fc5be8d76bf84bde733a97a8c375
Committed by
Ingo Molnar
1 parent
007b756053
x86/boot: Synchronize trampoline_cr4_features and mmu_cr4_features directly
The initialization process for trampoline_cr4_features and mmu_cr4_features was confusing. The intent is for mmu_cr4_features and *trampoline_cr4_features to stay in sync, but trampoline_cr4_features is NULL until setup_real_mode() runs. The old code synchronized *trampoline_cr4_features *twice*, once in setup_real_mode() and once in setup_arch(). It also initialized mmu_cr4_features in setup_real_mode(), which causes the actual value of mmu_cr4_features to potentially depend on when setup_real_mode() is called. With this patch, mmu_cr4_features is initialized directly in setup_arch(), and *trampoline_cr4_features is synchronized to mmu_cr4_features when the trampoline is set up. After this patch, it should be safe to defer setup_real_mode(). Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mario Limonciello <mario_limonciello@dell.com> Cc: Matt Fleming <mfleming@suse.de> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/d48a263f9912389b957dd495a7127b009259ffe0.1470821230.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Showing 2 changed files with 12 additions and 8 deletions Side-by-side Diff
arch/x86/kernel/setup.c
... | ... | @@ -1131,6 +1131,16 @@ |
1131 | 1131 | |
1132 | 1132 | early_trap_pf_init(); |
1133 | 1133 | |
1134 | + /* | |
1135 | + * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features) | |
1136 | + * with the current CR4 value. This may not be necessary, but | |
1137 | + * auditing all the early-boot CR4 manipulation would be needed to | |
1138 | + * rule it out. | |
1139 | + */ | |
1140 | + if (boot_cpu_data.cpuid_level >= 0) | |
1141 | + /* A CPU has %cr4 if and only if it has CPUID. */ | |
1142 | + mmu_cr4_features = __read_cr4(); | |
1143 | + | |
1134 | 1144 | setup_real_mode(); |
1135 | 1145 | |
1136 | 1146 | memblock_set_current_limit(get_max_mapped()); |
... | ... | @@ -1179,13 +1189,6 @@ |
1179 | 1189 | x86_init.paging.pagetable_init(); |
1180 | 1190 | |
1181 | 1191 | kasan_init(); |
1182 | - | |
1183 | - if (boot_cpu_data.cpuid_level >= 0) { | |
1184 | - /* A CPU has %cr4 if and only if it has CPUID */ | |
1185 | - mmu_cr4_features = __read_cr4(); | |
1186 | - if (trampoline_cr4_features) | |
1187 | - *trampoline_cr4_features = mmu_cr4_features; | |
1188 | - } | |
1189 | 1192 | |
1190 | 1193 | #ifdef CONFIG_X86_32 |
1191 | 1194 | /* sync back kernel address range */ |
arch/x86/realmode/init.c
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | #include <asm/cacheflush.h> |
5 | 5 | #include <asm/pgtable.h> |
6 | 6 | #include <asm/realmode.h> |
7 | +#include <asm/tlbflush.h> | |
7 | 8 | |
8 | 9 | struct real_mode_header *real_mode_header; |
9 | 10 | u32 *trampoline_cr4_features; |
... | ... | @@ -84,7 +85,7 @@ |
84 | 85 | |
85 | 86 | trampoline_header->start = (u64) secondary_startup_64; |
86 | 87 | trampoline_cr4_features = &trampoline_header->cr4; |
87 | - *trampoline_cr4_features = __read_cr4(); | |
88 | + *trampoline_cr4_features = mmu_cr4_features; | |
88 | 89 | |
89 | 90 | trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); |
90 | 91 | trampoline_pgd[0] = trampoline_pgd_entry.pgd; |