x86, cpu: Add forcepae parameter for booting PAE kernels on PAE-disabled Pentium M
authorChris Bainbridge <chris.bainbridge@gmail.com>
Fri, 7 Mar 2014 11:40:42 +0000 (18:40 +0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 20 Mar 2014 23:31:54 +0000 (16:31 -0700)
Many Pentium M systems disable PAE but may have a functionally usable PAE
implementation. This adds the "forcepae" parameter which bypasses the boot
check for PAE, and sets the CPU as being PAE capable. Using this parameter
will taint the kernel with TAINT_CPU_OUT_OF_SPEC.

Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com>
Link: http://lkml.kernel.org/r/20140307114040.GA4997@localhost
Acked-by: Borislav Petkov <bp@suse.de>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Documentation/kernel-parameters.txt
arch/x86/boot/cpucheck.c
arch/x86/kernel/cpu/intel.c

index 7116fda7077ffce993b0d2456869934ab8c3ee09..06600cc9a26ccbb2023c758ea7f6a4ed756e69e3 100644 (file)
@@ -1011,6 +1011,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        parameter will force ia64_sal_cache_flush to call
                        ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
 
+       forcepae [X86-32]
+                       Forcefully enable Physical Address Extension (PAE).
+                       Many Pentium M systems disable PAE but may have a
+                       functionally usable PAE implementation.
+                       Warning: use of this parameter will taint the kernel
+                       and may cause unknown problems.
+
        ftrace=[tracer]
                        [FTRACE] will set and start the specified tracer
                        as early as possible in order to facilitate early
index 100a9a10076a649e7e7008a3579867391ca16fa4..f0d0b20fe14982529a10d4cec1e8aff6ebf4d96d 100644 (file)
@@ -67,6 +67,13 @@ static int is_transmeta(void)
               cpu_vendor[2] == A32('M', 'x', '8', '6');
 }
 
+static int is_intel(void)
+{
+       return cpu_vendor[0] == A32('G', 'e', 'n', 'u') &&
+              cpu_vendor[1] == A32('i', 'n', 'e', 'I') &&
+              cpu_vendor[2] == A32('n', 't', 'e', 'l');
+}
+
 /* Returns a bitmask of which words we have error bits in */
 static int check_cpuflags(void)
 {
@@ -153,6 +160,19 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
                asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
 
                err = check_cpuflags();
+       } else if (err == 0x01 &&
+                  !(err_flags[0] & ~(1 << X86_FEATURE_PAE)) &&
+                  is_intel() && cpu.level == 6 &&
+                  (cpu.model == 9 || cpu.model == 13)) {
+               /* PAE is disabled on this Pentium M but can be forced */
+               if (cmdline_find_option_bool("forcepae")) {
+                       puts("WARNING: Forcing PAE in CPU flags\n");
+                       set_bit(X86_FEATURE_PAE, cpu.flags);
+                       err = check_cpuflags();
+               }
+               else {
+                       puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n");
+               }
        }
 
        if (err_flags_ptr)
index 34bbb555e2694c70133fed9955cecc78ffbb60ca..897d6201ef10b25ca98b3ea66ab4ff1706d5c81d 100644 (file)
@@ -186,6 +186,14 @@ static void intel_smp_check(struct cpuinfo_x86 *c)
        }
 }
 
+static int forcepae;
+static int __init forcepae_setup(char *__unused)
+{
+       forcepae = 1;
+       return 1;
+}
+__setup("forcepae", forcepae_setup);
+
 static void intel_workarounds(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_X86_F00F_BUG
@@ -213,6 +221,17 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
        if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
                clear_cpu_cap(c, X86_FEATURE_SEP);
 
+       /*
+        * PAE CPUID issue: many Pentium M report no PAE but may have a
+        * functionally usable PAE implementation.
+        * Forcefully enable PAE if kernel parameter "forcepae" is present.
+        */
+       if (forcepae) {
+               printk(KERN_WARNING "PAE forced!\n");
+               set_cpu_cap(c, X86_FEATURE_PAE);
+               add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
+       }
+
        /*
         * P4 Xeon errata 037 workaround.
         * Hardware prefetcher may cause stale data to be loaded into the cache.