diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 92e83e5..cbccc06 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1657,6 +1657,8 @@ and is between 256 and 4096 characters. It is defined in the file register save and restore. The kernel will only save legacy floating-point registers on task switch. + noselfsnoop [BUGS=X86] Disables x86 Self-Snoop feature. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 220e2ea..65c6508 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -269,6 +269,7 @@ extern const char * const x86_power_flags[32]; #define cpu_has_ds boot_cpu_has(X86_FEATURE_DS) #define cpu_has_pebs boot_cpu_has(X86_FEATURE_PEBS) #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) +#define cpu_has_selfsnoop boot_cpu_has(X86_FEATURE_SELFSNOOP) #define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS) #define cpu_has_gbpages boot_cpu_has(X86_FEATURE_GBPAGES) #define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index d16c2c5..fa8f557 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -108,6 +108,20 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) if (c->x86 == 6 && c->x86_model < 15) clear_cpu_cap(c, X86_FEATURE_PAT); + /* + * Pentium-M erratum Y9: + * + * Write cycles of WC memory type do not self-snoop. This may result + * in data inconsistency – if the addresses of the WC data are + * aliased to WB memory type memory, which has been cached. + * In such a case, the internal caches will not be updated with + * the WC data sent on the system bus. + * + * Enable Self-Snoop only on Core 2 or later CPUs. + */ + if (c->x86 == 15 || (c->x86 == 6 && c->x86_model < 15)) + clear_cpu_cap(c, X86_FEATURE_SELFSNOOP); + #ifdef CONFIG_KMEMCHECK /* * P4s have a "fast strings" feature which causes single- diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 532e793..427594e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -51,6 +51,13 @@ static DEFINE_SPINLOCK(cpa_lock); #define CPA_ARRAY 2 #define CPA_PAGES_ARRAY 4 +static int __init x86_selfsnoop_setup(char *s) +{ + setup_clear_cpu_cap(X86_FEATURE_SELFSNOOP); + return 1; +} +__setup("noselfsnoop", x86_selfsnoop_setup); + #ifdef CONFIG_PROC_FS static unsigned long direct_pages_count[PG_LEVEL_NUM]; @@ -911,10 +918,10 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, goto out; /* - * No need to flush, when we did not set any of the caching - * attributes: + * No need to flush when CPU supports self snoop or + * when we did not set any of the caching attributes: */ - cache = cache_attr(mask_set); + cache = cpu_has_selfsnoop ? 0 : cache_attr(mask_set); /* * On success we use clflush, when the CPU supports it to