diff options
| -rw-r--r-- | arch/x86/kernel/cpu/mtrr/main.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index aff46b99ff01..bccf57f5b615 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c | |||
| @@ -992,22 +992,17 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
| 992 | /* only cut back, when it is not the last */ | 992 | /* only cut back, when it is not the last */ |
| 993 | if (sizek) { | 993 | if (sizek) { |
| 994 | while (range0_basek + range0_sizek > (basek + sizek)) { | 994 | while (range0_basek + range0_sizek > (basek + sizek)) { |
| 995 | range0_sizek -= chunk_sizek; | 995 | if (range0_sizek >= chunk_sizek) |
| 996 | range0_sizek -= chunk_sizek; | ||
| 997 | else | ||
| 998 | range0_sizek = 0; | ||
| 999 | |||
| 996 | if (!range0_sizek) | 1000 | if (!range0_sizek) |
| 997 | break; | 1001 | break; |
| 998 | } | 1002 | } |
| 999 | } | 1003 | } |
| 1000 | 1004 | ||
| 1001 | if (range0_sizek) { | 1005 | second_try: |
| 1002 | if (debug_print) | ||
| 1003 | printk(KERN_DEBUG "range0: %016lx - %016lx\n", | ||
| 1004 | range0_basek<<10, | ||
| 1005 | (range0_basek + range0_sizek)<<10); | ||
| 1006 | state->reg = range_to_mtrr(state->reg, range0_basek, | ||
| 1007 | range0_sizek, MTRR_TYPE_WRBACK); | ||
| 1008 | |||
| 1009 | } | ||
| 1010 | |||
| 1011 | range_basek = range0_basek + range0_sizek; | 1006 | range_basek = range0_basek + range0_sizek; |
| 1012 | 1007 | ||
| 1013 | /* one hole in the middle */ | 1008 | /* one hole in the middle */ |
| @@ -1015,33 +1010,50 @@ range_to_mtrr_with_hole(struct var_mtrr_state *state, unsigned long basek, | |||
| 1015 | second_sizek = range_basek - basek; | 1010 | second_sizek = range_basek - basek; |
| 1016 | 1011 | ||
| 1017 | if (range0_sizek > state->range_sizek) { | 1012 | if (range0_sizek > state->range_sizek) { |
| 1018 | unsigned long hole_basek, hole_sizek; | ||
| 1019 | 1013 | ||
| 1020 | /* one hole in middle or at end */ | 1014 | /* one hole in middle or at end */ |
| 1021 | hole_sizek = range0_sizek - state->range_sizek - second_sizek; | 1015 | hole_sizek = range0_sizek - state->range_sizek - second_sizek; |
| 1022 | if (hole_sizek) { | 1016 | |
| 1023 | hole_basek = range_basek - hole_sizek - second_sizek; | 1017 | /* hole size should be less than half of range0 size */ |
| 1024 | if (debug_print) | 1018 | if (hole_sizek > (range0_sizek >> 1) && |
| 1025 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", | 1019 | range0_sizek >= chunk_sizek) { |
| 1026 | hole_basek<<10, | 1020 | range0_sizek -= chunk_sizek; |
| 1027 | (hole_basek + hole_sizek)<<10); | 1021 | second_sizek = 0; |
| 1028 | state->reg = range_to_mtrr(state->reg, hole_basek, | 1022 | hole_sizek = 0; |
| 1029 | hole_sizek, | 1023 | |
| 1030 | MTRR_TYPE_UNCACHABLE); | 1024 | goto second_try; |
| 1031 | } | 1025 | } |
| 1032 | } else { | 1026 | } |
| 1027 | |||
| 1028 | if (range0_sizek) { | ||
| 1029 | if (debug_print) | ||
| 1030 | printk(KERN_DEBUG "range0: %016lx - %016lx\n", | ||
| 1031 | range0_basek<<10, | ||
| 1032 | (range0_basek + range0_sizek)<<10); | ||
| 1033 | state->reg = range_to_mtrr(state->reg, range0_basek, | ||
| 1034 | range0_sizek, MTRR_TYPE_WRBACK); | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | if (range0_sizek < state->range_sizek) { | ||
| 1033 | /* need to handle left over */ | 1038 | /* need to handle left over */ |
| 1034 | range_sizek = state->range_sizek - range0_sizek; | 1039 | range_sizek = state->range_sizek - range0_sizek; |
| 1035 | 1040 | ||
| 1036 | if (range_sizek) { | 1041 | if (debug_print) |
| 1037 | if (debug_print) | 1042 | printk(KERN_DEBUG "range: %016lx - %016lx\n", |
| 1038 | printk(KERN_DEBUG "range: %016lx - %016lx\n", | 1043 | range_basek<<10, |
| 1039 | range_basek<<10, | 1044 | (range_basek + range_sizek)<<10); |
| 1040 | (range_basek + range_sizek)<<10); | 1045 | state->reg = range_to_mtrr(state->reg, range_basek, |
| 1041 | state->reg = range_to_mtrr(state->reg, range_basek, | 1046 | range_sizek, MTRR_TYPE_WRBACK); |
| 1042 | range_sizek, | 1047 | } |
| 1043 | MTRR_TYPE_WRBACK); | 1048 | |
| 1044 | } | 1049 | if (hole_sizek) { |
| 1050 | hole_basek = range_basek - hole_sizek - second_sizek; | ||
| 1051 | if (debug_print) | ||
| 1052 | printk(KERN_DEBUG "hole: %016lx - %016lx\n", | ||
| 1053 | hole_basek<<10, | ||
| 1054 | (hole_basek + hole_sizek)<<10); | ||
| 1055 | state->reg = range_to_mtrr(state->reg, hole_basek, | ||
| 1056 | hole_sizek, MTRR_TYPE_UNCACHABLE); | ||
| 1045 | } | 1057 | } |
| 1046 | 1058 | ||
| 1047 | return second_sizek; | 1059 | return second_sizek; |
