Merge branch 'linus' into core/objtool, to pick up dependent commits
[sfrench/cifs-2.6.git] / arch / x86 / mm / init.c
index 7777ccc0e9f979dc76cc9d520885eea02114223e..a22c2b95e5133919e839d3c7a7a33b82b17e629c 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/microcode.h>
 #include <asm/kaslr.h>
 #include <asm/hypervisor.h>
+#include <asm/cpufeature.h>
 
 /*
  * We need to define the tracepoints somewhere, and tlb.c
@@ -193,6 +194,38 @@ static void __init probe_page_size_mask(void)
        }
 }
 
+static void setup_pcid(void)
+{
+#ifdef CONFIG_X86_64
+       if (boot_cpu_has(X86_FEATURE_PCID)) {
+               if (boot_cpu_has(X86_FEATURE_PGE)) {
+                       /*
+                        * This can't be cr4_set_bits_and_update_boot() --
+                        * the trampoline code can't handle CR4.PCIDE and
+                        * it wouldn't do any good anyway.  Despite the name,
+                        * cr4_set_bits_and_update_boot() doesn't actually
+                        * cause the bits in question to remain set all the
+                        * way through the secondary boot asm.
+                        *
+                        * Instead, we brute-force it and set CR4.PCIDE
+                        * manually in start_secondary().
+                        */
+                       cr4_set_bits(X86_CR4_PCIDE);
+               } else {
+                       /*
+                        * flush_tlb_all(), as currently implemented, won't
+                        * work if PCID is on but PGE is not.  Since that
+                        * combination doesn't exist on real hardware, there's
+                        * no reason to try to fully support it, but it's
+                        * polite to avoid corrupting data if we're on
+                        * an improperly configured VM.
+                        */
+                       setup_clear_cpu_cap(X86_FEATURE_PCID);
+               }
+       }
+#endif
+}
+
 #ifdef CONFIG_X86_32
 #define NR_RANGE_MR 3
 #else /* CONFIG_X86_64 */
@@ -592,6 +625,7 @@ void __init init_mem_mapping(void)
        unsigned long end;
 
        probe_page_size_mask();
+       setup_pcid();
 
 #ifdef CONFIG_X86_64
        end = max_pfn << PAGE_SHIFT;
@@ -637,7 +671,7 @@ void __init init_mem_mapping(void)
        load_cr3(swapper_pg_dir);
        __flush_tlb_all();
 
-       hypervisor_init_mem_mapping();
+       x86_init.hyper.init_mem_mapping();
 
        early_memtest(0, max_pfn_mapped << PAGE_SHIFT);
 }