x86/mm/pat: Untangle pat_init()
authorBorislav Petkov <bp@suse.de>
Thu, 4 Jun 2015 16:55:09 +0000 (18:55 +0200)
committerIngo Molnar <mingo@kernel.org>
Sun, 7 Jun 2015 13:28:52 +0000 (15:28 +0200)
Split it into a BSP and AP version which makes the PAT
initialization path actually readable again.

Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Elliott@hp.com
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: arnd@arndb.de
Cc: hch@lst.de
Cc: hmh@hmh.eng.br
Cc: jgross@suse.com
Cc: konrad.wilk@oracle.com
Cc: linux-mm <linux-mm@kvack.org>
Cc: linux-nvdimm@lists.01.org
Cc: stefan.bader@canonical.com
Cc: yigal@plexistor.com
Link: http://lkml.kernel.org/r/1433436928-31903-2-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/mm/pat.c

index a1c9654..476d078 100644 (file)
@@ -36,6 +36,8 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "" fmt
 
+static bool boot_cpu_done;
+
 static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
 
 static inline void pat_disable(const char *reason)
@@ -194,31 +196,47 @@ void pat_init_cache_modes(void)
 
 #define PAT(x, y)      ((u64)PAT_ ## y << ((x)*8))
 
-void pat_init(void)
+static void pat_bsp_init(u64 pat)
 {
-       u64 pat;
-       bool boot_cpu = !boot_pat_state;
+       if (!cpu_has_pat) {
+               pat_disable("PAT not supported by CPU.");
+               return;
+       }
 
-       if (!pat_enabled())
+       rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
+       if (!boot_pat_state) {
+               pat_disable("PAT MSR is 0, disabled.");
                return;
+       }
 
+       wrmsrl(MSR_IA32_CR_PAT, pat);
+
+       pat_init_cache_modes();
+}
+
+static void pat_ap_init(u64 pat)
+{
        if (!cpu_has_pat) {
-               if (!boot_pat_state) {
-                       pat_disable("PAT not supported by CPU.");
-                       return;
-               } else {
-                       /*
-                        * If this happens we are on a secondary CPU, but
-                        * switched to PAT on the boot CPU. We have no way to
-                        * undo PAT.
-                        */
-                       pr_err("x86/PAT: PAT enabled, but not supported by secondary CPU\n");
-                       BUG();
-               }
+               /*
+                * If this happens we are on a secondary CPU, but switched to
+                * PAT on the boot CPU. We have no way to undo PAT.
+                */
+               panic("x86/PAT: PAT enabled, but not supported by secondary CPU\n");
        }
 
-       /* Set PWT to Write-Combining. All other bits stay the same */
+       wrmsrl(MSR_IA32_CR_PAT, pat);
+}
+
+void pat_init(void)
+{
+       u64 pat;
+
+       if (!pat_enabled())
+               return;
+
        /*
+        * Set PWT to Write-Combining. All other bits stay the same:
+        *
         * PTE encoding used in Linux:
         *      PAT
         *      |PCD
@@ -233,19 +251,12 @@ void pat_init(void)
        pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
              PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
 
-       /* Boot CPU check */
-       if (!boot_pat_state) {
-               rdmsrl(MSR_IA32_CR_PAT, boot_pat_state);
-               if (!boot_pat_state) {
-                       pat_disable("PAT read returns always zero, disabled.");
-                       return;
-               }
+       if (!boot_cpu_done) {
+               pat_bsp_init(pat);
+               boot_cpu_done = true;
+       } else {
+               pat_ap_init(pat);
        }
-
-       wrmsrl(MSR_IA32_CR_PAT, pat);
-
-       if (boot_cpu)
-               pat_init_cache_modes();
 }
 
 #undef PAT