diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/e820.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 7053f4adb8ed..e09c18c8f3c1 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -916,6 +916,48 @@ void __init reserve_early_overlap_ok(u64 start, u64 end, char *name) | |||
916 | __reserve_early(start, end, name, 1); | 916 | __reserve_early(start, end, name, 1); |
917 | } | 917 | } |
918 | 918 | ||
919 | static void __init __check_and_double_early_res(u64 start) | ||
920 | { | ||
921 | u64 end, size, mem; | ||
922 | struct early_res *new; | ||
923 | |||
924 | /* do we have enough slots left ? */ | ||
925 | if ((max_early_res - early_res_count) > max(max_early_res/8, 2)) | ||
926 | return; | ||
927 | |||
928 | /* double it */ | ||
929 | end = max_pfn_mapped << PAGE_SHIFT; | ||
930 | size = sizeof(struct early_res) * max_early_res * 2; | ||
931 | mem = find_e820_area(start, end, size, sizeof(struct early_res)); | ||
932 | |||
933 | if (mem == -1ULL) | ||
934 | panic("can not find more space for early_res array"); | ||
935 | |||
936 | new = __va(mem); | ||
937 | /* save the first one for own */ | ||
938 | new[0].start = mem; | ||
939 | new[0].end = mem + size; | ||
940 | new[0].overlap_ok = 0; | ||
941 | /* copy old to new */ | ||
942 | if (early_res == early_res_x) { | ||
943 | memcpy(&new[1], &early_res[0], | ||
944 | sizeof(struct early_res) * max_early_res); | ||
945 | memset(&new[max_early_res+1], 0, | ||
946 | sizeof(struct early_res) * (max_early_res - 1)); | ||
947 | early_res_count++; | ||
948 | } else { | ||
949 | memcpy(&new[1], &early_res[1], | ||
950 | sizeof(struct early_res) * (max_early_res - 1)); | ||
951 | memset(&new[max_early_res], 0, | ||
952 | sizeof(struct early_res) * max_early_res); | ||
953 | } | ||
954 | memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res); | ||
955 | early_res = new; | ||
956 | max_early_res *= 2; | ||
957 | printk(KERN_DEBUG "early_res array is doubled to %d at [%llx - %llx]\n", | ||
958 | max_early_res, mem, mem + size - 1); | ||
959 | } | ||
960 | |||
919 | /* | 961 | /* |
920 | * Most early reservations come here. | 962 | * Most early reservations come here. |
921 | * | 963 | * |
@@ -929,6 +971,8 @@ void __init reserve_early(u64 start, u64 end, char *name) | |||
929 | if (start >= end) | 971 | if (start >= end) |
930 | return; | 972 | return; |
931 | 973 | ||
974 | __check_and_double_early_res(end); | ||
975 | |||
932 | drop_overlaps_that_are_ok(start, end); | 976 | drop_overlaps_that_are_ok(start, end); |
933 | __reserve_early(start, end, name, 0); | 977 | __reserve_early(start, end, name, 0); |
934 | } | 978 | } |
@@ -957,6 +1001,10 @@ void __init early_res_to_bootmem(u64 start, u64 end) | |||
957 | for (i = 0; i < max_early_res && early_res[i].end; i++) | 1001 | for (i = 0; i < max_early_res && early_res[i].end; i++) |
958 | count++; | 1002 | count++; |
959 | 1003 | ||
1004 | /* need to skip first one ?*/ | ||
1005 | if (early_res != early_res_x) | ||
1006 | idx = 1; | ||
1007 | |||
960 | printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n", | 1008 | printk(KERN_INFO "(%d/%d early reservations) ==> bootmem [%010llx - %010llx]\n", |
961 | count - idx, max_early_res, start, end); | 1009 | count - idx, max_early_res, start, end); |
962 | for (i = idx; i < count; i++) { | 1010 | for (i = idx; i < count; i++) { |
@@ -974,6 +1022,11 @@ void __init early_res_to_bootmem(u64 start, u64 end) | |||
974 | reserve_bootmem_generic(final_start, final_end - final_start, | 1022 | reserve_bootmem_generic(final_start, final_end - final_start, |
975 | BOOTMEM_DEFAULT); | 1023 | BOOTMEM_DEFAULT); |
976 | } | 1024 | } |
1025 | /* clear them */ | ||
1026 | memset(&early_res[0], 0, sizeof(struct early_res) * max_early_res); | ||
1027 | early_res = NULL; | ||
1028 | max_early_res = 0; | ||
1029 | early_res_count = 0; | ||
977 | } | 1030 | } |
978 | 1031 | ||
979 | /* Check for already reserved areas */ | 1032 | /* Check for already reserved areas */ |