diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-09-27 03:30:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-27 12:09:34 -0400 |
commit | 2313c2793d290a8cc37c428f8622c53f3fe1d6dc (patch) | |
tree | 7c58eadcd07a5b51defac8b455b75e0e72d09c42 /arch | |
parent | 7fc2368d1d0dce7a778beb2fba3acac8fa7a34b6 (diff) |
x86: mtrr_cleanup optimization, v2
fix hpa's t61 with 4g ram:
change layout from
(n - 1)*chunksize + chunk_size - NC
to
n*chunksize - NC
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/main.c | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index cc135572882a..93d575ac61a3 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
@@ -970,6 +970,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
970 | /* try to append some small hole */ | 970 | /* try to append some small hole */ |
971 | range0_basek = state->range_startk; | 971 | range0_basek = state->range_startk; |
972 | range0_sizek = ALIGN(state->range_sizek, chunk_sizek); | 972 | range0_sizek = ALIGN(state->range_sizek, chunk_sizek); |
973 | |||
974 | /* no increase */ | ||
973 | if (range0_sizek == state->range_sizek) { | 975 | if (range0_sizek == state->range_sizek) { |
974 | if (debug_print) | 976 | if (debug_print) |
975 | printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", | 977 | printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", |
@@ -980,13 +982,13 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
980 | return 0; | 982 | return 0; |
981 | } | 983 | } |
982 | 984 | ||
983 | range0_sizek -= chunk_sizek; | 985 | /* only cut back, when it is not the last */ |
984 | if (range0_sizek && sizek) { | 986 | if (sizek) { |
985 | while (range0_basek + range0_sizek > (basek + sizek)) { | 987 | while (range0_basek + range0_sizek > (basek + sizek)) { |
986 | range0_sizek -= chunk_sizek; | 988 | range0_sizek -= chunk_sizek; |
987 | if (!range0_sizek) | 989 | if (!range0_sizek) |
988 | break; | 990 | break; |
989 | } | 991 | } |
990 | } | 992 | } |
991 | 993 | ||
992 | if (range0_sizek) { | 994 | if (range0_sizek) { |
@@ -1000,46 +1002,39 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
1000 | } | 1002 | } |
1001 | 1003 | ||
1002 | range_basek = range0_basek + range0_sizek; | 1004 | range_basek = range0_basek + range0_sizek; |
1003 | range_sizek = chunk_sizek; | ||
1004 | 1005 | ||
1005 | if (range_basek + range_sizek > basek && | 1006 | /* one hole in the middle */ |
1006 | range_basek + range_sizek <= (basek + sizek)) { | 1007 | if (range_basek > basek && range_basek <= (basek + sizek)) |
1007 | /* one hole */ | 1008 | second_sizek = range_basek - basek; |
1008 | second_basek = basek; | ||
1009 | second_sizek = range_basek + range_sizek - basek; | ||
1010 | } | ||
1011 | 1009 | ||
1012 | /* if last piece, only could one hole near end */ | 1010 | if (range0_sizek > state->range_sizek) { |
1013 | if ((second_basek || !basek) && | 1011 | unsigned long hole_basek, hole_sizek; |
1014 | range_sizek - (state->range_sizek - range0_sizek) - second_sizek < | 1012 | |
1015 | (chunk_sizek >> 1)) { | 1013 | /* one hole in middle or at end */ |
1016 | /* | 1014 | hole_sizek = range0_sizek - state->range_sizek - second_sizek; |
1017 | * one hole in middle (second_sizek is 0) or at end | 1015 | if (hole_sizek) { |
1018 | * (second_sizek is 0 ) | 1016 | hole_basek = range_basek - hole_sizek - second_sizek; |
1019 | */ | 1017 | if (debug_print) |
1020 | hole_sizek = range_sizek - (state->range_sizek - range0_sizek) | 1018 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", |
1021 | - second_sizek; | 1019 | hole_basek<<10, |
1022 | hole_basek = range_basek + range_sizek - hole_sizek | 1020 | (hole_basek + hole_sizek)<<10); |
1023 | - second_sizek; | 1021 | state->reg = range_to_mtrr(state->reg, hole_basek, |
1024 | } else { | 1022 | hole_sizek, |
1025 | /* fallback for big hole, or several holes */ | 1023 | MTRR_TYPE_UNCACHABLE); |
1024 | } | ||
1025 | } else { | ||
1026 | /* need to handle left over */ | ||
1026 | range_sizek = state->range_sizek - range0_sizek; | 1027 | range_sizek = state->range_sizek - range0_sizek; |
1027 | second_basek = 0; | ||
1028 | second_sizek = 0; | ||
1029 | } | ||
1030 | 1028 | ||
1031 | if (debug_print) | 1029 | if (range_sizek) { |
1032 | printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10, | 1030 | if (debug_print) |
1033 | (range_basek + range_sizek)<<10); | 1031 | printk(KERN_DEBUG "range: %016lx - %016lx\n", |
1034 | state->reg = range_to_mtrr(state->reg, range_basek, range_sizek, | 1032 | range_basek<<10, |
1033 | (range_basek + range_sizek)<<10); | ||
1034 | state->reg = range_to_mtrr(state->reg, range_basek, | ||
1035 | range_sizek, | ||
1035 | MTRR_TYPE_WRBACK); | 1036 | MTRR_TYPE_WRBACK); |
1036 | if (hole_sizek) { | 1037 | } |
1037 | if (debug_print) | ||
1038 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", | ||
1039 | hole_basek<<10, (hole_basek + hole_sizek)<<10); | ||
1040 | state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek, | ||
1041 | MTRR_TYPE_UNCACHABLE); | ||
1042 | |||
1043 | } | 1038 | } |
1044 | 1039 | ||
1045 | return second_sizek; | 1040 | return second_sizek; |