aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToshi Kani <toshi.kani@hpe.com>2016-03-23 17:41:57 -0400
committerIngo Molnar <mingo@kernel.org>2016-03-29 06:23:25 -0400
commit02f037d641dc6672be5cfe7875a48ab99b95b154 (patch)
tree606902997743c91bbb0886d3306ba7cc79f39d05
parent1993b176a8224e371e0732ffada7ab9eb3b0912b (diff)
x86/mm/pat: Add support of non-default PAT MSR setting
In preparation for fixing a regression caused by: 9cd25aac1f44 ("x86/mm/pat: Emulate PAT when it is disabled")' ... PAT needs to support a case that PAT MSR is initialized with a non-default value. When pat_init() is called and PAT is disabled, it initializes the PAT table with the BIOS default value. Xen, however, sets PAT MSR with a non-default value to enable WC. This causes inconsistency between the PAT table and PAT MSR when PAT is set to disable on Xen. Change pat_init() to handle the PAT disable cases properly. Add init_cache_modes() to handle two cases when PAT is set to disable. 1. CPU supports PAT: Set PAT table to be consistent with PAT MSR. 2. CPU does not support PAT: Set PAT table to be consistent with PWT and PCD bits in a PTE. Note, __init_cache_modes(), renamed from pat_init_cache_modes(), will be changed to a static function in a later patch. Signed-off-by: Toshi Kani <toshi.kani@hpe.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Juergen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Luis R. Rodriguez <mcgrof@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Toshi Kani <toshi.kani@hp.com> Cc: elliott@hpe.com Cc: konrad.wilk@oracle.com Cc: paul.gortmaker@windriver.com Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1458769323-24491-2-git-send-email-toshi.kani@hpe.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/pat.h2
-rw-r--r--arch/x86/mm/pat.c73
-rw-r--r--arch/x86/xen/enlighten.c2
3 files changed, 55 insertions, 22 deletions
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index ca6c228d5e62..97ea55bc2b54 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -6,7 +6,7 @@
6 6
7bool pat_enabled(void); 7bool pat_enabled(void);
8extern void pat_init(void); 8extern void pat_init(void);
9void pat_init_cache_modes(u64); 9void __init_cache_modes(u64);
10 10
11extern int reserve_memtype(u64 start, u64 end, 11extern int reserve_memtype(u64 start, u64 end,
12 enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm); 12 enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index faec01e7a17d..b4663885308f 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -181,7 +181,7 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
181 * configuration. 181 * configuration.
182 * Using lower indices is preferred, so we start with highest index. 182 * Using lower indices is preferred, so we start with highest index.
183 */ 183 */
184void pat_init_cache_modes(u64 pat) 184void __init_cache_modes(u64 pat)
185{ 185{
186 enum page_cache_mode cache; 186 enum page_cache_mode cache;
187 char pat_msg[33]; 187 char pat_msg[33];
@@ -207,9 +207,6 @@ static void pat_bsp_init(u64 pat)
207 return; 207 return;
208 } 208 }
209 209
210 if (!pat_enabled())
211 goto done;
212
213 rdmsrl(MSR_IA32_CR_PAT, tmp_pat); 210 rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
214 if (!tmp_pat) { 211 if (!tmp_pat) {
215 pat_disable("PAT MSR is 0, disabled."); 212 pat_disable("PAT MSR is 0, disabled.");
@@ -218,15 +215,11 @@ static void pat_bsp_init(u64 pat)
218 215
219 wrmsrl(MSR_IA32_CR_PAT, pat); 216 wrmsrl(MSR_IA32_CR_PAT, pat);
220 217
221done: 218 __init_cache_modes(pat);
222 pat_init_cache_modes(pat);
223} 219}
224 220
225static void pat_ap_init(u64 pat) 221static void pat_ap_init(u64 pat)
226{ 222{
227 if (!pat_enabled())
228 return;
229
230 if (!cpu_has_pat) { 223 if (!cpu_has_pat) {
231 /* 224 /*
232 * If this happens we are on a secondary CPU, but switched to 225 * If this happens we are on a secondary CPU, but switched to
@@ -238,18 +231,32 @@ static void pat_ap_init(u64 pat)
238 wrmsrl(MSR_IA32_CR_PAT, pat); 231 wrmsrl(MSR_IA32_CR_PAT, pat);
239} 232}
240 233
241void pat_init(void) 234static void init_cache_modes(void)
242{ 235{
243 u64 pat; 236 u64 pat = 0;
244 struct cpuinfo_x86 *c = &boot_cpu_data; 237 static int init_cm_done;
245 238
246 if (!pat_enabled()) { 239 if (init_cm_done)
240 return;
241
242 if (boot_cpu_has(X86_FEATURE_PAT)) {
243 /*
244 * CPU supports PAT. Set PAT table to be consistent with
245 * PAT MSR. This case supports "nopat" boot option, and
246 * virtual machine environments which support PAT without
247 * MTRRs. In specific, Xen has unique setup to PAT MSR.
248 *
249 * If PAT MSR returns 0, it is considered invalid and emulates
250 * as No PAT.
251 */
252 rdmsrl(MSR_IA32_CR_PAT, pat);
253 }
254
255 if (!pat) {
247 /* 256 /*
248 * No PAT. Emulate the PAT table that corresponds to the two 257 * No PAT. Emulate the PAT table that corresponds to the two
249 * cache bits, PWT (Write Through) and PCD (Cache Disable). This 258 * cache bits, PWT (Write Through) and PCD (Cache Disable).
250 * setup is the same as the BIOS default setup when the system 259 * This setup is also the same as the BIOS default setup.
251 * has PAT but the "nopat" boot option has been specified. This
252 * emulated PAT table is used when MSR_IA32_CR_PAT returns 0.
253 * 260 *
254 * PTE encoding: 261 * PTE encoding:
255 * 262 *
@@ -266,10 +273,36 @@ void pat_init(void)
266 */ 273 */
267 pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) | 274 pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
268 PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC); 275 PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
276 }
277
278 __init_cache_modes(pat);
279
280 init_cm_done = 1;
281}
282
283/**
284 * pat_init - Initialize PAT MSR and PAT table
285 *
286 * This function initializes PAT MSR and PAT table with an OS-defined value
287 * to enable additional cache attributes, WC and WT.
288 *
289 * This function must be called on all CPUs using the specific sequence of
290 * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
291 * procedure for PAT.
292 */
293void pat_init(void)
294{
295 u64 pat;
296 struct cpuinfo_x86 *c = &boot_cpu_data;
297
298 if (!pat_enabled()) {
299 init_cache_modes();
300 return;
301 }
269 302
270 } else if ((c->x86_vendor == X86_VENDOR_INTEL) && 303 if ((c->x86_vendor == X86_VENDOR_INTEL) &&
271 (((c->x86 == 0x6) && (c->x86_model <= 0xd)) || 304 (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
272 ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) { 305 ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
273 /* 306 /*
274 * PAT support with the lower four entries. Intel Pentium 2, 307 * PAT support with the lower four entries. Intel Pentium 2,
275 * 3, M, and 4 are affected by PAT errata, which makes the 308 * 3, M, and 4 are affected by PAT errata, which makes the
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 880862c7d9dd..c469a7c7c309 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1623,7 +1623,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
1623 * configuration. 1623 * configuration.
1624 */ 1624 */
1625 rdmsrl(MSR_IA32_CR_PAT, pat); 1625 rdmsrl(MSR_IA32_CR_PAT, pat);
1626 pat_init_cache_modes(pat); 1626 __init_cache_modes(pat);
1627 1627
1628 /* keep using Xen gdt for now; no urgent need to change it */ 1628 /* keep using Xen gdt for now; no urgent need to change it */
1629 1629