diff options
Diffstat (limited to 'arch/ia64/kernel/efi.c')
-rw-r--r-- | arch/ia64/kernel/efi.c | 65 |
1 files changed, 62 insertions, 3 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index bb8770a177b5..9b96e7dbaf67 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/efi.h> | 28 | #include <linux/efi.h> |
29 | #include <linux/kexec.h> | ||
29 | 30 | ||
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | #include <asm/kregs.h> | 32 | #include <asm/kregs.h> |
@@ -41,7 +42,7 @@ extern efi_status_t efi_call_phys (void *, ...); | |||
41 | struct efi efi; | 42 | struct efi efi; |
42 | EXPORT_SYMBOL(efi); | 43 | EXPORT_SYMBOL(efi); |
43 | static efi_runtime_services_t *runtime; | 44 | static efi_runtime_services_t *runtime; |
44 | static unsigned long mem_limit = ~0UL, max_addr = ~0UL; | 45 | static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; |
45 | 46 | ||
46 | #define efi_call_virt(f, args...) (*(f))(args) | 47 | #define efi_call_virt(f, args...) (*(f))(args) |
47 | 48 | ||
@@ -421,6 +422,8 @@ efi_init (void) | |||
421 | mem_limit = memparse(cp + 4, &cp); | 422 | mem_limit = memparse(cp + 4, &cp); |
422 | } else if (memcmp(cp, "max_addr=", 9) == 0) { | 423 | } else if (memcmp(cp, "max_addr=", 9) == 0) { |
423 | max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); | 424 | max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); |
425 | } else if (memcmp(cp, "min_addr=", 9) == 0) { | ||
426 | min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); | ||
424 | } else { | 427 | } else { |
425 | while (*cp != ' ' && *cp) | 428 | while (*cp != ' ' && *cp) |
426 | ++cp; | 429 | ++cp; |
@@ -428,6 +431,8 @@ efi_init (void) | |||
428 | ++cp; | 431 | ++cp; |
429 | } | 432 | } |
430 | } | 433 | } |
434 | if (min_addr != 0UL) | ||
435 | printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); | ||
431 | if (max_addr != ~0UL) | 436 | if (max_addr != ~0UL) |
432 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); | 437 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); |
433 | 438 | ||
@@ -894,7 +899,8 @@ find_memmap_space (void) | |||
894 | as = max(contig_low, md->phys_addr); | 899 | as = max(contig_low, md->phys_addr); |
895 | ae = min(contig_high, efi_md_end(md)); | 900 | ae = min(contig_high, efi_md_end(md)); |
896 | 901 | ||
897 | /* keep within max_addr= command line arg */ | 902 | /* keep within max_addr= and min_addr= command line arg */ |
903 | as = max(as, min_addr); | ||
898 | ae = min(ae, max_addr); | 904 | ae = min(ae, max_addr); |
899 | if (ae <= as) | 905 | if (ae <= as) |
900 | continue; | 906 | continue; |
@@ -1004,7 +1010,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
1004 | } else | 1010 | } else |
1005 | ae = efi_md_end(md); | 1011 | ae = efi_md_end(md); |
1006 | 1012 | ||
1007 | /* keep within max_addr= command line arg */ | 1013 | /* keep within max_addr= and min_addr= command line arg */ |
1014 | as = max(as, min_addr); | ||
1008 | ae = min(ae, max_addr); | 1015 | ae = min(ae, max_addr); |
1009 | if (ae <= as) | 1016 | if (ae <= as) |
1010 | continue; | 1017 | continue; |
@@ -1116,6 +1123,58 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
1116 | */ | 1123 | */ |
1117 | insert_resource(res, code_resource); | 1124 | insert_resource(res, code_resource); |
1118 | insert_resource(res, data_resource); | 1125 | insert_resource(res, data_resource); |
1126 | #ifdef CONFIG_KEXEC | ||
1127 | insert_resource(res, &efi_memmap_res); | ||
1128 | insert_resource(res, &boot_param_res); | ||
1129 | if (crashk_res.end > crashk_res.start) | ||
1130 | insert_resource(res, &crashk_res); | ||
1131 | #endif | ||
1119 | } | 1132 | } |
1120 | } | 1133 | } |
1121 | } | 1134 | } |
1135 | |||
1136 | #ifdef CONFIG_KEXEC | ||
1137 | /* find a block of memory aligned to 64M exclude reserved regions | ||
1138 | rsvd_regions are sorted | ||
1139 | */ | ||
1140 | unsigned long | ||
1141 | kdump_find_rsvd_region (unsigned long size, | ||
1142 | struct rsvd_region *r, int n) | ||
1143 | { | ||
1144 | int i; | ||
1145 | u64 start, end; | ||
1146 | u64 alignment = 1UL << _PAGE_SIZE_64M; | ||
1147 | void *efi_map_start, *efi_map_end, *p; | ||
1148 | efi_memory_desc_t *md; | ||
1149 | u64 efi_desc_size; | ||
1150 | |||
1151 | efi_map_start = __va(ia64_boot_param->efi_memmap); | ||
1152 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | ||
1153 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | ||
1154 | |||
1155 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | ||
1156 | md = p; | ||
1157 | if (!efi_wb(md)) | ||
1158 | continue; | ||
1159 | start = ALIGN(md->phys_addr, alignment); | ||
1160 | end = efi_md_end(md); | ||
1161 | for (i = 0; i < n; i++) { | ||
1162 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { | ||
1163 | if (__pa(r[i].start) > start + size) | ||
1164 | return start; | ||
1165 | start = ALIGN(__pa(r[i].end), alignment); | ||
1166 | if (i < n-1 && __pa(r[i+1].start) < start + size) | ||
1167 | continue; | ||
1168 | else | ||
1169 | break; | ||
1170 | } | ||
1171 | } | ||
1172 | if (end > start + size) | ||
1173 | return start; | ||
1174 | } | ||
1175 | |||
1176 | printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", | ||
1177 | size); | ||
1178 | return ~0UL; | ||
1179 | } | ||
1180 | #endif | ||