diff options
-rw-r--r-- | arch/x86/include/asm/e820/api.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/e820.c | 31 | ||||
-rw-r--r-- | arch/x86/power/hibernate_64.c | 4 |
3 files changed, 29 insertions, 7 deletions
diff --git a/arch/x86/include/asm/e820/api.h b/arch/x86/include/asm/e820/api.h index a688095421ab..a504adc661a4 100644 --- a/arch/x86/include/asm/e820/api.h +++ b/arch/x86/include/asm/e820/api.h | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | extern struct e820_table *e820_table; | 6 | extern struct e820_table *e820_table; |
7 | extern struct e820_table *e820_table_kexec; | 7 | extern struct e820_table *e820_table_kexec; |
8 | extern struct e820_table *e820_table_firmware; | ||
8 | 9 | ||
9 | extern unsigned long pci_mem_start; | 10 | extern unsigned long pci_mem_start; |
10 | 11 | ||
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 591019031e23..532da61d605c 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c | |||
@@ -20,10 +20,12 @@ | |||
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | 21 | ||
22 | /* | 22 | /* |
23 | * We organize the E820 table into two main data structures: | 23 | * We organize the E820 table into three main data structures: |
24 | * | 24 | * |
25 | * - 'e820_table_kexec': the original firmware version passed to us by the | 25 | * - 'e820_table_firmware': the original firmware version passed to us by the |
26 | * bootloader - not modified by the kernel. We use this to: | 26 | * bootloader - not modified by the kernel. It is composed of two parts: |
27 | * the first 128 E820 memory entries in boot_params.e820_table and the remaining | ||
28 | * (if any) entries of the SETUP_E820_EXT nodes. We use this to: | ||
27 | * | 29 | * |
28 | * - inform the user about the firmware's notion of memory layout | 30 | * - inform the user about the firmware's notion of memory layout |
29 | * via /sys/firmware/memmap | 31 | * via /sys/firmware/memmap |
@@ -31,6 +33,14 @@ | |||
31 | * - the hibernation code uses it to generate a kernel-independent MD5 | 33 | * - the hibernation code uses it to generate a kernel-independent MD5 |
32 | * fingerprint of the physical memory layout of a system. | 34 | * fingerprint of the physical memory layout of a system. |
33 | * | 35 | * |
36 | * - 'e820_table_kexec': a slightly modified (by the kernel) firmware version | ||
37 | * passed to us by the bootloader - the major difference between | ||
38 | * e820_table_firmware[] and this one is that, the latter marks the setup_data | ||
39 | * list created by the EFI boot stub as reserved, so that kexec can reuse the | ||
40 | * setup_data information in the second kernel. Besides, e820_table_kexec[] | ||
41 | * might also be modified by the kexec itself to fake a mptable. | ||
42 | * We use this to: | ||
43 | * | ||
34 | * - kexec, which is a bootloader in disguise, uses the original E820 | 44 | * - kexec, which is a bootloader in disguise, uses the original E820 |
35 | * layout to pass to the kexec-ed kernel. This way the original kernel | 45 | * layout to pass to the kexec-ed kernel. This way the original kernel |
36 | * can have a restricted E820 map while the kexec()-ed kexec-kernel | 46 | * can have a restricted E820 map while the kexec()-ed kexec-kernel |
@@ -47,9 +57,11 @@ | |||
47 | */ | 57 | */ |
48 | static struct e820_table e820_table_init __initdata; | 58 | static struct e820_table e820_table_init __initdata; |
49 | static struct e820_table e820_table_kexec_init __initdata; | 59 | static struct e820_table e820_table_kexec_init __initdata; |
60 | static struct e820_table e820_table_firmware_init __initdata; | ||
50 | 61 | ||
51 | struct e820_table *e820_table __refdata = &e820_table_init; | 62 | struct e820_table *e820_table __refdata = &e820_table_init; |
52 | struct e820_table *e820_table_kexec __refdata = &e820_table_kexec_init; | 63 | struct e820_table *e820_table_kexec __refdata = &e820_table_kexec_init; |
64 | struct e820_table *e820_table_firmware __refdata = &e820_table_firmware_init; | ||
53 | 65 | ||
54 | /* For PCI or other memory-mapped resources */ | 66 | /* For PCI or other memory-mapped resources */ |
55 | unsigned long pci_mem_start = 0xaeedbabe; | 67 | unsigned long pci_mem_start = 0xaeedbabe; |
@@ -648,6 +660,12 @@ __init void e820__reallocate_tables(void) | |||
648 | BUG_ON(!n); | 660 | BUG_ON(!n); |
649 | memcpy(n, e820_table_kexec, size); | 661 | memcpy(n, e820_table_kexec, size); |
650 | e820_table_kexec = n; | 662 | e820_table_kexec = n; |
663 | |||
664 | size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_firmware->nr_entries; | ||
665 | n = kmalloc(size, GFP_KERNEL); | ||
666 | BUG_ON(!n); | ||
667 | memcpy(n, e820_table_firmware, size); | ||
668 | e820_table_firmware = n; | ||
651 | } | 669 | } |
652 | 670 | ||
653 | /* | 671 | /* |
@@ -670,6 +688,7 @@ void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len) | |||
670 | e820__update_table(e820_table); | 688 | e820__update_table(e820_table); |
671 | 689 | ||
672 | memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec)); | 690 | memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec)); |
691 | memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware)); | ||
673 | 692 | ||
674 | early_memunmap(sdata, data_len); | 693 | early_memunmap(sdata, data_len); |
675 | pr_info("e820: extended physical RAM map:\n"); | 694 | pr_info("e820: extended physical RAM map:\n"); |
@@ -1064,8 +1083,9 @@ void __init e820__reserve_resources(void) | |||
1064 | res++; | 1083 | res++; |
1065 | } | 1084 | } |
1066 | 1085 | ||
1067 | for (i = 0; i < e820_table_kexec->nr_entries; i++) { | 1086 | /* Expose the bootloader-provided memory layout to the sysfs. */ |
1068 | struct e820_entry *entry = e820_table_kexec->entries + i; | 1087 | for (i = 0; i < e820_table_firmware->nr_entries; i++) { |
1088 | struct e820_entry *entry = e820_table_firmware->entries + i; | ||
1069 | 1089 | ||
1070 | firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry)); | 1090 | firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry)); |
1071 | } | 1091 | } |
@@ -1178,6 +1198,7 @@ void __init e820__memory_setup(void) | |||
1178 | who = x86_init.resources.memory_setup(); | 1198 | who = x86_init.resources.memory_setup(); |
1179 | 1199 | ||
1180 | memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec)); | 1200 | memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec)); |
1201 | memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware)); | ||
1181 | 1202 | ||
1182 | pr_info("e820: BIOS-provided physical RAM map:\n"); | 1203 | pr_info("e820: BIOS-provided physical RAM map:\n"); |
1183 | e820__print_table(who); | 1204 | e820__print_table(who); |
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index 3ba161a08d6e..e3e62c8a8e70 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c | |||
@@ -251,7 +251,7 @@ static int get_e820_md5(struct e820_table *table, void *buf) | |||
251 | 251 | ||
252 | static void hibernation_e820_save(void *buf) | 252 | static void hibernation_e820_save(void *buf) |
253 | { | 253 | { |
254 | get_e820_md5(e820_table_kexec, buf); | 254 | get_e820_md5(e820_table_firmware, buf); |
255 | } | 255 | } |
256 | 256 | ||
257 | static bool hibernation_e820_mismatch(void *buf) | 257 | static bool hibernation_e820_mismatch(void *buf) |
@@ -264,7 +264,7 @@ static bool hibernation_e820_mismatch(void *buf) | |||
264 | if (!memcmp(result, buf, MD5_DIGEST_SIZE)) | 264 | if (!memcmp(result, buf, MD5_DIGEST_SIZE)) |
265 | return false; | 265 | return false; |
266 | 266 | ||
267 | ret = get_e820_md5(e820_table_kexec, result); | 267 | ret = get_e820_md5(e820_table_firmware, result); |
268 | if (ret) | 268 | if (ret) |
269 | return true; | 269 | return true; |
270 | 270 | ||