diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1905ce9..a4a3ef2 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -164,6 +164,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) { u64 misc_enable; + bool allow_fast_string = true; /* Unmask CPUID levels if masked: */ if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { @@ -259,17 +260,35 @@ * * Enable PAT WC only on P4, Core 2 or later CPUs. */ - if (c->x86 == 6 && c->x86_model < 15) + if (c->x86 == 6 && c->x86_model < 15) { + allow_fast_string = false; clear_cpu_cap(c, X86_FEATURE_PAT); - + } /* - * If fast string is not enabled in IA32_MISC_ENABLE for any reason, - * clear the fast string and enhanced fast string CPU capabilities. + * If BIOS didn't enable fast string operation, try to enable + * it ourselves. If that fails, then clear the fast string + * and enhanced fast string CPU capabilities. */ if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + + if (allow_fast_string && + !(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) { + misc_enable |= MSR_IA32_MISC_ENABLE_FAST_STRING; + wrmsrl_safe(MSR_IA32_MISC_ENABLE, misc_enable); + + /* Re-read to make sure it stuck. */ + rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); + + if (misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING) + printk_once(KERN_INFO "BIOS disabled fast string operation, re-enabled sucessfully.\n"); + } + if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) { - pr_info("Disabled fast string operations\n"); + if (allow_fast_string) + printk_once(KERN_INFO FW_WARN "BIOS disabled fast string operation, re-enable failed.\n"); + else + printk_once(KERN_INFO "Disabled fast string operations\n"); setup_clear_cpu_cap(X86_FEATURE_REP_GOOD); setup_clear_cpu_cap(X86_FEATURE_ERMS); }