aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2014-11-03 08:02:03 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-11-16 05:04:26 -0500
commitbd809af16e3ab1f8d55b3e2928c47c67e2a865d2 (patch)
tree8ac5084b758cc1af91737e070d281f041df470c0
parentf5b2831d654167d77da8afbef4d2584897b12d0c (diff)
x86: Enable PAT to use cache mode translation tables
Update the translation tables from cache mode to pgprot values according to the PAT settings. This enables changing the cache attributes of a PAT index in just one place without having to change at the users side. With this change it is possible to use the same kernel with different PAT configurations, e.g. supporting Xen. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Toshi Kani <toshi.kani@hp.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: stefan.bader@canonical.com Cc: xen-devel@lists.xensource.com Cc: ville.syrjala@linux.intel.com Cc: david.vrabel@citrix.com Cc: jbeulich@suse.com Cc: plagnioj@jcrosoft.com Cc: tomi.valkeinen@ti.com Cc: bhelgaas@google.com Link: http://lkml.kernel.org/r/1415019724-4317-18-git-send-email-jgross@suse.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/include/asm/pat.h1
-rw-r--r--arch/x86/include/asm/pgtable_types.h4
-rw-r--r--arch/x86/mm/init.c8
-rw-r--r--arch/x86/mm/mm_internal.h2
-rw-r--r--arch/x86/mm/pat.c50
5 files changed, 63 insertions, 2 deletions
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index 150407a7234d..91bc4ba95f91 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -11,6 +11,7 @@ static const int pat_enabled;
11#endif 11#endif
12 12
13extern void pat_init(void); 13extern void pat_init(void);
14void pat_init_cache_modes(void);
14 15
15extern int reserve_memtype(u64 start, u64 end, 16extern int reserve_memtype(u64 start, u64 end,
16 enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm); 17 enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 6d5f6d154215..af447f95e3be 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -351,6 +351,10 @@ extern uint8_t __pte2cachemode_tbl[8];
351 ((((cb) >> (_PAGE_BIT_PAT - 2)) & 4) | \ 351 ((((cb) >> (_PAGE_BIT_PAT - 2)) & 4) | \
352 (((cb) >> (_PAGE_BIT_PCD - 1)) & 2) | \ 352 (((cb) >> (_PAGE_BIT_PCD - 1)) & 2) | \
353 (((cb) >> _PAGE_BIT_PWT) & 1)) 353 (((cb) >> _PAGE_BIT_PWT) & 1))
354#define __cm_idx2pte(i) \
355 ((((i) & 4) << (_PAGE_BIT_PAT - 2)) | \
356 (((i) & 2) << (_PAGE_BIT_PCD - 1)) | \
357 (((i) & 1) << _PAGE_BIT_PWT))
354 358
355static inline unsigned long cachemode2protval(enum page_cache_mode pcm) 359static inline unsigned long cachemode2protval(enum page_cache_mode pcm)
356{ 360{
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index a9776ba475d4..82b41d56bb98 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -716,3 +716,11 @@ void __init zone_sizes_init(void)
716 free_area_init_nodes(max_zone_pfns); 716 free_area_init_nodes(max_zone_pfns);
717} 717}
718 718
719void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache)
720{
721 /* entry 0 MUST be WB (hardwired to speed up translations) */
722 BUG_ON(!entry && cache != _PAGE_CACHE_MODE_WB);
723
724 __cachemode2pte_tbl[cache] = __cm_idx2pte(entry);
725 __pte2cachemode_tbl[entry] = cache;
726}
diff --git a/arch/x86/mm/mm_internal.h b/arch/x86/mm/mm_internal.h
index 6b563a118891..62474ba66c8e 100644
--- a/arch/x86/mm/mm_internal.h
+++ b/arch/x86/mm/mm_internal.h
@@ -16,4 +16,6 @@ void zone_sizes_init(void);
16 16
17extern int after_bootmem; 17extern int after_bootmem;
18 18
19void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache);
20
19#endif /* __X86_MM_INTERNAL_H */ 21#endif /* __X86_MM_INTERNAL_H */
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index ef75f3f89810..4c601276a556 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -31,6 +31,7 @@
31#include <asm/io.h> 31#include <asm/io.h>
32 32
33#include "pat_internal.h" 33#include "pat_internal.h"
34#include "mm_internal.h"
34 35
35#ifdef CONFIG_X86_PAT 36#ifdef CONFIG_X86_PAT
36int __read_mostly pat_enabled = 1; 37int __read_mostly pat_enabled = 1;
@@ -75,6 +76,52 @@ enum {
75 PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */ 76 PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
76}; 77};
77 78
79#define CM(c) (_PAGE_CACHE_MODE_ ## c)
80
81static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
82{
83 enum page_cache_mode cache;
84 char *cache_mode;
85
86 switch (pat_val) {
87 case PAT_UC: cache = CM(UC); cache_mode = "UC "; break;
88 case PAT_WC: cache = CM(WC); cache_mode = "WC "; break;
89 case PAT_WT: cache = CM(WT); cache_mode = "WT "; break;
90 case PAT_WP: cache = CM(WP); cache_mode = "WP "; break;
91 case PAT_WB: cache = CM(WB); cache_mode = "WB "; break;
92 case PAT_UC_MINUS: cache = CM(UC_MINUS); cache_mode = "UC- "; break;
93 default: cache = CM(WB); cache_mode = "WB "; break;
94 }
95
96 memcpy(msg, cache_mode, 4);
97
98 return cache;
99}
100
101#undef CM
102
103/*
104 * Update the cache mode to pgprot translation tables according to PAT
105 * configuration.
106 * Using lower indices is preferred, so we start with highest index.
107 */
108void pat_init_cache_modes(void)
109{
110 int i;
111 enum page_cache_mode cache;
112 char pat_msg[33];
113 u64 pat;
114
115 rdmsrl(MSR_IA32_CR_PAT, pat);
116 pat_msg[32] = 0;
117 for (i = 7; i >= 0; i--) {
118 cache = pat_get_cache_mode((pat >> (i * 8)) & 7,
119 pat_msg + 4 * i);
120 update_cache_mode_entry(i, cache);
121 }
122 pr_info("PAT configuration [0-7]: %s\n", pat_msg);
123}
124
78#define PAT(x, y) ((u64)PAT_ ## y << ((x)*8)) 125#define PAT(x, y) ((u64)PAT_ ## y << ((x)*8))
79 126
80void pat_init(void) 127void pat_init(void)
@@ -124,8 +171,7 @@ void pat_init(void)
124 wrmsrl(MSR_IA32_CR_PAT, pat); 171 wrmsrl(MSR_IA32_CR_PAT, pat);
125 172
126 if (boot_cpu) 173 if (boot_cpu)
127 printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n", 174 pat_init_cache_modes();
128 smp_processor_id(), boot_pat_state, pat);
129} 175}
130 176
131#undef PAT 177#undef PAT