diff options
author | Bernhard Walle <bwalle@suse.de> | 2008-06-27 07:12:55 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-08 11:55:42 -0400 |
commit | 5dfcf14d5b28174f94cbe9b4fb35d415db61c64a (patch) | |
tree | d5e6c47d8a635e07b3dfb3c115f8cae34fc7c553 /arch/x86/kernel/e820.c | |
parent | 69ac9cd629ca96e59f34eb4ccd12d00b2c8276a7 (diff) |
x86: use FIRMWARE_MEMMAP on x86/E820
This patch uses the /sys/firmware/memmap interface provided in the last patch
on the x86 architecture when E820 is used. The patch copies the E820
memory map very early, and registers the E820 map afterwards via
firmware_map_add_early().
Signed-off-by: Bernhard Walle <bwalle@suse.de>
Acked-by: Greg KH <gregkh@suse.de>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Cc: kexec@lists.infradead.org
Cc: yhlu.kernel@gmail.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/e820.c')
-rw-r--r-- | arch/x86/kernel/e820.c | 44 |
1 files changed, 37 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 | } |