diff options
-rw-r--r-- | arch/x86/kernel/e820.c | 44 | ||||
-rw-r--r-- | include/asm-x86/e820.h | 2 |
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 | */ | ||
30 | struct e820map e820; | 45 | struct e820map e820; |
46 | struct e820map e820_saved; | ||
31 | 47 | ||
32 | /* For PCI or other memory-mapped resources */ | 48 | /* For PCI or other memory-mapped resources */ |
33 | unsigned long pci_mem_start = 0xaeedbabe; | 49 | unsigned long pci_mem_start = 0xaeedbabe; |
@@ -1198,6 +1214,17 @@ void __init finish_e820_parsing(void) | |||
1198 | } | 1214 | } |
1199 | } | 1215 | } |
1200 | 1216 | ||
1217 | static 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 | ||
1235 | char *__init default_machine_specific_memory_setup(void) | 1263 | char *__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 */ | ||
62 | extern struct e820map e820; | 63 | extern struct e820map e820; |
64 | extern struct e820map e820_saved; | ||
63 | 65 | ||
64 | extern int e820_any_mapped(u64 start, u64 end, unsigned type); | 66 | extern int e820_any_mapped(u64 start, u64 end, unsigned type); |
65 | extern int e820_all_mapped(u64 start, u64 end, unsigned type); | 67 | extern int e820_all_mapped(u64 start, u64 end, unsigned type); |