summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/x86/mtrr/mtrr.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/cpu/x86/mtrr/mtrr.c b/src/cpu/x86/mtrr/mtrr.c
index 005ea81063..253a7c318b 100644
--- a/src/cpu/x86/mtrr/mtrr.c
+++ b/src/cpu/x86/mtrr/mtrr.c
@@ -553,14 +553,31 @@ static void calc_var_mtrrs_with_hole(struct var_mtrr_state *var_state,
if (!var_state->above4gb && a2 > RANGE_4GB)
a2 = RANGE_4GB;
+ next = memranges_next_entry(var_state->addr_space, r);
+
b1 = a2;
+
+ /* First check if a1 is >= 4GiB and the current etnry is the last
+ * entry. If so perform an optimization of covering a larger range
+ * defined by the base address' alignment. */
+ if (a1 >= RANGE_4GB && next == NULL) {
+ uint32_t addr_lsb;
+
+ addr_lsb = fls(a1);
+ b2 = (1 << addr_lsb) + a1;
+ if (b2 >= a2) {
+ calc_var_mtrr_range(var_state, a1, b2 - a1, mtrr_type);
+ return;
+ }
+ }
+
+ /* Handle the min alignment roundup case. */
b2 = ALIGN_UP(a2, MTRR_MIN_ALIGN);
/* Check against the next range. If the current range_entry is the
* last entry then carving a hole is no problem. If the current entry
* isn't the last entry then check that the last entry covers the
* entire hole range with the default mtrr type. */
- next = memranges_next_entry(var_state->addr_space, r);
if (next != NULL &&
(range_entry_mtrr_type(next) != var_state->def_mtrr_type ||
range_entry_end_mtrr_addr(next) < b2)) {