generic.c (ac7c5353b189e10cf5dd27399f64f7b013abffc6) generic.c (2e5d9c857d4e6c9e7b7d8c8c86a68a7842d213d6)
1/* This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
2 because MTRRs can span upto 40 bits (36bits on most modern x86) */
3#include <linux/init.h>
4#include <linux/slab.h>
5#include <linux/mm.h>
6#include <linux/module.h>
7#include <asm/io.h>
8#include <asm/mtrr.h>
9#include <asm/msr.h>
10#include <asm/system.h>
11#include <asm/cpufeature.h>
12#include <asm/processor-flags.h>
13#include <asm/tlbflush.h>
1/* This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
2 because MTRRs can span upto 40 bits (36bits on most modern x86) */
3#include <linux/init.h>
4#include <linux/slab.h>
5#include <linux/mm.h>
6#include <linux/module.h>
7#include <asm/io.h>
8#include <asm/mtrr.h>
9#include <asm/msr.h>
10#include <asm/system.h>
11#include <asm/cpufeature.h>
12#include <asm/processor-flags.h>
13#include <asm/tlbflush.h>
14#include <asm/pat.h>
14#include "mtrr.h"
15
16struct mtrr_state {
17 struct mtrr_var_range var_ranges[MAX_VAR_RANGES];
18 mtrr_type fixed_ranges[NUM_FIXED_RANGES];
19 unsigned char enabled;
20 unsigned char have_fixed;
21 mtrr_type def_type;

--- 8 unchanged lines hidden (view full) ---

30 { MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */
31 { MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */
32 { MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */
33 {}
34};
35
36static unsigned long smp_changes_mask;
37static struct mtrr_state mtrr_state = {};
15#include "mtrr.h"
16
17struct mtrr_state {
18 struct mtrr_var_range var_ranges[MAX_VAR_RANGES];
19 mtrr_type fixed_ranges[NUM_FIXED_RANGES];
20 unsigned char enabled;
21 unsigned char have_fixed;
22 mtrr_type def_type;

--- 8 unchanged lines hidden (view full) ---

31 { MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */
32 { MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */
33 { MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */
34 {}
35};
36
37static unsigned long smp_changes_mask;
38static struct mtrr_state mtrr_state = {};
39static int mtrr_state_set;
38
39#undef MODULE_PARAM_PREFIX
40#define MODULE_PARAM_PREFIX "mtrr."
41
42static int mtrr_show;
43module_param_named(show, mtrr_show, bool, 0);
44
40
41#undef MODULE_PARAM_PREFIX
42#define MODULE_PARAM_PREFIX "mtrr."
43
44static int mtrr_show;
45module_param_named(show, mtrr_show, bool, 0);
46
47/*
48 * Returns the effective MTRR type for the region
49 * Error returns:
50 * - 0xFE - when the range is "not entirely covered" by _any_ var range MTRR
51 * - 0xFF - when MTRR is not enabled
52 */
53u8 mtrr_type_lookup(u64 start, u64 end)
54{
55 int i;
56 u64 base, mask;
57 u8 prev_match, curr_match;
58
59 if (!mtrr_state_set)
60 return 0xFF;
61
62 if (!mtrr_state.enabled)
63 return 0xFF;
64
65 /* Make end inclusive end, instead of exclusive */
66 end--;
67
68 /* Look in fixed ranges. Just return the type as per start */
69 if (mtrr_state.have_fixed && (start < 0x100000)) {
70 int idx;
71
72 if (start < 0x80000) {
73 idx = 0;
74 idx += (start >> 16);
75 return mtrr_state.fixed_ranges[idx];
76 } else if (start < 0xC0000) {
77 idx = 1 * 8;
78 idx += ((start - 0x80000) >> 14);
79 return mtrr_state.fixed_ranges[idx];
80 } else if (start < 0x1000000) {
81 idx = 3 * 8;
82 idx += ((start - 0xC0000) >> 12);
83 return mtrr_state.fixed_ranges[idx];
84 }
85 }
86
87 /*
88 * Look in variable ranges
89 * Look of multiple ranges matching this address and pick type
90 * as per MTRR precedence
91 */
92 if (!mtrr_state.enabled & 2) {
93 return mtrr_state.def_type;
94 }
95
96 prev_match = 0xFF;
97 for (i = 0; i < num_var_ranges; ++i) {
98 unsigned short start_state, end_state;
99
100 if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11)))
101 continue;
102
103 base = (((u64)mtrr_state.var_ranges[i].base_hi) << 32) +
104 (mtrr_state.var_ranges[i].base_lo & PAGE_MASK);
105 mask = (((u64)mtrr_state.var_ranges[i].mask_hi) << 32) +
106 (mtrr_state.var_ranges[i].mask_lo & PAGE_MASK);
107
108 start_state = ((start & mask) == (base & mask));
109 end_state = ((end & mask) == (base & mask));
110 if (start_state != end_state)
111 return 0xFE;
112
113 if ((start & mask) != (base & mask)) {
114 continue;
115 }
116
117 curr_match = mtrr_state.var_ranges[i].base_lo & 0xff;
118 if (prev_match == 0xFF) {
119 prev_match = curr_match;
120 continue;
121 }
122
123 if (prev_match == MTRR_TYPE_UNCACHABLE ||
124 curr_match == MTRR_TYPE_UNCACHABLE) {
125 return MTRR_TYPE_UNCACHABLE;
126 }
127
128 if ((prev_match == MTRR_TYPE_WRBACK &&
129 curr_match == MTRR_TYPE_WRTHROUGH) ||
130 (prev_match == MTRR_TYPE_WRTHROUGH &&
131 curr_match == MTRR_TYPE_WRBACK)) {
132 prev_match = MTRR_TYPE_WRTHROUGH;
133 curr_match = MTRR_TYPE_WRTHROUGH;
134 }
135
136 if (prev_match != curr_match) {
137 return MTRR_TYPE_UNCACHABLE;
138 }
139 }
140
141 if (prev_match != 0xFF)
142 return prev_match;
143
144 return mtrr_state.def_type;
145}
146
45/* Get the MSR pair relating to a var range */
46static void
47get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
48{
49 rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
50 rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
51}
52

--- 21 unchanged lines hidden (view full) ---

74{
75 unsigned i;
76
77 for (i = 0; i < 8; ++i, ++types, base += step)
78 printk(KERN_INFO "MTRR %05X-%05X %s\n",
79 base, base + step - 1, mtrr_attrib_to_str(*types));
80}
81
147/* Get the MSR pair relating to a var range */
148static void
149get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
150{
151 rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
152 rdmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
153}
154

--- 21 unchanged lines hidden (view full) ---

176{
177 unsigned i;
178
179 for (i = 0; i < 8; ++i, ++types, base += step)
180 printk(KERN_INFO "MTRR %05X-%05X %s\n",
181 base, base + step - 1, mtrr_attrib_to_str(*types));
182}
183
184static void prepare_set(void);
185static void post_set(void);
186
82/* Grab all of the MTRR state for this CPU into *state */
83void __init get_mtrr_state(void)
84{
85 unsigned int i;
86 struct mtrr_var_range *vrs;
87 unsigned lo, dummy;
187/* Grab all of the MTRR state for this CPU into *state */
188void __init get_mtrr_state(void)
189{
190 unsigned int i;
191 struct mtrr_var_range *vrs;
192 unsigned lo, dummy;
193 unsigned long flags;
88
89 vrs = mtrr_state.var_ranges;
90
91 rdmsr(MTRRcap_MSR, lo, dummy);
92 mtrr_state.have_fixed = (lo >> 8) & 1;
93
94 for (i = 0; i < num_var_ranges; i++)
95 get_mtrr_var_range(i, &vrs[i]);

--- 30 unchanged lines hidden (view full) ---

126 high_width,
127 mtrr_state.var_ranges[i].mask_hi,
128 mtrr_state.var_ranges[i].mask_lo >> 12,
129 mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
130 else
131 printk(KERN_INFO "MTRR %u disabled\n", i);
132 }
133 }
194
195 vrs = mtrr_state.var_ranges;
196
197 rdmsr(MTRRcap_MSR, lo, dummy);
198 mtrr_state.have_fixed = (lo >> 8) & 1;
199
200 for (i = 0; i < num_var_ranges; i++)
201 get_mtrr_var_range(i, &vrs[i]);

--- 30 unchanged lines hidden (view full) ---

232 high_width,
233 mtrr_state.var_ranges[i].mask_hi,
234 mtrr_state.var_ranges[i].mask_lo >> 12,
235 mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff));
236 else
237 printk(KERN_INFO "MTRR %u disabled\n", i);
238 }
239 }
240 mtrr_state_set = 1;
241
242 /* PAT setup for BP. We need to go through sync steps here */
243 local_irq_save(flags);
244 prepare_set();
245
246 pat_init();
247
248 post_set();
249 local_irq_restore(flags);
250
134}
135
136/* Some BIOS's are fucked and don't set all MTRRs the same! */
137void __init mtrr_state_warn(void)
138{
139 unsigned long mask = smp_changes_mask;
140
141 if (!mask)

--- 250 unchanged lines hidden (view full) ---

392 unsigned long flags;
393
394 local_irq_save(flags);
395 prepare_set();
396
397 /* Actually set the state */
398 mask = set_mtrr_state();
399
251}
252
253/* Some BIOS's are fucked and don't set all MTRRs the same! */
254void __init mtrr_state_warn(void)
255{
256 unsigned long mask = smp_changes_mask;
257
258 if (!mask)

--- 250 unchanged lines hidden (view full) ---

509 unsigned long flags;
510
511 local_irq_save(flags);
512 prepare_set();
513
514 /* Actually set the state */
515 mask = set_mtrr_state();
516
517 /* also set PAT */
518 pat_init();
519
400 post_set();
401 local_irq_restore(flags);
402
403 /* Use the atomic bitops to update the global mask */
404 for (count = 0; count < sizeof mask * 8; ++count) {
405 if (mask & 0x01)
406 set_bit(count, &smp_changes_mask);
407 mask >>= 1;

--- 99 unchanged lines hidden ---
520 post_set();
521 local_irq_restore(flags);
522
523 /* Use the atomic bitops to update the global mask */
524 for (count = 0; count < sizeof mask * 8; ++count) {
525 if (mask & 0x01)
526 set_bit(count, &smp_changes_mask);
527 mask >>= 1;

--- 99 unchanged lines hidden ---