x86: mtrr_cleanup hole size should be less than half of chunk_size, v2

v2: should check with half of range0 size instead of chunk_size

So don't have silly big hole.

in hpa's case we could auto detect instead of adding mtrr_chunk_size in
command line.

Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Yinghai Lu 2008-09-27 20:26:06 -07:00 committed by Ingo Molnar
parent 54d45ff420
commit 8f0afaa58e
1 changed files with 45 additions and 33 deletions

View File

@ -992,12 +992,39 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
/* only cut back, when it is not the last */ /* only cut back, when it is not the last */
if (sizek) { if (sizek) {
while (range0_basek + range0_sizek > (basek + sizek)) { while (range0_basek + range0_sizek > (basek + sizek)) {
if (range0_sizek >= chunk_sizek)
range0_sizek -= chunk_sizek; range0_sizek -= chunk_sizek;
else
range0_sizek = 0;
if (!range0_sizek) if (!range0_sizek)
break; break;
} }
} }
second_try:
range_basek = range0_basek + range0_sizek;
/* one hole in the middle */
if (range_basek > basek && range_basek <= (basek + sizek))
second_sizek = range_basek - basek;
if (range0_sizek > state->range_sizek) {
/* one hole in middle or at end */
hole_sizek = range0_sizek - state->range_sizek - second_sizek;
/* hole size should be less than half of range0 size */
if (hole_sizek > (range0_sizek >> 1) &&
range0_sizek >= chunk_sizek) {
range0_sizek -= chunk_sizek;
second_sizek = 0;
hole_sizek = 0;
goto second_try;
}
}
if (range0_sizek) { if (range0_sizek) {
if (debug_print) if (debug_print)
printk(KERN_DEBUG "range0: %016lx - %016lx\n", printk(KERN_DEBUG "range0: %016lx - %016lx\n",
@ -1005,20 +1032,20 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
(range0_basek + range0_sizek)<<10); (range0_basek + range0_sizek)<<10);
state->reg = range_to_mtrr(state->reg, range0_basek, state->reg = range_to_mtrr(state->reg, range0_basek,
range0_sizek, MTRR_TYPE_WRBACK); range0_sizek, MTRR_TYPE_WRBACK);
} }
range_basek = range0_basek + range0_sizek; if (range0_sizek < state->range_sizek) {
/* need to handle left over */
range_sizek = state->range_sizek - range0_sizek;
/* one hole in the middle */ if (debug_print)
if (range_basek > basek && range_basek <= (basek + sizek)) printk(KERN_DEBUG "range: %016lx - %016lx\n",
second_sizek = range_basek - basek; range_basek<<10,
(range_basek + range_sizek)<<10);
state->reg = range_to_mtrr(state->reg, range_basek,
range_sizek, MTRR_TYPE_WRBACK);
}
if (range0_sizek > state->range_sizek) {
unsigned long hole_basek, hole_sizek;
/* one hole in middle or at end */
hole_sizek = range0_sizek - state->range_sizek - second_sizek;
if (hole_sizek) { if (hole_sizek) {
hole_basek = range_basek - hole_sizek - second_sizek; hole_basek = range_basek - hole_sizek - second_sizek;
if (debug_print) if (debug_print)
@ -1026,22 +1053,7 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek,
hole_basek<<10, hole_basek<<10,
(hole_basek + hole_sizek)<<10); (hole_basek + hole_sizek)<<10);
state->reg = range_to_mtrr(state->reg, hole_basek, state->reg = range_to_mtrr(state->reg, hole_basek,
hole_sizek, hole_sizek, MTRR_TYPE_UNCACHABLE);
MTRR_TYPE_UNCACHABLE);
}
} else {
/* need to handle left over */
range_sizek = state->range_sizek - range0_sizek;
if (range_sizek) {
if (debug_print)
printk(KERN_DEBUG "range: %016lx - %016lx\n",
range_basek<<10,
(range_basek + range_sizek)<<10);
state->reg = range_to_mtrr(state->reg, range_basek,
range_sizek,
MTRR_TYPE_WRBACK);
}
} }
return second_sizek; return second_sizek;