|
@@ -379,6 +379,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
|
|
|
unsigned long *size, mtrr_type *type)
|
|
|
{
|
|
|
unsigned int mask_lo, mask_hi, base_lo, base_hi;
|
|
|
+ unsigned int tmp, hi;
|
|
|
|
|
|
rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi);
|
|
|
if ((mask_lo & 0x800) == 0) {
|
|
@@ -392,8 +393,18 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
|
|
|
rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
|
|
|
|
|
|
/* Work out the shifted address mask. */
|
|
|
- mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT)
|
|
|
- | mask_lo >> PAGE_SHIFT;
|
|
|
+ tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT;
|
|
|
+ mask_lo = size_or_mask | tmp;
|
|
|
+ /* Expand tmp with high bits to all 1s*/
|
|
|
+ hi = fls(tmp);
|
|
|
+ if (hi > 0) {
|
|
|
+ tmp |= ~((1<<(hi - 1)) - 1);
|
|
|
+
|
|
|
+ if (tmp != mask_lo) {
|
|
|
+ WARN_ON("mtrr: your BIOS has set up an incorrect mask, fixing it up.\n");
|
|
|
+ mask_lo = tmp;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* This works correctly if size is a power of two, i.e. a
|
|
|
contiguous range. */
|