Skip to content

Commit

Permalink
x86: MTRR workaround for system with stange var MTRRs
Browse files Browse the repository at this point in the history
Impact: don't trim e820 according to wrong mtrr

Ozan reports that his server emits strange warning.
it turns out the BIOS sets the MTRRs incorrectly.

Ignore those strange ranges, and don't trim e820,
just emit one warning about BIOS

Reported-by: Ozan Çağlayan <ozan@pardus.org.tr>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <49BEE1E7.7020706@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Yinghai Lu authored and Ingo Molnar committed Mar 17, 2009
1 parent d4c90e3 commit f0348c4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 8 deletions.
11 changes: 11 additions & 0 deletions arch/x86/kernel/cpu/mtrr/cleanup.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,17 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range,
if (!size)
continue;
base = range_state[i].base_pfn;
if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed &&
(mtrr_state.enabled & 1)) {
/* Var MTRR contains UC entry below 1M? Skip it: */
printk(KERN_WARNING "WARNING: BIOS bug: VAR MTRR %d "
"contains strange UC entry under 1M, check "
"with your system vendor!\n", i);
if (base + size <= (1<<(20-PAGE_SHIFT)))
continue;
size -= (1<<(20-PAGE_SHIFT)) - base;
base = 1<<(20-PAGE_SHIFT);
}
subtract_range(range, base, base + size - 1);
}
if (extra_remove_size)
Expand Down
16 changes: 8 additions & 8 deletions arch/x86/kernel/cpu/mtrr/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,17 +574,17 @@ struct mtrr_value {
unsigned long lsize;
};

static struct mtrr_value mtrr_state[MTRR_MAX_VAR_RANGES];
static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES];

static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
{
int i;

for (i = 0; i < num_var_ranges; i++) {
mtrr_if->get(i,
&mtrr_state[i].lbase,
&mtrr_state[i].lsize,
&mtrr_state[i].ltype);
&mtrr_value[i].lbase,
&mtrr_value[i].lsize,
&mtrr_value[i].ltype);
}
return 0;
}
Expand All @@ -594,11 +594,11 @@ static int mtrr_restore(struct sys_device * sysdev)
int i;

for (i = 0; i < num_var_ranges; i++) {
if (mtrr_state[i].lsize)
if (mtrr_value[i].lsize)
set_mtrr(i,
mtrr_state[i].lbase,
mtrr_state[i].lsize,
mtrr_state[i].ltype);
mtrr_value[i].lbase,
mtrr_value[i].lsize,
mtrr_value[i].ltype);
}
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/mtrr/mtrr.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ extern struct mtrr_ops * mtrr_if;

extern unsigned int num_var_ranges;
extern u64 mtrr_tom2;
extern struct mtrr_state_type mtrr_state;

void mtrr_state_warn(void);
const char *mtrr_attrib_to_str(int x);
Expand Down

0 comments on commit f0348c4

Please sign in to comment.