|
@@ -102,55 +102,68 @@ static int check_type_overlap(u8 *prev, u8 *curr)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Error/Semi-error returns:
|
|
|
|
- * MTRR_TYPE_INVALID - when MTRR is not enabled
|
|
|
|
- * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
|
|
|
|
- * corresponds only to [start:*partial_end].
|
|
|
|
- * Caller has to lookup again for [*partial_end:end].
|
|
|
|
|
|
+/**
|
|
|
|
+ * mtrr_type_lookup_fixed - look up memory type in MTRR fixed entries
|
|
|
|
+ *
|
|
|
|
+ * Return the MTRR fixed memory type of 'start'.
|
|
|
|
+ *
|
|
|
|
+ * MTRR fixed entries are divided into the following ways:
|
|
|
|
+ * 0x00000 - 0x7FFFF : This range is divided into eight 64KB sub-ranges
|
|
|
|
+ * 0x80000 - 0xBFFFF : This range is divided into sixteen 16KB sub-ranges
|
|
|
|
+ * 0xC0000 - 0xFFFFF : This range is divided into sixty-four 4KB sub-ranges
|
|
|
|
+ *
|
|
|
|
+ * Return Values:
|
|
|
|
+ * MTRR_TYPE_(type) - Matched memory type
|
|
|
|
+ * MTRR_TYPE_INVALID - Unmatched
|
|
|
|
+ */
|
|
|
|
+static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
|
|
|
|
+{
|
|
|
|
+ int idx;
|
|
|
|
+
|
|
|
|
+ if (start >= 0x100000)
|
|
|
|
+ return MTRR_TYPE_INVALID;
|
|
|
|
+
|
|
|
|
+ /* 0x0 - 0x7FFFF */
|
|
|
|
+ if (start < 0x80000) {
|
|
|
|
+ idx = 0;
|
|
|
|
+ idx += (start >> 16);
|
|
|
|
+ return mtrr_state.fixed_ranges[idx];
|
|
|
|
+ /* 0x80000 - 0xBFFFF */
|
|
|
|
+ } else if (start < 0xC0000) {
|
|
|
|
+ idx = 1 * 8;
|
|
|
|
+ idx += ((start - 0x80000) >> 14);
|
|
|
|
+ return mtrr_state.fixed_ranges[idx];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* 0xC0000 - 0xFFFFF */
|
|
|
|
+ idx = 3 * 8;
|
|
|
|
+ idx += ((start - 0xC0000) >> 12);
|
|
|
|
+ return mtrr_state.fixed_ranges[idx];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * mtrr_type_lookup_variable - look up memory type in MTRR variable entries
|
|
|
|
+ *
|
|
|
|
+ * Return Value:
|
|
|
|
+ * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
|
|
|
|
+ *
|
|
|
|
+ * Output Argument:
|
|
|
|
+ * repeat - Set to 1 when [start:end] spanned across MTRR range and type
|
|
|
|
+ * returned corresponds only to [start:*partial_end]. Caller has
|
|
|
|
+ * to lookup again for [*partial_end:end].
|
|
*/
|
|
*/
|
|
-static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
|
|
|
|
|
|
+static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
|
|
|
|
+ int *repeat)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
u64 base, mask;
|
|
u64 base, mask;
|
|
u8 prev_match, curr_match;
|
|
u8 prev_match, curr_match;
|
|
|
|
|
|
*repeat = 0;
|
|
*repeat = 0;
|
|
- if (!mtrr_state_set)
|
|
|
|
- return MTRR_TYPE_INVALID;
|
|
|
|
-
|
|
|
|
- if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
|
|
|
|
- return MTRR_TYPE_INVALID;
|
|
|
|
|
|
|
|
- /* Make end inclusive end, instead of exclusive */
|
|
|
|
|
|
+ /* Make end inclusive instead of exclusive */
|
|
end--;
|
|
end--;
|
|
|
|
|
|
- /* Look in fixed ranges. Just return the type as per start */
|
|
|
|
- if ((start < 0x100000) &&
|
|
|
|
- (mtrr_state.have_fixed) &&
|
|
|
|
- (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
|
|
|
|
- int idx;
|
|
|
|
-
|
|
|
|
- if (start < 0x80000) {
|
|
|
|
- idx = 0;
|
|
|
|
- idx += (start >> 16);
|
|
|
|
- return mtrr_state.fixed_ranges[idx];
|
|
|
|
- } else if (start < 0xC0000) {
|
|
|
|
- idx = 1 * 8;
|
|
|
|
- idx += ((start - 0x80000) >> 14);
|
|
|
|
- return mtrr_state.fixed_ranges[idx];
|
|
|
|
- } else {
|
|
|
|
- idx = 3 * 8;
|
|
|
|
- idx += ((start - 0xC0000) >> 12);
|
|
|
|
- return mtrr_state.fixed_ranges[idx];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- * Look in variable ranges
|
|
|
|
- * Look of multiple ranges matching this address and pick type
|
|
|
|
- * as per MTRR precedence
|
|
|
|
- */
|
|
|
|
prev_match = MTRR_TYPE_INVALID;
|
|
prev_match = MTRR_TYPE_INVALID;
|
|
for (i = 0; i < num_var_ranges; ++i) {
|
|
for (i = 0; i < num_var_ranges; ++i) {
|
|
unsigned short start_state, end_state, inclusive;
|
|
unsigned short start_state, end_state, inclusive;
|
|
@@ -186,7 +199,8 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
|
|
* advised to lookup again after having adjusted start
|
|
* advised to lookup again after having adjusted start
|
|
* and end.
|
|
* and end.
|
|
*
|
|
*
|
|
- * Note: This way we handle multiple overlaps as well.
|
|
|
|
|
|
+ * Note: This way we handle overlaps with multiple
|
|
|
|
+ * entries and the default type properly.
|
|
*/
|
|
*/
|
|
if (start_state)
|
|
if (start_state)
|
|
*partial_end = base + get_mtrr_size(mask);
|
|
*partial_end = base + get_mtrr_size(mask);
|
|
@@ -215,21 +229,18 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
|
|
return curr_match;
|
|
return curr_match;
|
|
}
|
|
}
|
|
|
|
|
|
- if (mtrr_tom2) {
|
|
|
|
- if (start >= (1ULL<<32) && (end < mtrr_tom2))
|
|
|
|
- return MTRR_TYPE_WRBACK;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (prev_match != MTRR_TYPE_INVALID)
|
|
if (prev_match != MTRR_TYPE_INVALID)
|
|
return prev_match;
|
|
return prev_match;
|
|
|
|
|
|
return mtrr_state.def_type;
|
|
return mtrr_state.def_type;
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Returns the effective MTRR type for the region
|
|
|
|
- * Error return:
|
|
|
|
- * MTRR_TYPE_INVALID - when MTRR is not enabled
|
|
|
|
|
|
+/**
|
|
|
|
+ * mtrr_type_lookup - look up memory type in MTRR
|
|
|
|
+ *
|
|
|
|
+ * Return Values:
|
|
|
|
+ * MTRR_TYPE_(type) - The effective MTRR type for the region
|
|
|
|
+ * MTRR_TYPE_INVALID - MTRR is disabled
|
|
*/
|
|
*/
|
|
u8 mtrr_type_lookup(u64 start, u64 end)
|
|
u8 mtrr_type_lookup(u64 start, u64 end)
|
|
{
|
|
{
|
|
@@ -237,22 +248,45 @@ u8 mtrr_type_lookup(u64 start, u64 end)
|
|
int repeat;
|
|
int repeat;
|
|
u64 partial_end;
|
|
u64 partial_end;
|
|
|
|
|
|
- type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
|
|
|
|
|
|
+ if (!mtrr_state_set)
|
|
|
|
+ return MTRR_TYPE_INVALID;
|
|
|
|
+
|
|
|
|
+ if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
|
|
|
|
+ return MTRR_TYPE_INVALID;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Look up the fixed ranges first, which take priority over
|
|
|
|
+ * the variable ranges.
|
|
|
|
+ */
|
|
|
|
+ if ((start < 0x100000) &&
|
|
|
|
+ (mtrr_state.have_fixed) &&
|
|
|
|
+ (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
|
|
|
|
+ return mtrr_type_lookup_fixed(start, end);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Look up the variable ranges. Look of multiple ranges matching
|
|
|
|
+ * this address and pick type as per MTRR precedence.
|
|
|
|
+ */
|
|
|
|
+ type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Common path is with repeat = 0.
|
|
* Common path is with repeat = 0.
|
|
* However, we can have cases where [start:end] spans across some
|
|
* However, we can have cases where [start:end] spans across some
|
|
- * MTRR range. Do repeated lookups for that case here.
|
|
|
|
|
|
+ * MTRR ranges and/or the default type. Do repeated lookups for
|
|
|
|
+ * that case here.
|
|
*/
|
|
*/
|
|
while (repeat) {
|
|
while (repeat) {
|
|
prev_type = type;
|
|
prev_type = type;
|
|
start = partial_end;
|
|
start = partial_end;
|
|
- type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
|
|
|
|
|
|
+ type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
|
|
|
|
|
|
if (check_type_overlap(&prev_type, &type))
|
|
if (check_type_overlap(&prev_type, &type))
|
|
return type;
|
|
return type;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
|
|
|
|
+ return MTRR_TYPE_WRBACK;
|
|
|
|
+
|
|
return type;
|
|
return type;
|
|
}
|
|
}
|
|
|
|
|