diff options
Diffstat (limited to 'arch/x86/kernel/cpu/mtrr/main.c')
| -rw-r--r-- | arch/x86/kernel/cpu/mtrr/main.c | 276 |
1 files changed, 190 insertions, 86 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index b117d7f8a564..c78c04821ea1 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
| @@ -729,7 +729,7 @@ struct var_mtrr_range_state { | |||
| 729 | mtrr_type type; | 729 | mtrr_type type; |
| 730 | }; | 730 | }; |
| 731 | 731 | ||
| 732 | struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; | 732 | static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; |
| 733 | static int __initdata debug_print; | 733 | static int __initdata debug_print; |
| 734 | 734 | ||
| 735 | static int __init | 735 | static int __init |
| @@ -759,7 +759,8 @@ x86_get_mtrr_mem_range(struct res_range *range, int nr_range, | |||
| 759 | /* take out UC ranges */ | 759 | /* take out UC ranges */ |
| 760 | for (i = 0; i < num_var_ranges; i++) { | 760 | for (i = 0; i < num_var_ranges; i++) { |
| 761 | type = range_state[i].type; | 761 | type = range_state[i].type; |
| 762 | if (type != MTRR_TYPE_UNCACHABLE) | 762 | if (type != MTRR_TYPE_UNCACHABLE && |
| 763 | type != MTRR_TYPE_WRPROT) | ||
| 763 | continue; | 764 | continue; |
| 764 | size = range_state[i].size_pfn; | 765 | size = range_state[i].size_pfn; |
| 765 | if (!size) | 766 | if (!size) |
| @@ -834,7 +835,14 @@ static int __init enable_mtrr_cleanup_setup(char *str) | |||
| 834 | enable_mtrr_cleanup = 1; | 835 | enable_mtrr_cleanup = 1; |
| 835 | return 0; | 836 | return 0; |
| 836 | } | 837 | } |
| 837 | early_param("enble_mtrr_cleanup", enable_mtrr_cleanup_setup); | 838 | early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup); |
| 839 | |||
| 840 | static int __init mtrr_cleanup_debug_setup(char *str) | ||
| 841 | { | ||
| 842 | debug_print = 1; | ||
| 843 | return 0; | ||
| 844 | } | ||
| 845 | early_param("mtrr_cleanup_debug", mtrr_cleanup_debug_setup); | ||
| 838 | 846 | ||
| 839 | struct var_mtrr_state { | 847 | struct var_mtrr_state { |
| 840 | unsigned long range_startk; | 848 | unsigned long range_startk; |
| @@ -898,6 +906,27 @@ set_var_mtrr_all(unsigned int address_bits) | |||
| 898 | } | 906 | } |
| 899 | } | 907 | } |
| 900 | 908 | ||
| 909 | static unsigned long to_size_factor(unsigned long sizek, char *factorp) | ||
| 910 | { | ||
| 911 | char factor; | ||
| 912 | unsigned long base = sizek; | ||
| 913 | |||
| 914 | if (base & ((1<<10) - 1)) { | ||
| 915 | /* not MB alignment */ | ||
| 916 | factor = 'K'; | ||
| 917 | } else if (base & ((1<<20) - 1)){ | ||
| 918 | factor = 'M'; | ||
| 919 | base >>= 10; | ||
| 920 | } else { | ||
| 921 | factor = 'G'; | ||
| 922 | base >>= 20; | ||
| 923 | } | ||
| 924 | |||
| 925 | *factorp = factor; | ||
| 926 | |||
| 927 | return base; | ||
| 928 | } | ||
| 929 | |||
| 901 | static unsigned int __init | 930 | static unsigned int __init |
| 902 | range_to_mtrr(unsigned int reg, unsigned long range_startk, | 931 | range_to_mtrr(unsigned int reg, unsigned long range_startk, |
| 903 | unsigned long range_sizek, unsigned char type) | 932 | unsigned long range_sizek, unsigned char type) |
| @@ -919,13 +948,21 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk, | |||
| 919 | align = max_align; | 948 | align = max_align; |
| 920 | 949 | ||
| 921 | sizek = 1 << align; | 950 | sizek = 1 << align; |
| 922 | if (debug_print) | 951 | if (debug_print) { |
| 952 | char start_factor = 'K', size_factor = 'K'; | ||
| 953 | unsigned long start_base, size_base; | ||
| 954 | |||
| 955 | start_base = to_size_factor(range_startk, &start_factor), | ||
| 956 | size_base = to_size_factor(sizek, &size_factor), | ||
| 957 | |||
| 923 | printk(KERN_DEBUG "Setting variable MTRR %d, " | 958 | printk(KERN_DEBUG "Setting variable MTRR %d, " |
| 924 | "base: %ldMB, range: %ldMB, type %s\n", | 959 | "base: %ld%cB, range: %ld%cB, type %s\n", |
| 925 | reg, range_startk >> 10, sizek >> 10, | 960 | reg, start_base, start_factor, |
| 961 | size_base, size_factor, | ||
| 926 | (type == MTRR_TYPE_UNCACHABLE)?"UC": | 962 | (type == MTRR_TYPE_UNCACHABLE)?"UC": |
| 927 | ((type == MTRR_TYPE_WRBACK)?"WB":"Other") | 963 | ((type == MTRR_TYPE_WRBACK)?"WB":"Other") |
| 928 | ); | 964 | ); |
| 965 | } | ||
| 929 | save_var_mtrr(reg++, range_startk, sizek, type); | 966 | save_var_mtrr(reg++, range_startk, sizek, type); |
| 930 | range_startk += sizek; | 967 | range_startk += sizek; |
| 931 | range_sizek -= sizek; | 968 | range_sizek -= sizek; |
| @@ -970,6 +1007,8 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
| 970 | /* try to append some small hole */ | 1007 | /* try to append some small hole */ |
| 971 | range0_basek = state->range_startk; | 1008 | range0_basek = state->range_startk; |
| 972 | range0_sizek = ALIGN(state->range_sizek, chunk_sizek); | 1009 | range0_sizek = ALIGN(state->range_sizek, chunk_sizek); |
| 1010 | |||
| 1011 | /* no increase */ | ||
| 973 | if (range0_sizek == state->range_sizek) { | 1012 | if (range0_sizek == state->range_sizek) { |
| 974 | if (debug_print) | 1013 | if (debug_print) |
| 975 | printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", | 1014 | printk(KERN_DEBUG "rangeX: %016lx - %016lx\n", |
| @@ -980,13 +1019,40 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
| 980 | return 0; | 1019 | return 0; |
| 981 | } | 1020 | } |
| 982 | 1021 | ||
| 983 | range0_sizek -= chunk_sizek; | 1022 | /* only cut back, when it is not the last */ |
| 984 | if (range0_sizek && sizek) { | 1023 | if (sizek) { |
| 985 | while (range0_basek + range0_sizek > (basek + sizek)) { | 1024 | while (range0_basek + range0_sizek > (basek + sizek)) { |
| 986 | range0_sizek -= chunk_sizek; | 1025 | if (range0_sizek >= chunk_sizek) |
| 987 | if (!range0_sizek) | 1026 | range0_sizek -= chunk_sizek; |
| 988 | break; | 1027 | else |
| 989 | } | 1028 | range0_sizek = 0; |
| 1029 | |||
| 1030 | if (!range0_sizek) | ||
| 1031 | break; | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | second_try: | ||
| 1036 | range_basek = range0_basek + range0_sizek; | ||
| 1037 | |||
| 1038 | /* one hole in the middle */ | ||
| 1039 | if (range_basek > basek && range_basek <= (basek + sizek)) | ||
| 1040 | second_sizek = range_basek - basek; | ||
| 1041 | |||
| 1042 | if (range0_sizek > state->range_sizek) { | ||
| 1043 | |||
| 1044 | /* one hole in middle or at end */ | ||
| 1045 | hole_sizek = range0_sizek - state->range_sizek - second_sizek; | ||
| 1046 | |||
| 1047 | /* hole size should be less than half of range0 size */ | ||
| 1048 | if (hole_sizek >= (range0_sizek >> 1) && | ||
| 1049 | range0_sizek >= chunk_sizek) { | ||
| 1050 | range0_sizek -= chunk_sizek; | ||
| 1051 | second_sizek = 0; | ||
| 1052 | hole_sizek = 0; | ||
| 1053 | |||
| 1054 | goto second_try; | ||
| 1055 | } | ||
| 990 | } | 1056 | } |
| 991 | 1057 | ||
| 992 | if (range0_sizek) { | 1058 | if (range0_sizek) { |
| @@ -996,50 +1062,28 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
| 996 | (range0_basek + range0_sizek)<<10); | 1062 | (range0_basek + range0_sizek)<<10); |
| 997 | state->reg = range_to_mtrr(state->reg, range0_basek, | 1063 | state->reg = range_to_mtrr(state->reg, range0_basek, |
| 998 | range0_sizek, MTRR_TYPE_WRBACK); | 1064 | range0_sizek, MTRR_TYPE_WRBACK); |
| 999 | |||
| 1000 | } | ||
| 1001 | |||
| 1002 | range_basek = range0_basek + range0_sizek; | ||
| 1003 | range_sizek = chunk_sizek; | ||
| 1004 | |||
| 1005 | if (range_basek + range_sizek > basek && | ||
| 1006 | range_basek + range_sizek <= (basek + sizek)) { | ||
| 1007 | /* one hole */ | ||
| 1008 | second_basek = basek; | ||
| 1009 | second_sizek = range_basek + range_sizek - basek; | ||
| 1010 | } | 1065 | } |
| 1011 | 1066 | ||
| 1012 | /* if last piece, only could one hole near end */ | 1067 | if (range0_sizek < state->range_sizek) { |
| 1013 | if ((second_basek || !basek) && | 1068 | /* need to handle left over */ |
| 1014 | range_sizek - (state->range_sizek - range0_sizek) - second_sizek < | ||
| 1015 | (chunk_sizek >> 1)) { | ||
| 1016 | /* | ||
| 1017 | * one hole in middle (second_sizek is 0) or at end | ||
| 1018 | * (second_sizek is 0 ) | ||
| 1019 | */ | ||
| 1020 | hole_sizek = range_sizek - (state->range_sizek - range0_sizek) | ||
| 1021 | - second_sizek; | ||
| 1022 | hole_basek = range_basek + range_sizek - hole_sizek | ||
| 1023 | - second_sizek; | ||
| 1024 | } else { | ||
| 1025 | /* fallback for big hole, or several holes */ | ||
| 1026 | range_sizek = state->range_sizek - range0_sizek; | 1069 | range_sizek = state->range_sizek - range0_sizek; |
| 1027 | second_basek = 0; | 1070 | |
| 1028 | second_sizek = 0; | 1071 | if (debug_print) |
| 1072 | printk(KERN_DEBUG "range: %016lx - %016lx\n", | ||
| 1073 | range_basek<<10, | ||
| 1074 | (range_basek + range_sizek)<<10); | ||
| 1075 | state->reg = range_to_mtrr(state->reg, range_basek, | ||
| 1076 | range_sizek, MTRR_TYPE_WRBACK); | ||
| 1029 | } | 1077 | } |
| 1030 | 1078 | ||
| 1031 | if (debug_print) | ||
| 1032 | printk(KERN_DEBUG "range: %016lx - %016lx\n", range_basek<<10, | ||
| 1033 | (range_basek + range_sizek)<<10); | ||
| 1034 | state->reg = range_to_mtrr(state->reg, range_basek, range_sizek, | ||
| 1035 | MTRR_TYPE_WRBACK); | ||
| 1036 | if (hole_sizek) { | 1079 | if (hole_sizek) { |
| 1080 | hole_basek = range_basek - hole_sizek - second_sizek; | ||
| 1037 | if (debug_print) | 1081 | if (debug_print) |
| 1038 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", | 1082 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", |
| 1039 | hole_basek<<10, (hole_basek + hole_sizek)<<10); | 1083 | hole_basek<<10, |
| 1040 | state->reg = range_to_mtrr(state->reg, hole_basek, hole_sizek, | 1084 | (hole_basek + hole_sizek)<<10); |
| 1041 | MTRR_TYPE_UNCACHABLE); | 1085 | state->reg = range_to_mtrr(state->reg, hole_basek, |
| 1042 | 1086 | hole_sizek, MTRR_TYPE_UNCACHABLE); | |
| 1043 | } | 1087 | } |
| 1044 | 1088 | ||
| 1045 | return second_sizek; | 1089 | return second_sizek; |
| @@ -1154,11 +1198,11 @@ struct mtrr_cleanup_result { | |||
| 1154 | }; | 1198 | }; |
| 1155 | 1199 | ||
| 1156 | /* | 1200 | /* |
| 1157 | * gran_size: 1M, 2M, ..., 2G | 1201 | * gran_size: 64K, 128K, 256K, 512K, 1M, 2M, ..., 2G |
| 1158 | * chunk size: gran_size, ..., 4G | 1202 | * chunk size: gran_size, ..., 2G |
| 1159 | * so we need (2+13)*6 | 1203 | * so we need (1+16)*8 |
| 1160 | */ | 1204 | */ |
| 1161 | #define NUM_RESULT 90 | 1205 | #define NUM_RESULT 136 |
| 1162 | #define PSHIFT (PAGE_SHIFT - 10) | 1206 | #define PSHIFT (PAGE_SHIFT - 10) |
| 1163 | 1207 | ||
| 1164 | static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; | 1208 | static struct mtrr_cleanup_result __initdata result[NUM_RESULT]; |
| @@ -1168,13 +1212,14 @@ static unsigned long __initdata min_loss_pfn[RANGE_NUM]; | |||
| 1168 | static int __init mtrr_cleanup(unsigned address_bits) | 1212 | static int __init mtrr_cleanup(unsigned address_bits) |
| 1169 | { | 1213 | { |
| 1170 | unsigned long extra_remove_base, extra_remove_size; | 1214 | unsigned long extra_remove_base, extra_remove_size; |
| 1171 | unsigned long i, base, size, def, dummy; | 1215 | unsigned long base, size, def, dummy; |
| 1172 | mtrr_type type; | 1216 | mtrr_type type; |
| 1173 | int nr_range, nr_range_new; | 1217 | int nr_range, nr_range_new; |
| 1174 | u64 chunk_size, gran_size; | 1218 | u64 chunk_size, gran_size; |
| 1175 | unsigned long range_sums, range_sums_new; | 1219 | unsigned long range_sums, range_sums_new; |
| 1176 | int index_good; | 1220 | int index_good; |
| 1177 | int num_reg_good; | 1221 | int num_reg_good; |
| 1222 | int i; | ||
| 1178 | 1223 | ||
| 1179 | /* extra one for all 0 */ | 1224 | /* extra one for all 0 */ |
| 1180 | int num[MTRR_NUM_TYPES + 1]; | 1225 | int num[MTRR_NUM_TYPES + 1]; |
| @@ -1204,6 +1249,8 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1204 | continue; | 1249 | continue; |
| 1205 | if (!size) | 1250 | if (!size) |
| 1206 | type = MTRR_NUM_TYPES; | 1251 | type = MTRR_NUM_TYPES; |
| 1252 | if (type == MTRR_TYPE_WRPROT) | ||
| 1253 | type = MTRR_TYPE_UNCACHABLE; | ||
| 1207 | num[type]++; | 1254 | num[type]++; |
| 1208 | } | 1255 | } |
| 1209 | 1256 | ||
| @@ -1216,23 +1263,57 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1216 | num_var_ranges - num[MTRR_NUM_TYPES]) | 1263 | num_var_ranges - num[MTRR_NUM_TYPES]) |
| 1217 | return 0; | 1264 | return 0; |
| 1218 | 1265 | ||
| 1266 | /* print original var MTRRs at first, for debugging: */ | ||
| 1267 | printk(KERN_DEBUG "original variable MTRRs\n"); | ||
| 1268 | for (i = 0; i < num_var_ranges; i++) { | ||
| 1269 | char start_factor = 'K', size_factor = 'K'; | ||
| 1270 | unsigned long start_base, size_base; | ||
| 1271 | |||
| 1272 | size_base = range_state[i].size_pfn << (PAGE_SHIFT - 10); | ||
| 1273 | if (!size_base) | ||
| 1274 | continue; | ||
| 1275 | |||
| 1276 | size_base = to_size_factor(size_base, &size_factor), | ||
| 1277 | start_base = range_state[i].base_pfn << (PAGE_SHIFT - 10); | ||
| 1278 | start_base = to_size_factor(start_base, &start_factor), | ||
| 1279 | type = range_state[i].type; | ||
| 1280 | |||
| 1281 | printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n", | ||
| 1282 | i, start_base, start_factor, | ||
| 1283 | size_base, size_factor, | ||
| 1284 | (type == MTRR_TYPE_UNCACHABLE) ? "UC" : | ||
| 1285 | ((type == MTRR_TYPE_WRPROT) ? "WP" : | ||
| 1286 | ((type == MTRR_TYPE_WRBACK) ? "WB" : "Other")) | ||
| 1287 | ); | ||
| 1288 | } | ||
| 1289 | |||
| 1219 | memset(range, 0, sizeof(range)); | 1290 | memset(range, 0, sizeof(range)); |
| 1220 | extra_remove_size = 0; | 1291 | extra_remove_size = 0; |
| 1221 | if (mtrr_tom2) { | 1292 | extra_remove_base = 1 << (32 - PAGE_SHIFT); |
| 1222 | extra_remove_base = 1 << (32 - PAGE_SHIFT); | 1293 | if (mtrr_tom2) |
| 1223 | extra_remove_size = | 1294 | extra_remove_size = |
| 1224 | (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; | 1295 | (mtrr_tom2 >> PAGE_SHIFT) - extra_remove_base; |
| 1225 | } | ||
| 1226 | nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, | 1296 | nr_range = x86_get_mtrr_mem_range(range, 0, extra_remove_base, |
| 1227 | extra_remove_size); | 1297 | extra_remove_size); |
| 1298 | /* | ||
| 1299 | * [0, 1M) should always be coverred by var mtrr with WB | ||
| 1300 | * and fixed mtrrs should take effective before var mtrr for it | ||
| 1301 | */ | ||
| 1302 | nr_range = add_range_with_merge(range, nr_range, 0, | ||
| 1303 | (1ULL<<(20 - PAGE_SHIFT)) - 1); | ||
| 1304 | /* sort the ranges */ | ||
| 1305 | sort(range, nr_range, sizeof(struct res_range), cmp_range, NULL); | ||
| 1306 | |||
| 1228 | range_sums = sum_ranges(range, nr_range); | 1307 | range_sums = sum_ranges(range, nr_range); |
| 1229 | printk(KERN_INFO "total RAM coverred: %ldM\n", | 1308 | printk(KERN_INFO "total RAM coverred: %ldM\n", |
| 1230 | range_sums >> (20 - PAGE_SHIFT)); | 1309 | range_sums >> (20 - PAGE_SHIFT)); |
| 1231 | 1310 | ||
| 1232 | if (mtrr_chunk_size && mtrr_gran_size) { | 1311 | if (mtrr_chunk_size && mtrr_gran_size) { |
| 1233 | int num_reg; | 1312 | int num_reg; |
| 1313 | char gran_factor, chunk_factor, lose_factor; | ||
| 1314 | unsigned long gran_base, chunk_base, lose_base; | ||
| 1234 | 1315 | ||
| 1235 | debug_print = 1; | 1316 | debug_print++; |
| 1236 | /* convert ranges to var ranges state */ | 1317 | /* convert ranges to var ranges state */ |
| 1237 | num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size, | 1318 | num_reg = x86_setup_var_mtrrs(range, nr_range, mtrr_chunk_size, |
| 1238 | mtrr_gran_size); | 1319 | mtrr_gran_size); |
| @@ -1256,34 +1337,48 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1256 | result[i].lose_cover_sizek = | 1337 | result[i].lose_cover_sizek = |
| 1257 | (range_sums - range_sums_new) << PSHIFT; | 1338 | (range_sums - range_sums_new) << PSHIFT; |
| 1258 | 1339 | ||
| 1259 | printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", | 1340 | gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), |
| 1260 | result[i].bad?"*BAD*":" ", result[i].gran_sizek >> 10, | 1341 | chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), |
| 1261 | result[i].chunk_sizek >> 10); | 1342 | lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), |
| 1262 | printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ldM \n", | 1343 | printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", |
| 1344 | result[i].bad?"*BAD*":" ", | ||
| 1345 | gran_base, gran_factor, chunk_base, chunk_factor); | ||
| 1346 | printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", | ||
| 1263 | result[i].num_reg, result[i].bad?"-":"", | 1347 | result[i].num_reg, result[i].bad?"-":"", |
| 1264 | result[i].lose_cover_sizek >> 10); | 1348 | lose_base, lose_factor); |
| 1265 | if (!result[i].bad) { | 1349 | if (!result[i].bad) { |
| 1266 | set_var_mtrr_all(address_bits); | 1350 | set_var_mtrr_all(address_bits); |
| 1267 | return 1; | 1351 | return 1; |
| 1268 | } | 1352 | } |
| 1269 | printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " | 1353 | printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " |
| 1270 | "will find optimal one\n"); | 1354 | "will find optimal one\n"); |
| 1271 | debug_print = 0; | 1355 | debug_print--; |
| 1272 | memset(result, 0, sizeof(result[0])); | 1356 | memset(result, 0, sizeof(result[0])); |
| 1273 | } | 1357 | } |
| 1274 | 1358 | ||
| 1275 | i = 0; | 1359 | i = 0; |
| 1276 | memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); | 1360 | memset(min_loss_pfn, 0xff, sizeof(min_loss_pfn)); |
| 1277 | memset(result, 0, sizeof(result)); | 1361 | memset(result, 0, sizeof(result)); |
| 1278 | for (gran_size = (1ULL<<20); gran_size < (1ULL<<32); gran_size <<= 1) { | 1362 | for (gran_size = (1ULL<<16); gran_size < (1ULL<<32); gran_size <<= 1) { |
| 1279 | for (chunk_size = gran_size; chunk_size < (1ULL<<33); | 1363 | char gran_factor; |
| 1364 | unsigned long gran_base; | ||
| 1365 | |||
| 1366 | if (debug_print) | ||
| 1367 | gran_base = to_size_factor(gran_size >> 10, &gran_factor); | ||
| 1368 | |||
| 1369 | for (chunk_size = gran_size; chunk_size < (1ULL<<32); | ||
| 1280 | chunk_size <<= 1) { | 1370 | chunk_size <<= 1) { |
| 1281 | int num_reg; | 1371 | int num_reg; |
| 1282 | 1372 | ||
| 1283 | if (debug_print) | 1373 | if (debug_print) { |
| 1284 | printk(KERN_INFO | 1374 | char chunk_factor; |
| 1285 | "\ngran_size: %lldM chunk_size_size: %lldM\n", | 1375 | unsigned long chunk_base; |
| 1286 | gran_size >> 20, chunk_size >> 20); | 1376 | |
| 1377 | chunk_base = to_size_factor(chunk_size>>10, &chunk_factor), | ||
| 1378 | printk(KERN_INFO "\n"); | ||
| 1379 | printk(KERN_INFO "gran_size: %ld%c chunk_size: %ld%c \n", | ||
| 1380 | gran_base, gran_factor, chunk_base, chunk_factor); | ||
| 1381 | } | ||
| 1287 | if (i >= NUM_RESULT) | 1382 | if (i >= NUM_RESULT) |
| 1288 | continue; | 1383 | continue; |
| 1289 | 1384 | ||
| @@ -1326,12 +1421,18 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1326 | 1421 | ||
| 1327 | /* print out all */ | 1422 | /* print out all */ |
| 1328 | for (i = 0; i < NUM_RESULT; i++) { | 1423 | for (i = 0; i < NUM_RESULT; i++) { |
| 1329 | printk(KERN_INFO "%sgran_size: %ldM \tchunk_size: %ldM \t", | 1424 | char gran_factor, chunk_factor, lose_factor; |
| 1330 | result[i].bad?"*BAD* ":" ", result[i].gran_sizek >> 10, | 1425 | unsigned long gran_base, chunk_base, lose_base; |
| 1331 | result[i].chunk_sizek >> 10); | 1426 | |
| 1332 | printk(KERN_CONT "num_reg: %d \tlose RAM: %s%ldM\n", | 1427 | gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), |
| 1333 | result[i].num_reg, result[i].bad?"-":"", | 1428 | chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), |
| 1334 | result[i].lose_cover_sizek >> 10); | 1429 | lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), |
| 1430 | printk(KERN_INFO "%sgran_size: %ld%c \tchunk_size: %ld%c \t", | ||
| 1431 | result[i].bad?"*BAD*":" ", | ||
| 1432 | gran_base, gran_factor, chunk_base, chunk_factor); | ||
| 1433 | printk(KERN_CONT "num_reg: %d \tlose cover RAM: %s%ld%c\n", | ||
| 1434 | result[i].num_reg, result[i].bad?"-":"", | ||
| 1435 | lose_base, lose_factor); | ||
| 1335 | } | 1436 | } |
| 1336 | 1437 | ||
| 1337 | /* try to find the optimal index */ | 1438 | /* try to find the optimal index */ |
| @@ -1339,10 +1440,8 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1339 | nr_mtrr_spare_reg = num_var_ranges - 1; | 1440 | nr_mtrr_spare_reg = num_var_ranges - 1; |
| 1340 | num_reg_good = -1; | 1441 | num_reg_good = -1; |
| 1341 | for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) { | 1442 | for (i = num_var_ranges - nr_mtrr_spare_reg; i > 0; i--) { |
| 1342 | if (!min_loss_pfn[i]) { | 1443 | if (!min_loss_pfn[i]) |
| 1343 | num_reg_good = i; | 1444 | num_reg_good = i; |
| 1344 | break; | ||
| 1345 | } | ||
| 1346 | } | 1445 | } |
| 1347 | 1446 | ||
| 1348 | index_good = -1; | 1447 | index_good = -1; |
| @@ -1358,21 +1457,26 @@ static int __init mtrr_cleanup(unsigned address_bits) | |||
| 1358 | } | 1457 | } |
| 1359 | 1458 | ||
| 1360 | if (index_good != -1) { | 1459 | if (index_good != -1) { |
| 1460 | char gran_factor, chunk_factor, lose_factor; | ||
| 1461 | unsigned long gran_base, chunk_base, lose_base; | ||
| 1462 | |||
| 1361 | printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); | 1463 | printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); |
| 1362 | i = index_good; | 1464 | i = index_good; |
| 1363 | printk(KERN_INFO "gran_size: %ldM \tchunk_size: %ldM \t", | 1465 | gran_base = to_size_factor(result[i].gran_sizek, &gran_factor), |
| 1364 | result[i].gran_sizek >> 10, | 1466 | chunk_base = to_size_factor(result[i].chunk_sizek, &chunk_factor), |
| 1365 | result[i].chunk_sizek >> 10); | 1467 | lose_base = to_size_factor(result[i].lose_cover_sizek, &lose_factor), |
| 1366 | printk(KERN_CONT "num_reg: %d \tlose RAM: %ldM\n", | 1468 | printk(KERN_INFO "gran_size: %ld%c \tchunk_size: %ld%c \t", |
| 1367 | result[i].num_reg, | 1469 | gran_base, gran_factor, chunk_base, chunk_factor); |
| 1368 | result[i].lose_cover_sizek >> 10); | 1470 | printk(KERN_CONT "num_reg: %d \tlose RAM: %ld%c\n", |
| 1471 | result[i].num_reg, lose_base, lose_factor); | ||
| 1369 | /* convert ranges to var ranges state */ | 1472 | /* convert ranges to var ranges state */ |
| 1370 | chunk_size = result[i].chunk_sizek; | 1473 | chunk_size = result[i].chunk_sizek; |
| 1371 | chunk_size <<= 10; | 1474 | chunk_size <<= 10; |
| 1372 | gran_size = result[i].gran_sizek; | 1475 | gran_size = result[i].gran_sizek; |
| 1373 | gran_size <<= 10; | 1476 | gran_size <<= 10; |
| 1374 | debug_print = 1; | 1477 | debug_print++; |
| 1375 | x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); | 1478 | x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); |
| 1479 | debug_print--; | ||
| 1376 | set_var_mtrr_all(address_bits); | 1480 | set_var_mtrr_all(address_bits); |
| 1377 | return 1; | 1481 | return 1; |
| 1378 | } | 1482 | } |
