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 --- |