Skip to content

Commit bd809af

Browse files
jgross1KAGA-KOKO
authored andcommitted
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 <[email protected]> Reviewed-by: Toshi Kani <[email protected]> Reviewed-by: Konrad Rzeszutek Wilk <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent f5b2831 commit bd809af

File tree

5 files changed

+63
-2
lines changed

5 files changed

+63
-2
lines changed

arch/x86/include/asm/pat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ static const int pat_enabled;
1111
#endif
1212

1313
extern void pat_init(void);
14+
void pat_init_cache_modes(void);
1415

1516
extern int reserve_memtype(u64 start, u64 end,
1617
enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);

arch/x86/include/asm/pgtable_types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ extern uint8_t __pte2cachemode_tbl[8];
351351
((((cb) >> (_PAGE_BIT_PAT - 2)) & 4) | \
352352
(((cb) >> (_PAGE_BIT_PCD - 1)) & 2) | \
353353
(((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))
354358

355359
static inline unsigned long cachemode2protval(enum page_cache_mode pcm)
356360
{

arch/x86/mm/init.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,3 +716,11 @@ void __init zone_sizes_init(void)
716716
free_area_init_nodes(max_zone_pfns);
717717
}
718718

719+
void 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+
}

arch/x86/mm/mm_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ void zone_sizes_init(void);
1616

1717
extern int after_bootmem;
1818

19+
void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache);
20+
1921
#endif /* __X86_MM_INTERNAL_H */

arch/x86/mm/pat.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <asm/io.h>
3232

3333
#include "pat_internal.h"
34+
#include "mm_internal.h"
3435

3536
#ifdef CONFIG_X86_PAT
3637
int __read_mostly pat_enabled = 1;
@@ -75,6 +76,52 @@ enum {
7576
PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
7677
};
7778

79+
#define CM(c) (_PAGE_CACHE_MODE_ ## c)
80+
81+
static 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+
*/
108+
void 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+
78125
#define PAT(x, y) ((u64)PAT_ ## y << ((x)*8))
79126

80127
void pat_init(void)
@@ -124,8 +171,7 @@ void pat_init(void)
124171
wrmsrl(MSR_IA32_CR_PAT, pat);
125172

126173
if (boot_cpu)
127-
printk(KERN_INFO "x86 PAT enabled: cpu %d, old 0x%Lx, new 0x%Lx\n",
128-
smp_processor_id(), boot_pat_state, pat);
174+
pat_init_cache_modes();
129175
}
130176

131177
#undef PAT

0 commit comments

Comments
 (0)