aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-04-13 05:36:19 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-13 05:36:19 -0400
commitd8d1c35139481ee8e292d91cd3fd35a6b3a316eb (patch)
tree0a06b6c185e91bf14b22e7f526755e2ca80209bf
parentcb44d0cfc2969999a4d9e20e4fd8749fec6c5498 (diff)
parent1886297ce0c8d563a08c8a8c4c0b97743e06cd37 (diff)
Merge branch 'x86/mm' into x86/asm to resolve conflict and to create common base
Conflicts: arch/x86/include/asm/cpufeature.h Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/x86/pat.txt32
-rw-r--r--arch/x86/include/asm/cpufeature.h1
-rw-r--r--arch/x86/include/asm/mtrr.h6
-rw-r--r--arch/x86/include/asm/pat.h2
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c24
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c13
-rw-r--r--arch/x86/kernel/cpu/mtrr/mtrr.h1
-rw-r--r--arch/x86/mm/pat.c109
-rw-r--r--arch/x86/xen/enlighten.c9
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c2
10 files changed, 133 insertions, 66 deletions
diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt
index 54944c71b819..2a4ee6302122 100644
--- a/Documentation/x86/pat.txt
+++ b/Documentation/x86/pat.txt
@@ -196,3 +196,35 @@ Another, more verbose way of getting PAT related debug messages is with
196"debugpat" boot parameter. With this parameter, various debug messages are 196"debugpat" boot parameter. With this parameter, various debug messages are
197printed to dmesg log. 197printed to dmesg log.
198 198
199PAT Initialization
200------------------
201
202The following table describes how PAT is initialized under various
203configurations. The PAT MSR must be updated by Linux in order to support WC
204and WT attributes. Otherwise, the PAT MSR has the value programmed in it
205by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.
206
207 MTRR PAT Call Sequence PAT State PAT MSR
208 =========================================================
209 E E MTRR -> PAT init Enabled OS
210 E D MTRR -> PAT init Disabled -
211 D E MTRR -> PAT disable Disabled BIOS
212 D D MTRR -> PAT disable Disabled -
213 - np/E PAT -> PAT disable Disabled BIOS
214 - np/D PAT -> PAT disable Disabled -
215 E !P/E MTRR -> PAT init Disabled BIOS
216 D !P/E MTRR -> PAT disable Disabled BIOS
217 !M !P/E MTRR stub -> PAT disable Disabled BIOS
218
219 Legend
220 ------------------------------------------------
221 E Feature enabled in CPU
222 D Feature disabled/unsupported in CPU
223 np "nopat" boot option specified
224 !P CONFIG_X86_PAT option unset
225 !M CONFIG_MTRR option unset
226 Enabled PAT state set to enabled
227 Disabled PAT state set to disabled
228 OS PAT initializes PAT MSR with OS setting
229 BIOS PAT keeps PAT MSR with BIOS setting
230
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 97e5f13ea471..c594e04bf529 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -126,7 +126,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
126#define cpu_has_aes boot_cpu_has(X86_FEATURE_AES) 126#define cpu_has_aes boot_cpu_has(X86_FEATURE_AES)
127#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX) 127#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX)
128#define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2) 128#define cpu_has_avx2 boot_cpu_has(X86_FEATURE_AVX2)
129#define cpu_has_pat boot_cpu_has(X86_FEATURE_PAT)
130#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE) 129#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
131#define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES) 130#define cpu_has_xsaves boot_cpu_has(X86_FEATURE_XSAVES)
132/* 131/*
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index b94f6f64e23d..dbff1456d215 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -24,6 +24,7 @@
24#define _ASM_X86_MTRR_H 24#define _ASM_X86_MTRR_H
25 25
26#include <uapi/asm/mtrr.h> 26#include <uapi/asm/mtrr.h>
27#include <asm/pat.h>
27 28
28 29
29/* 30/*
@@ -83,9 +84,12 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
83static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) 84static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
84{ 85{
85} 86}
87static inline void mtrr_bp_init(void)
88{
89 pat_disable("MTRRs disabled, skipping PAT initialization too.");
90}
86 91
87#define mtrr_ap_init() do {} while (0) 92#define mtrr_ap_init() do {} while (0)
88#define mtrr_bp_init() do {} while (0)
89#define set_mtrr_aps_delayed_init() do {} while (0) 93#define set_mtrr_aps_delayed_init() do {} while (0)
90#define mtrr_aps_init() do {} while (0) 94#define mtrr_aps_init() do {} while (0)
91#define mtrr_bp_restore() do {} while (0) 95#define mtrr_bp_restore() do {} while (0)
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index ca6c228d5e62..0b1ff4c1c14e 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -5,8 +5,8 @@
5#include <asm/pgtable_types.h> 5#include <asm/pgtable_types.h>
6 6
7bool pat_enabled(void); 7bool pat_enabled(void);
8void pat_disable(const char *reason);
8extern void pat_init(void); 9extern void pat_init(void);
9void pat_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/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index f1bed301bdb2..16e37a2581ac 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -444,11 +444,24 @@ static void __init print_mtrr_state(void)
444 pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20); 444 pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
445} 445}
446 446
447/* PAT setup for BP. We need to go through sync steps here */
448void __init mtrr_bp_pat_init(void)
449{
450 unsigned long flags;
451
452 local_irq_save(flags);
453 prepare_set();
454
455 pat_init();
456
457 post_set();
458 local_irq_restore(flags);
459}
460
447/* Grab all of the MTRR state for this CPU into *state */ 461/* Grab all of the MTRR state for this CPU into *state */
448bool __init get_mtrr_state(void) 462bool __init get_mtrr_state(void)
449{ 463{
450 struct mtrr_var_range *vrs; 464 struct mtrr_var_range *vrs;
451 unsigned long flags;
452 unsigned lo, dummy; 465 unsigned lo, dummy;
453 unsigned int i; 466 unsigned int i;
454 467
@@ -481,15 +494,6 @@ bool __init get_mtrr_state(void)
481 494
482 mtrr_state_set = 1; 495 mtrr_state_set = 1;
483 496
484 /* PAT setup for BP. We need to go through sync steps here */
485 local_irq_save(flags);
486 prepare_set();
487
488 pat_init();
489
490 post_set();
491 local_irq_restore(flags);
492
493 return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED); 497 return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
494} 498}
495 499
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 10f8d4796240..7d393ecdeee6 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -752,6 +752,9 @@ void __init mtrr_bp_init(void)
752 /* BIOS may override */ 752 /* BIOS may override */
753 __mtrr_enabled = get_mtrr_state(); 753 __mtrr_enabled = get_mtrr_state();
754 754
755 if (mtrr_enabled())
756 mtrr_bp_pat_init();
757
755 if (mtrr_cleanup(phys_addr)) { 758 if (mtrr_cleanup(phys_addr)) {
756 changed_by_mtrr_cleanup = 1; 759 changed_by_mtrr_cleanup = 1;
757 mtrr_if->set_all(); 760 mtrr_if->set_all();
@@ -759,8 +762,16 @@ void __init mtrr_bp_init(void)
759 } 762 }
760 } 763 }
761 764
762 if (!mtrr_enabled()) 765 if (!mtrr_enabled()) {
763 pr_info("MTRR: Disabled\n"); 766 pr_info("MTRR: Disabled\n");
767
768 /*
769 * PAT initialization relies on MTRR's rendezvous handler.
770 * Skip PAT init until the handler can initialize both
771 * features independently.
772 */
773 pat_disable("MTRRs disabled, skipping PAT initialization too.");
774 }
764} 775}
765 776
766void mtrr_ap_init(void) 777void mtrr_ap_init(void)
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 951884dcc433..6c7ced07d16d 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
52void fill_mtrr_var_range(unsigned int index, 52void fill_mtrr_var_range(unsigned int index,
53 u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); 53 u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
54bool get_mtrr_state(void); 54bool get_mtrr_state(void);
55void mtrr_bp_pat_init(void);
55 56
56extern void set_mtrr_ops(const struct mtrr_ops *ops); 57extern void set_mtrr_ops(const struct mtrr_ops *ops);
57 58
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index faec01e7a17d..fb0604f11eec 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -40,11 +40,22 @@
40static bool boot_cpu_done; 40static bool boot_cpu_done;
41 41
42static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT); 42static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
43static void init_cache_modes(void);
43 44
44static inline void pat_disable(const char *reason) 45void pat_disable(const char *reason)
45{ 46{
47 if (!__pat_enabled)
48 return;
49
50 if (boot_cpu_done) {
51 WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n");
52 return;
53 }
54
46 __pat_enabled = 0; 55 __pat_enabled = 0;
47 pr_info("x86/PAT: %s\n", reason); 56 pr_info("x86/PAT: %s\n", reason);
57
58 init_cache_modes();
48} 59}
49 60
50static int __init nopat(char *str) 61static int __init nopat(char *str)
@@ -181,7 +192,7 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
181 * configuration. 192 * configuration.
182 * Using lower indices is preferred, so we start with highest index. 193 * Using lower indices is preferred, so we start with highest index.
183 */ 194 */
184void pat_init_cache_modes(u64 pat) 195static void __init_cache_modes(u64 pat)
185{ 196{
186 enum page_cache_mode cache; 197 enum page_cache_mode cache;
187 char pat_msg[33]; 198 char pat_msg[33];
@@ -202,14 +213,11 @@ static void pat_bsp_init(u64 pat)
202{ 213{
203 u64 tmp_pat; 214 u64 tmp_pat;
204 215
205 if (!cpu_has_pat) { 216 if (!boot_cpu_has(X86_FEATURE_PAT)) {
206 pat_disable("PAT not supported by CPU."); 217 pat_disable("PAT not supported by CPU.");
207 return; 218 return;
208 } 219 }
209 220
210 if (!pat_enabled())
211 goto done;
212
213 rdmsrl(MSR_IA32_CR_PAT, tmp_pat); 221 rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
214 if (!tmp_pat) { 222 if (!tmp_pat) {
215 pat_disable("PAT MSR is 0, disabled."); 223 pat_disable("PAT MSR is 0, disabled.");
@@ -218,16 +226,12 @@ static void pat_bsp_init(u64 pat)
218 226
219 wrmsrl(MSR_IA32_CR_PAT, pat); 227 wrmsrl(MSR_IA32_CR_PAT, pat);
220 228
221done: 229 __init_cache_modes(pat);
222 pat_init_cache_modes(pat);
223} 230}
224 231
225static void pat_ap_init(u64 pat) 232static void pat_ap_init(u64 pat)
226{ 233{
227 if (!pat_enabled()) 234 if (!boot_cpu_has(X86_FEATURE_PAT)) {
228 return;
229
230 if (!cpu_has_pat) {
231 /* 235 /*
232 * If this happens we are on a secondary CPU, but switched to 236 * If this happens we are on a secondary CPU, but switched to
233 * PAT on the boot CPU. We have no way to undo PAT. 237 * PAT on the boot CPU. We have no way to undo PAT.
@@ -238,18 +242,32 @@ static void pat_ap_init(u64 pat)
238 wrmsrl(MSR_IA32_CR_PAT, pat); 242 wrmsrl(MSR_IA32_CR_PAT, pat);
239} 243}
240 244
241void pat_init(void) 245static void init_cache_modes(void)
242{ 246{
243 u64 pat; 247 u64 pat = 0;
244 struct cpuinfo_x86 *c = &boot_cpu_data; 248 static int init_cm_done;
245 249
246 if (!pat_enabled()) { 250 if (init_cm_done)
251 return;
252
253 if (boot_cpu_has(X86_FEATURE_PAT)) {
254 /*
255 * CPU supports PAT. Set PAT table to be consistent with
256 * PAT MSR. This case supports "nopat" boot option, and
257 * virtual machine environments which support PAT without
258 * MTRRs. In specific, Xen has unique setup to PAT MSR.
259 *
260 * If PAT MSR returns 0, it is considered invalid and emulates
261 * as No PAT.
262 */
263 rdmsrl(MSR_IA32_CR_PAT, pat);
264 }
265
266 if (!pat) {
247 /* 267 /*
248 * No PAT. Emulate the PAT table that corresponds to the two 268 * No PAT. Emulate the PAT table that corresponds to the two
249 * cache bits, PWT (Write Through) and PCD (Cache Disable). This 269 * cache bits, PWT (Write Through) and PCD (Cache Disable).
250 * setup is the same as the BIOS default setup when the system 270 * 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 * 271 *
254 * PTE encoding: 272 * PTE encoding:
255 * 273 *
@@ -266,10 +284,36 @@ void pat_init(void)
266 */ 284 */
267 pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) | 285 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); 286 PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
287 }
288
289 __init_cache_modes(pat);
290
291 init_cm_done = 1;
292}
293
294/**
295 * pat_init - Initialize PAT MSR and PAT table
296 *
297 * This function initializes PAT MSR and PAT table with an OS-defined value
298 * to enable additional cache attributes, WC and WT.
299 *
300 * This function must be called on all CPUs using the specific sequence of
301 * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
302 * procedure for PAT.
303 */
304void pat_init(void)
305{
306 u64 pat;
307 struct cpuinfo_x86 *c = &boot_cpu_data;
308
309 if (!pat_enabled()) {
310 init_cache_modes();
311 return;
312 }
269 313
270 } else if ((c->x86_vendor == X86_VENDOR_INTEL) && 314 if ((c->x86_vendor == X86_VENDOR_INTEL) &&
271 (((c->x86 == 0x6) && (c->x86_model <= 0xd)) || 315 (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
272 ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) { 316 ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
273 /* 317 /*
274 * PAT support with the lower four entries. Intel Pentium 2, 318 * PAT support with the lower four entries. Intel Pentium 2,
275 * 3, M, and 4 are affected by PAT errata, which makes the 319 * 3, M, and 4 are affected by PAT errata, which makes the
@@ -734,25 +778,6 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
734 if (file->f_flags & O_DSYNC) 778 if (file->f_flags & O_DSYNC)
735 pcm = _PAGE_CACHE_MODE_UC_MINUS; 779 pcm = _PAGE_CACHE_MODE_UC_MINUS;
736 780
737#ifdef CONFIG_X86_32
738 /*
739 * On the PPro and successors, the MTRRs are used to set
740 * memory types for physical addresses outside main memory,
741 * so blindly setting UC or PWT on those pages is wrong.
742 * For Pentiums and earlier, the surround logic should disable
743 * caching for the high addresses through the KEN pin, but
744 * we maintain the tradition of paranoia in this code.
745 */
746 if (!pat_enabled() &&
747 !(boot_cpu_has(X86_FEATURE_MTRR) ||
748 boot_cpu_has(X86_FEATURE_K6_MTRR) ||
749 boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
750 boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
751 (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
752 pcm = _PAGE_CACHE_MODE_UC;
753 }
754#endif
755
756 *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) | 781 *vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
757 cachemode2protval(pcm)); 782 cachemode2protval(pcm));
758 return 1; 783 return 1;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index ff2a2e6ef7af..9b8f1eacc110 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -75,7 +75,6 @@
75#include <asm/mach_traps.h> 75#include <asm/mach_traps.h>
76#include <asm/mwait.h> 76#include <asm/mwait.h>
77#include <asm/pci_x86.h> 77#include <asm/pci_x86.h>
78#include <asm/pat.h>
79#include <asm/cpu.h> 78#include <asm/cpu.h>
80 79
81#ifdef CONFIG_ACPI 80#ifdef CONFIG_ACPI
@@ -1511,7 +1510,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
1511{ 1510{
1512 struct physdev_set_iopl set_iopl; 1511 struct physdev_set_iopl set_iopl;
1513 unsigned long initrd_start = 0; 1512 unsigned long initrd_start = 0;
1514 u64 pat;
1515 int rc; 1513 int rc;
1516 1514
1517 if (!xen_start_info) 1515 if (!xen_start_info)
@@ -1618,13 +1616,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
1618 xen_start_info->nr_pages); 1616 xen_start_info->nr_pages);
1619 xen_reserve_special_pages(); 1617 xen_reserve_special_pages();
1620 1618
1621 /*
1622 * Modify the cache mode translation tables to match Xen's PAT
1623 * configuration.
1624 */
1625 rdmsrl(MSR_IA32_CR_PAT, pat);
1626 pat_init_cache_modes(pat);
1627
1628 /* keep using Xen gdt for now; no urgent need to change it */ 1619 /* keep using Xen gdt for now; no urgent need to change it */
1629 1620
1630#ifdef CONFIG_X86_32 1621#ifdef CONFIG_X86_32
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3d31d3ac589e..aaec8aef9fd4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1732,7 +1732,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
1732 if (args->flags & ~(I915_MMAP_WC)) 1732 if (args->flags & ~(I915_MMAP_WC))
1733 return -EINVAL; 1733 return -EINVAL;
1734 1734
1735 if (args->flags & I915_MMAP_WC && !cpu_has_pat) 1735 if (args->flags & I915_MMAP_WC && !boot_cpu_has(X86_FEATURE_PAT))
1736 return -ENODEV; 1736 return -ENODEV;
1737 1737
1738 obj = drm_gem_object_lookup(dev, file, args->handle); 1738 obj = drm_gem_object_lookup(dev, file, args->handle);