aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/e820.c44
-rw-r--r--include/asm-x86/e820.h2
2 files changed, 39 insertions, 7 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index d0335853ff52..fc1d579f212b 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -19,6 +19,7 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/pfn.h> 20#include <linux/pfn.h>
21#include <linux/suspend.h> 21#include <linux/suspend.h>
22#include <linux/firmware-map.h>
22 23
23#include <asm/pgtable.h> 24#include <asm/pgtable.h>
24#include <asm/page.h> 25#include <asm/page.h>
@@ -27,7 +28,22 @@
27#include <asm/setup.h> 28#include <asm/setup.h>
28#include <asm/trampoline.h> 29#include <asm/trampoline.h>
29 30
31/*
32 * The e820 map is the map that gets modified e.g. with command line parameters
33 * and that is also registered with modifications in the kernel resource tree
34 * with the iomem_resource as parent.
35 *
36 * The e820_saved is directly saved after the BIOS-provided memory map is
37 * copied. It doesn't get modified afterwards. It's registered for the
38 * /sys/firmware/memmap interface.
39 *
40 * That memory map is not modified and is used as base for kexec. The kexec'd
41 * kernel should get the same memory map as the firmware provides. Then the
42 * user can e.g. boot the original kernel with mem=1G while still booting the
43 * next kernel with full memory.
44 */
30struct e820map e820; 45struct e820map e820;
46struct e820map e820_saved;
31 47
32/* For PCI or other memory-mapped resources */ 48/* For PCI or other memory-mapped resources */
33unsigned long pci_mem_start = 0xaeedbabe; 49unsigned long pci_mem_start = 0xaeedbabe;
@@ -1198,6 +1214,17 @@ void __init finish_e820_parsing(void)
1198 } 1214 }
1199} 1215}
1200 1216
1217static inline const char *e820_type_to_string(int e820_type)
1218{
1219 switch (e820_type) {
1220 case E820_RESERVED_KERN:
1221 case E820_RAM: return "System RAM";
1222 case E820_ACPI: return "ACPI Tables";
1223 case E820_NVS: return "ACPI Non-volatile Storage";
1224 default: return "reserved";
1225 }
1226}
1227
1201/* 1228/*
1202 * Mark e820 reserved areas as busy for the resource manager. 1229 * Mark e820 reserved areas as busy for the resource manager.
1203 */ 1230 */
@@ -1209,13 +1236,6 @@ void __init e820_reserve_resources(void)
1209 1236
1210 res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map); 1237 res = alloc_bootmem_low(sizeof(struct resource) * e820.nr_map);
1211 for (i = 0; i < e820.nr_map; i++) { 1238 for (i = 0; i < e820.nr_map; i++) {
1212 switch (e820.map[i].type) {
1213 case E820_RESERVED_KERN:
1214 case E820_RAM: res->name = "System RAM"; break;
1215 case E820_ACPI: res->name = "ACPI Tables"; break;
1216 case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
1217 default: res->name = "reserved";
1218 }
1219 end = e820.map[i].addr + e820.map[i].size - 1; 1239 end = e820.map[i].addr + e820.map[i].size - 1;
1220#ifndef CONFIG_RESOURCES_64BIT 1240#ifndef CONFIG_RESOURCES_64BIT
1221 if (end > 0x100000000ULL) { 1241 if (end > 0x100000000ULL) {
@@ -1223,6 +1243,7 @@ void __init e820_reserve_resources(void)
1223 continue; 1243 continue;
1224 } 1244 }
1225#endif 1245#endif
1246 res->name = e820_type_to_string(e820.map[i].type);
1226 res->start = e820.map[i].addr; 1247 res->start = e820.map[i].addr;
1227 res->end = end; 1248 res->end = end;
1228 1249
@@ -1230,6 +1251,13 @@ void __init e820_reserve_resources(void)
1230 insert_resource(&iomem_resource, res); 1251 insert_resource(&iomem_resource, res);
1231 res++; 1252 res++;
1232 } 1253 }
1254
1255 for (i = 0; i < e820_saved.nr_map; i++) {
1256 struct e820entry *entry = &e820_saved.map[i];
1257 firmware_map_add_early(entry->addr,
1258 entry->addr + entry->size - 1,
1259 e820_type_to_string(entry->type));
1260 }
1233} 1261}
1234 1262
1235char *__init default_machine_specific_memory_setup(void) 1263char *__init default_machine_specific_memory_setup(void)
@@ -1266,6 +1294,8 @@ char *__init default_machine_specific_memory_setup(void)
1266 e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM); 1294 e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
1267 } 1295 }
1268 1296
1297 memcpy(&e820_saved, &e820, sizeof(struct e820map));
1298
1269 /* In case someone cares... */ 1299 /* In case someone cares... */
1270 return who; 1300 return who;
1271} 1301}
diff --git a/include/asm-x86/e820.h b/include/asm-x86/e820.h
index 4b26604b3c19..a20d0a7f5892 100644
--- a/include/asm-x86/e820.h
+++ b/include/asm-x86/e820.h
@@ -59,7 +59,9 @@ struct e820map {
59 struct e820entry map[E820_X_MAX]; 59 struct e820entry map[E820_X_MAX];
60}; 60};
61 61
62/* see comment in arch/x86/kernel/e820.c */
62extern struct e820map e820; 63extern struct e820map e820;
64extern struct e820map e820_saved;
63 65
64extern int e820_any_mapped(u64 start, u64 end, unsigned type); 66extern int e820_any_mapped(u64 start, u64 end, unsigned type);
65extern int e820_all_mapped(u64 start, u64 end, unsigned type); 67extern int e820_all_mapped(u64 start, u64 end, unsigned type);