Skip to content

Commit 0cc705f

Browse files
Toshi KaniIngo Molnar
authored andcommitted
x86/mm/mtrr: Clean up mtrr_type_lookup()
MTRRs contain fixed and variable entries. mtrr_type_lookup() may repeatedly call __mtrr_type_lookup() to handle a request that overlaps with variable entries. However, __mtrr_type_lookup() also handles the fixed entries, which do not have to be repeated. Therefore, this patch creates separate functions, mtrr_type_lookup_fixed() and mtrr_type_lookup_variable(), to handle the fixed and variable ranges respectively. The patch also updates the function headers to clarify the return values and output argument. It updates comments to clarify that the repeating is necessary to handle overlaps with the default type, since overlaps with multiple entries alone can be handled without such repeating. There is no functional change in this patch. Signed-off-by: Toshi Kani <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: [email protected] Cc: H. Peter Anvin <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Luis R. Rodriguez <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: linux-mm <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 3d3ca41 commit 0cc705f

File tree

1 file changed

+86
-52
lines changed

1 file changed

+86
-52
lines changed

arch/x86/kernel/cpu/mtrr/generic.c

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -102,55 +102,68 @@ static int check_type_overlap(u8 *prev, u8 *curr)
102102
return 0;
103103
}
104104

105-
/*
106-
* Error/Semi-error returns:
107-
* MTRR_TYPE_INVALID - when MTRR is not enabled
108-
* *repeat == 1 implies [start:end] spanned across MTRR range and type returned
109-
* corresponds only to [start:*partial_end].
110-
* Caller has to lookup again for [*partial_end:end].
105+
/**
106+
* mtrr_type_lookup_fixed - look up memory type in MTRR fixed entries
107+
*
108+
* Return the MTRR fixed memory type of 'start'.
109+
*
110+
* MTRR fixed entries are divided into the following ways:
111+
* 0x00000 - 0x7FFFF : This range is divided into eight 64KB sub-ranges
112+
* 0x80000 - 0xBFFFF : This range is divided into sixteen 16KB sub-ranges
113+
* 0xC0000 - 0xFFFFF : This range is divided into sixty-four 4KB sub-ranges
114+
*
115+
* Return Values:
116+
* MTRR_TYPE_(type) - Matched memory type
117+
* MTRR_TYPE_INVALID - Unmatched
118+
*/
119+
static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
120+
{
121+
int idx;
122+
123+
if (start >= 0x100000)
124+
return MTRR_TYPE_INVALID;
125+
126+
/* 0x0 - 0x7FFFF */
127+
if (start < 0x80000) {
128+
idx = 0;
129+
idx += (start >> 16);
130+
return mtrr_state.fixed_ranges[idx];
131+
/* 0x80000 - 0xBFFFF */
132+
} else if (start < 0xC0000) {
133+
idx = 1 * 8;
134+
idx += ((start - 0x80000) >> 14);
135+
return mtrr_state.fixed_ranges[idx];
136+
}
137+
138+
/* 0xC0000 - 0xFFFFF */
139+
idx = 3 * 8;
140+
idx += ((start - 0xC0000) >> 12);
141+
return mtrr_state.fixed_ranges[idx];
142+
}
143+
144+
/**
145+
* mtrr_type_lookup_variable - look up memory type in MTRR variable entries
146+
*
147+
* Return Value:
148+
* MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
149+
*
150+
* Output Argument:
151+
* repeat - Set to 1 when [start:end] spanned across MTRR range and type
152+
* returned corresponds only to [start:*partial_end]. Caller has
153+
* to lookup again for [*partial_end:end].
111154
*/
112-
static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
155+
static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
156+
int *repeat)
113157
{
114158
int i;
115159
u64 base, mask;
116160
u8 prev_match, curr_match;
117161

118162
*repeat = 0;
119-
if (!mtrr_state_set)
120-
return MTRR_TYPE_INVALID;
121-
122-
if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
123-
return MTRR_TYPE_INVALID;
124163

125-
/* Make end inclusive end, instead of exclusive */
164+
/* Make end inclusive instead of exclusive */
126165
end--;
127166

128-
/* Look in fixed ranges. Just return the type as per start */
129-
if ((start < 0x100000) &&
130-
(mtrr_state.have_fixed) &&
131-
(mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
132-
int idx;
133-
134-
if (start < 0x80000) {
135-
idx = 0;
136-
idx += (start >> 16);
137-
return mtrr_state.fixed_ranges[idx];
138-
} else if (start < 0xC0000) {
139-
idx = 1 * 8;
140-
idx += ((start - 0x80000) >> 14);
141-
return mtrr_state.fixed_ranges[idx];
142-
} else {
143-
idx = 3 * 8;
144-
idx += ((start - 0xC0000) >> 12);
145-
return mtrr_state.fixed_ranges[idx];
146-
}
147-
}
148-
149-
/*
150-
* Look in variable ranges
151-
* Look of multiple ranges matching this address and pick type
152-
* as per MTRR precedence
153-
*/
154167
prev_match = MTRR_TYPE_INVALID;
155168
for (i = 0; i < num_var_ranges; ++i) {
156169
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)
186199
* advised to lookup again after having adjusted start
187200
* and end.
188201
*
189-
* Note: This way we handle multiple overlaps as well.
202+
* Note: This way we handle overlaps with multiple
203+
* entries and the default type properly.
190204
*/
191205
if (start_state)
192206
*partial_end = base + get_mtrr_size(mask);
@@ -215,44 +229,64 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
215229
return curr_match;
216230
}
217231

218-
if (mtrr_tom2) {
219-
if (start >= (1ULL<<32) && (end < mtrr_tom2))
220-
return MTRR_TYPE_WRBACK;
221-
}
222-
223232
if (prev_match != MTRR_TYPE_INVALID)
224233
return prev_match;
225234

226235
return mtrr_state.def_type;
227236
}
228237

229-
/*
230-
* Returns the effective MTRR type for the region
231-
* Error return:
232-
* MTRR_TYPE_INVALID - when MTRR is not enabled
238+
/**
239+
* mtrr_type_lookup - look up memory type in MTRR
240+
*
241+
* Return Values:
242+
* MTRR_TYPE_(type) - The effective MTRR type for the region
243+
* MTRR_TYPE_INVALID - MTRR is disabled
233244
*/
234245
u8 mtrr_type_lookup(u64 start, u64 end)
235246
{
236247
u8 type, prev_type;
237248
int repeat;
238249
u64 partial_end;
239250

240-
type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
251+
if (!mtrr_state_set)
252+
return MTRR_TYPE_INVALID;
253+
254+
if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
255+
return MTRR_TYPE_INVALID;
256+
257+
/*
258+
* Look up the fixed ranges first, which take priority over
259+
* the variable ranges.
260+
*/
261+
if ((start < 0x100000) &&
262+
(mtrr_state.have_fixed) &&
263+
(mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
264+
return mtrr_type_lookup_fixed(start, end);
265+
266+
/*
267+
* Look up the variable ranges. Look of multiple ranges matching
268+
* this address and pick type as per MTRR precedence.
269+
*/
270+
type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
241271

242272
/*
243273
* Common path is with repeat = 0.
244274
* However, we can have cases where [start:end] spans across some
245-
* MTRR range. Do repeated lookups for that case here.
275+
* MTRR ranges and/or the default type. Do repeated lookups for
276+
* that case here.
246277
*/
247278
while (repeat) {
248279
prev_type = type;
249280
start = partial_end;
250-
type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
281+
type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
251282

252283
if (check_type_overlap(&prev_type, &type))
253284
return type;
254285
}
255286

287+
if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
288+
return MTRR_TYPE_WRBACK;
289+
256290
return type;
257291
}
258292

0 commit comments

Comments
 (0)