summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYinghai Lu <yinghailu@gmail.com>2005-01-27 22:48:12 +0000
committerYinghai Lu <yinghailu@gmail.com>2005-01-27 22:48:12 +0000
commit6360187e9e01a27b7f10ce8910ec01cee41fa329 (patch)
tree2dbd83473cc718c4d20c31548457073b3ef5f022
parent830435bb16e8e8dcc1e44f52b0603fcec4345664 (diff)
spare one more mtrr
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1903 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r--src/cpu/x86/mtrr/mtrr.c55
1 files changed, 24 insertions, 31 deletions
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 5cc09e3980..1c028a9ea1 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -219,36 +219,11 @@ static unsigned fixed_mtrr_index(unsigned long addrk)
static unsigned int range_to_mtrr(unsigned int reg,
unsigned long range_startk, unsigned long range_sizek,
- unsigned long next_range_startk)
+ unsigned long next_range_startk, unsigned char type)
{
if (!range_sizek || (reg >= BIOS_MTRRS)) {
return reg;
}
- if(next_range_startk == 4096*1024) {// There is a hole below 4G, We need to use UC to spare mtrr
- unsigned long sizek;
- sizek = 4096*1024;
- printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n",
- reg, range_startk >>10, sizek >> 10);
- set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK);
- while(range_sizek) {
- unsigned long max_align, align;
- /* Compute the maximum size I can make a range */
- max_align = fls(range_startk);
- align = fms(range_sizek);
- if (align > max_align) {
- align = max_align;
- }
- sizek = 1 << align;
- range_startk += sizek;
- range_sizek -= sizek;
- }
-
- range_startk = 4096*1024 - sizek;
- printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type NC\n",
- reg, range_startk >>10, sizek >> 10);
- set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_UNCACHEABLE);
- return reg;
- }
while(range_sizek) {
unsigned long max_align, align;
unsigned long sizek;
@@ -259,9 +234,12 @@ static unsigned int range_to_mtrr(unsigned int reg,
align = max_align;
}
sizek = 1 << align;
- printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n",
- reg, range_startk >>10, sizek >> 10);
- set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK);
+ printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type %s\n",
+ reg, range_startk >>10, sizek >> 10,
+ (type==MTRR_TYPE_UNCACHEABLE)?"NC":
+ ((type==MTRR_TYPE_WRBACK)?"WB":"Other")
+ );
+ set_var_mtrr(reg++, range_startk, sizek, type);
range_startk += sizek;
range_sizek -= sizek;
if (reg >= BIOS_MTRRS)
@@ -300,6 +278,7 @@ static void set_fixed_mtrr_resource(void *gp, struct device *dev, struct resourc
struct var_mtrr_state {
unsigned long range_startk, range_sizek;
unsigned int reg;
+ unsigned long hole_startk, hole_sizek;
};
void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
@@ -321,9 +300,20 @@ void set_var_mtrr_resource(void *gp, struct device *dev, struct resource *res)
}
/* Write the range mtrrs */
if (state->range_sizek != 0) {
- state->reg = range_to_mtrr(state->reg, state->range_startk, state->range_sizek, basek);
+ if(state->hole_sizek == 0) {
+ // we need to put that on to hole.
+ unsigned long endk = basek + sizek;
+ state->hole_startk = state->range_startk + state->range_sizek;
+ state->hole_sizek = basek - state->hole_startk;
+ state->range_sizek = endk - state->range_startk;
+ return;
+ }
+ state->reg = range_to_mtrr(state->reg, state->range_startk, state->range_sizek, basek, MTRR_TYPE_WRBACK);
+ state->reg = range_to_mtrr(state->reg, state->hole_startk, state->hole_sizek, basek, MTRR_TYPE_UNCACHEABLE);
state->range_startk = 0;
state->range_sizek = 0;
+ state->hole_startk = 0;
+ state->hole_sizek = 0;
}
/* Allocate an msr */
state->range_startk = basek;
@@ -358,13 +348,16 @@ void x86_setup_mtrrs(void)
*/
var_state.range_startk = 0;
var_state.range_sizek = 0;
+ var_state.hole_startk = 0;
+ var_state.hole_sizek = 0;
var_state.reg = 0;
search_global_resources(
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
set_var_mtrr_resource, &var_state);
/* Write the last range */
- var_state.reg = range_to_mtrr(var_state.reg, var_state.range_startk, var_state.range_sizek, 0);
+ var_state.reg = range_to_mtrr(var_state.reg, var_state.range_startk, var_state.range_sizek, 0, MTRR_TYPE_WRBACK);
+ var_state.reg = range_to_mtrr(var_state.reg, var_state.hole_startk, var_state.hole_sizek, 0, MTRR_TYPE_UNCACHEABLE);
printk_debug("DONE variable MTRRs\n");
printk_debug("Clear out the extra MTRR's\n");
/* Clear out the extra MTRR's */