x86: handle PAT more like other CPU features
Impact: Cleanup When PAT was originally introduced, it was handled specially for a few reasons: - PAT bugs are hard to track down, so we wanted to maintain a whitelist of CPUs. - The i386 and x86-64 CPUID code was not yet unified. Both of these are now obsolete, so handle PAT like any other features, including ordinary feature blacklisting due to known bugs. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
@@ -5,10 +5,8 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_X86_PAT
|
#ifdef CONFIG_X86_PAT
|
||||||
extern int pat_enabled;
|
extern int pat_enabled;
|
||||||
extern void validate_pat_support(struct cpuinfo_x86 *c);
|
|
||||||
#else
|
#else
|
||||||
static const int pat_enabled;
|
static const int pat_enabled;
|
||||||
static inline void validate_pat_support(struct cpuinfo_x86 *c) { }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void pat_init(void);
|
extern void pat_init(void);
|
||||||
@@ -17,6 +15,4 @@ extern int reserve_memtype(u64 start, u64 end,
|
|||||||
unsigned long req_type, unsigned long *ret_type);
|
unsigned long req_type, unsigned long *ret_type);
|
||||||
extern int free_memtype(u64 start, u64 end);
|
extern int free_memtype(u64 start, u64 end);
|
||||||
|
|
||||||
extern void pat_disable(char *reason);
|
|
||||||
|
|
||||||
#endif /* _ASM_X86_PAT_H */
|
#endif /* _ASM_X86_PAT_H */
|
||||||
|
@@ -143,37 +143,3 @@ void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_PAT
|
|
||||||
void __cpuinit validate_pat_support(struct cpuinfo_x86 *c)
|
|
||||||
{
|
|
||||||
if (!cpu_has_pat)
|
|
||||||
pat_disable("PAT not supported by CPU.");
|
|
||||||
|
|
||||||
switch (c->x86_vendor) {
|
|
||||||
case X86_VENDOR_INTEL:
|
|
||||||
/*
|
|
||||||
* There is a known erratum on Pentium III and Core Solo
|
|
||||||
* and Core Duo CPUs.
|
|
||||||
* " Page with PAT set to WC while associated MTRR is UC
|
|
||||||
* may consolidate to UC "
|
|
||||||
* Because of this erratum, it is better to stick with
|
|
||||||
* setting WC in MTRR rather than using PAT on these CPUs.
|
|
||||||
*
|
|
||||||
* Enable PAT WC only on P4, Core 2 or later CPUs.
|
|
||||||
*/
|
|
||||||
if (c->x86 > 0x6 || (c->x86 == 6 && c->x86_model >= 15))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pat_disable("PAT WC disabled due to known CPU erratum.");
|
|
||||||
return;
|
|
||||||
|
|
||||||
case X86_VENDOR_AMD:
|
|
||||||
case X86_VENDOR_CENTAUR:
|
|
||||||
case X86_VENDOR_TRANSMETA:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pat_disable("PAT disabled. Not yet verified on this CPU type.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@@ -570,8 +570,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
|
|||||||
if (this_cpu->c_early_init)
|
if (this_cpu->c_early_init)
|
||||||
this_cpu->c_early_init(c);
|
this_cpu->c_early_init(c);
|
||||||
|
|
||||||
validate_pat_support(c);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
c->cpu_index = boot_cpu_id;
|
c->cpu_index = boot_cpu_id;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -50,6 +50,18 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
|
|||||||
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
|
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is a known erratum on Pentium III and Core Solo
|
||||||
|
* and Core Duo CPUs.
|
||||||
|
* " Page with PAT set to WC while associated MTRR is UC
|
||||||
|
* may consolidate to UC "
|
||||||
|
* Because of this erratum, it is better to stick with
|
||||||
|
* setting WC in MTRR rather than using PAT on these CPUs.
|
||||||
|
*
|
||||||
|
* Enable PAT WC only on P4, Core 2 or later CPUs.
|
||||||
|
*/
|
||||||
|
if (c->x86 == 6 && c->x86_model < 15)
|
||||||
|
clear_cpu_cap(c, X86_FEATURE_PAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
#ifdef CONFIG_X86_PAT
|
#ifdef CONFIG_X86_PAT
|
||||||
int __read_mostly pat_enabled = 1;
|
int __read_mostly pat_enabled = 1;
|
||||||
|
|
||||||
void __cpuinit pat_disable(char *reason)
|
void __cpuinit pat_disable(const char *reason)
|
||||||
{
|
{
|
||||||
pat_enabled = 0;
|
pat_enabled = 0;
|
||||||
printk(KERN_INFO "%s\n", reason);
|
printk(KERN_INFO "%s\n", reason);
|
||||||
@@ -42,6 +42,11 @@ static int __init nopat(char *str)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("nopat", nopat);
|
early_param("nopat", nopat);
|
||||||
|
#else
|
||||||
|
static inline void pat_disable(const char *reason)
|
||||||
|
{
|
||||||
|
(void)reason;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -78,8 +83,11 @@ void pat_init(void)
|
|||||||
if (!pat_enabled)
|
if (!pat_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Paranoia check. */
|
if (!cpu_has_pat) {
|
||||||
if (!cpu_has_pat && boot_pat_state) {
|
if (!boot_pat_state) {
|
||||||
|
pat_disable("PAT not supported by CPU.");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
/*
|
/*
|
||||||
* If this happens we are on a secondary CPU, but
|
* If this happens we are on a secondary CPU, but
|
||||||
* switched to PAT on the boot CPU. We have no way to
|
* switched to PAT on the boot CPU. We have no way to
|
||||||
@@ -89,6 +97,7 @@ void pat_init(void)
|
|||||||
"but not supported by secondary CPU\n");
|
"but not supported by secondary CPU\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Set PWT to Write-Combining. All other bits stay the same */
|
/* Set PWT to Write-Combining. All other bits stay the same */
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user