[coreboot-gerrit] New patch to review for coreboot: 7e66ae0 NOTFORMERGE: MTRR: Automatically transform WRCOMB to UC if needed.
Vladimir Serbinenko (phcoder@gmail.com)
gerrit at coreboot.org
Wed Feb 5 22:10:02 CET 2014
Vladimir Serbinenko (phcoder at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5148
-gerrit
commit 7e66ae0ac9edb535b7d46be76c60074fcace4da8
Author: Vladimir Serbinenko <phcoder at gmail.com>
Date: Wed Feb 5 22:09:25 2014 +0100
NOTFORMERGE: MTRR: Automatically transform WRCOMB to UC if needed.
Change-Id: Ic2a25c4ed91abbe062e755147d007d5b97c30571
Signed-off-by: Vladimir Serbinenko <phcoder at gmail.com>
---
src/cpu/x86/mtrr/mtrr.c | 40 ++++++++++++++++++++++++++++++----------
1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 54fdfd8..ae49053 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -154,19 +154,22 @@ static inline int range_entry_mtrr_type(struct range_entry *r)
return range_entry_tag(r) & MTRR_TAG_MASK;
}
-static struct memranges *get_physical_address_space(void)
+static struct memranges *get_physical_address_space(int skip_wrcomb)
{
static struct memranges *addr_space;
static struct memranges addr_space_storage;
+ static int saved_skip_wrcomb = 0;
/* In order to handle some chipsets not being able to pre-determine
* uncacheable ranges, such as graphics memory, at resource insertion
* time remove uncacheable regions from the cacheable ones. */
- if (addr_space == NULL) {
+ if (addr_space == NULL || skip_wrcomb != saved_skip_wrcomb) {
struct range_entry *r;
unsigned long mask;
unsigned long match;
+ saved_skip_wrcomb = skip_wrcomb;
+
addr_space = &addr_space_storage;
mask = IORESOURCE_CACHEABLE;
@@ -180,10 +183,12 @@ static struct memranges *get_physical_address_space(void)
/* Handle any write combining resources. Only prefetchable
* resources with the IORESOURCE_WRCOMB flag are appropriate
* for this MTRR type. */
- match = IORESOURCE_PREFETCH | IORESOURCE_WRCOMB;
- mask |= match;
- memranges_add_resources(addr_space, mask, match,
- MTRR_TYPE_WRCOMB);
+ if (!skip_wrcomb) {
+ match = IORESOURCE_PREFETCH | IORESOURCE_WRCOMB;
+ mask |= match;
+ memranges_add_resources(addr_space, mask, match,
+ MTRR_TYPE_WRCOMB);
+ }
/* The address space below 4GiB is special. It needs to be
* covered entirly by range entries so that MTRR calculations
@@ -244,7 +249,7 @@ static void calc_fixed_mtrrs(void)
if (fixed_mtrr_types_initialized)
return;
- phys_addr_space = get_physical_address_space();
+ phys_addr_space = get_physical_address_space(0);
/* Set all fixed ranges to uncacheable first. */
memset(&fixed_mtrr_types[0], MTRR_TYPE_UNCACHEABLE, NUM_FIXED_RANGES);
@@ -586,7 +591,7 @@ static void calc_var_mtrrs_without_hole(struct var_mtrr_state *var_state,
}
static int calc_var_mtrrs(struct memranges *addr_space,
- int above4gb, int address_bits)
+ int above4gb, int address_bits, int *need_mtrr)
{
int wb_deftype_count;
int uc_deftype_count;
@@ -668,9 +673,11 @@ static int calc_var_mtrrs(struct memranges *addr_space,
if (wb_deftype_count < uc_deftype_count) {
printk(BIOS_DEBUG, "MTRR: WB selected as default type.\n");
+ *need_mtrr = wb_deftype_count;
return MTRR_TYPE_WRBACK;
}
printk(BIOS_DEBUG, "MTRR: UC selected as default type.\n");
+ *need_mtrr = uc_deftype_count;
return MTRR_TYPE_UNCACHEABLE;
}
@@ -708,15 +715,28 @@ static void commit_var_mtrrs(struct memranges *addr_space, int def_type,
void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb)
{
static int mtrr_default_type = -1;
+ static int skip_wrcomb = 0;
struct memranges *addr_space;
- addr_space = get_physical_address_space();
+ addr_space = get_physical_address_space(skip_wrcomb);
if (mtrr_default_type == -1) {
+ int need_mtrr = 0;
if (above4gb == 2)
detect_var_mtrrs();
mtrr_default_type =
- calc_var_mtrrs(addr_space, !!above4gb, address_bits);
+ calc_var_mtrrs(addr_space, !!above4gb, address_bits,
+ &need_mtrr);
+ /* Not enough MTRRs, make WRCOMB into UC. */
+ if (need_mtrr > bios_mtrrs) {
+ printk(BIOS_ERR, "not enough MTRRs, degrading WRCOMB"
+ " to UC\n");
+ skip_wrcomb = 1;
+ addr_space = get_physical_address_space(1);
+ mtrr_default_type =
+ calc_var_mtrrs(addr_space, !!above4gb,
+ address_bits, &need_mtrr);
+ }
}
disable_cache();
More information about the coreboot-gerrit
mailing list