hc
2024-09-20 a36159eec6ca17402b0e146b86efaf76568dc353
kernel/arch/x86/kernel/e820.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Low level x86 E820 memory map handling functions.
34 *
....@@ -9,12 +10,12 @@
910 * allocation code routines via a platform independent interface (memblock, etc.).
1011 */
1112 #include <linux/crash_dump.h>
12
-#include <linux/bootmem.h>
13
+#include <linux/memblock.h>
1314 #include <linux/suspend.h>
1415 #include <linux/acpi.h>
1516 #include <linux/firmware-map.h>
16
-#include <linux/memblock.h>
1717 #include <linux/sort.h>
18
+#include <linux/memory_hotplug.h>
1819
1920 #include <asm/e820/api.h>
2021 #include <asm/setup.h>
....@@ -30,8 +31,8 @@
3031 * - inform the user about the firmware's notion of memory layout
3132 * via /sys/firmware/memmap
3233 *
33
- * - the hibernation code uses it to generate a kernel-independent MD5
34
- * fingerprint of the physical memory layout of a system.
34
+ * - the hibernation code uses it to generate a kernel-independent CRC32
35
+ * checksum of the physical memory layout of a system.
3536 *
3637 * - 'e820_table_kexec': a slightly modified (by the kernel) firmware version
3738 * passed to us by the bootloader - the major difference between
....@@ -73,20 +74,32 @@
7374 * This function checks if any part of the range <start,end> is mapped
7475 * with type.
7576 */
76
-bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
77
+static bool _e820__mapped_any(struct e820_table *table,
78
+ u64 start, u64 end, enum e820_type type)
7779 {
7880 int i;
7981
80
- for (i = 0; i < e820_table->nr_entries; i++) {
81
- struct e820_entry *entry = &e820_table->entries[i];
82
+ for (i = 0; i < table->nr_entries; i++) {
83
+ struct e820_entry *entry = &table->entries[i];
8284
8385 if (type && entry->type != type)
8486 continue;
8587 if (entry->addr >= end || entry->addr + entry->size <= start)
8688 continue;
87
- return 1;
89
+ return true;
8890 }
89
- return 0;
91
+ return false;
92
+}
93
+
94
+bool e820__mapped_raw_any(u64 start, u64 end, enum e820_type type)
95
+{
96
+ return _e820__mapped_any(e820_table_firmware, start, end, type);
97
+}
98
+EXPORT_SYMBOL_GPL(e820__mapped_raw_any);
99
+
100
+bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
101
+{
102
+ return _e820__mapped_any(e820_table, start, end, type);
90103 }
91104 EXPORT_SYMBOL_GPL(e820__mapped_any);
92105
....@@ -177,6 +190,7 @@
177190 case E820_TYPE_RAM: /* Fall through: */
178191 case E820_TYPE_RESERVED_KERN: pr_cont("usable"); break;
179192 case E820_TYPE_RESERVED: pr_cont("reserved"); break;
193
+ case E820_TYPE_SOFT_RESERVED: pr_cont("soft reserved"); break;
180194 case E820_TYPE_ACPI: pr_cont("ACPI data"); break;
181195 case E820_TYPE_NVS: pr_cont("ACPI NVS"); break;
182196 case E820_TYPE_UNUSABLE: pr_cont("unusable"); break;
....@@ -291,6 +305,20 @@
291305 return (ap->addr != ap->entry->addr) - (bp->addr != bp->entry->addr);
292306 }
293307
308
+static bool e820_nomerge(enum e820_type type)
309
+{
310
+ /*
311
+ * These types may indicate distinct platform ranges aligned to
312
+ * numa node, protection domain, performance domain, or other
313
+ * boundaries. Do not merge them.
314
+ */
315
+ if (type == E820_TYPE_PRAM)
316
+ return true;
317
+ if (type == E820_TYPE_SOFT_RESERVED)
318
+ return true;
319
+ return false;
320
+}
321
+
294322 int __init e820__update_table(struct e820_table *table)
295323 {
296324 struct e820_entry *entries = table->entries;
....@@ -366,7 +394,7 @@
366394 }
367395
368396 /* Continue building up new map based on this information: */
369
- if (current_type != last_type || current_type == E820_TYPE_PRAM) {
397
+ if (current_type != last_type || e820_nomerge(current_type)) {
370398 if (last_type != 0) {
371399 new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr;
372400 /* Move forward only if the new size was non-zero: */
....@@ -672,21 +700,18 @@
672700 int size;
673701
674702 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table->nr_entries;
675
- n = kmalloc(size, GFP_KERNEL);
703
+ n = kmemdup(e820_table, size, GFP_KERNEL);
676704 BUG_ON(!n);
677
- memcpy(n, e820_table, size);
678705 e820_table = n;
679706
680707 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_kexec->nr_entries;
681
- n = kmalloc(size, GFP_KERNEL);
708
+ n = kmemdup(e820_table_kexec, size, GFP_KERNEL);
682709 BUG_ON(!n);
683
- memcpy(n, e820_table_kexec, size);
684710 e820_table_kexec = n;
685711
686712 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_firmware->nr_entries;
687
- n = kmalloc(size, GFP_KERNEL);
713
+ n = kmemdup(e820_table_firmware, size, GFP_KERNEL);
688714 BUG_ON(!n);
689
- memcpy(n, e820_table_firmware, size);
690715 e820_table_firmware = n;
691716 }
692717
....@@ -779,7 +804,7 @@
779804 {
780805 u64 addr;
781806
782
- addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
807
+ addr = memblock_phys_alloc(size, align);
783808 if (addr) {
784809 e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
785810 pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n");
....@@ -882,6 +907,10 @@
882907
883908 e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
884909
910
+#ifdef CONFIG_MEMORY_HOTPLUG
911
+ max_mem_size = mem_size;
912
+#endif
913
+
885914 return 0;
886915 }
887916 early_param("mem", parse_memopt);
....@@ -895,14 +924,6 @@
895924 return -EINVAL;
896925
897926 if (!strncmp(p, "exactmap", 8)) {
898
-#ifdef CONFIG_CRASH_DUMP
899
- /*
900
- * If we are doing a crash dump, we still need to know
901
- * the real memory size before the original memory map is
902
- * reset.
903
- */
904
- saved_max_pfn = e820__end_of_ram_pfn();
905
-#endif
906927 e820_table->nr_entries = 0;
907928 userdef = 1;
908929 return 0;
....@@ -974,8 +995,10 @@
974995 */
975996 void __init e820__reserve_setup_data(void)
976997 {
998
+ struct setup_indirect *indirect;
977999 struct setup_data *data;
978
- u64 pa_data;
1000
+ u64 pa_data, pa_next;
1001
+ u32 len;
9791002
9801003 pa_data = boot_params.hdr.setup_data;
9811004 if (!pa_data)
....@@ -983,10 +1006,46 @@
9831006
9841007 while (pa_data) {
9851008 data = early_memremap(pa_data, sizeof(*data));
1009
+ if (!data) {
1010
+ pr_warn("e820: failed to memremap setup_data entry\n");
1011
+ return;
1012
+ }
1013
+
1014
+ len = sizeof(*data);
1015
+ pa_next = data->next;
1016
+
9861017 e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
987
- e820__range_update_kexec(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
988
- pa_data = data->next;
989
- early_memunmap(data, sizeof(*data));
1018
+
1019
+ /*
1020
+ * SETUP_EFI is supplied by kexec and does not need to be
1021
+ * reserved.
1022
+ */
1023
+ if (data->type != SETUP_EFI)
1024
+ e820__range_update_kexec(pa_data,
1025
+ sizeof(*data) + data->len,
1026
+ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1027
+
1028
+ if (data->type == SETUP_INDIRECT) {
1029
+ len += data->len;
1030
+ early_memunmap(data, sizeof(*data));
1031
+ data = early_memremap(pa_data, len);
1032
+ if (!data) {
1033
+ pr_warn("e820: failed to memremap indirect setup_data\n");
1034
+ return;
1035
+ }
1036
+
1037
+ indirect = (struct setup_indirect *)data->data;
1038
+
1039
+ if (indirect->type != SETUP_INDIRECT) {
1040
+ e820__range_update(indirect->addr, indirect->len,
1041
+ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1042
+ e820__range_update_kexec(indirect->addr, indirect->len,
1043
+ E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1044
+ }
1045
+ }
1046
+
1047
+ pa_data = pa_next;
1048
+ early_memunmap(data, len);
9901049 }
9911050
9921051 e820__update_table(e820_table);
....@@ -1023,6 +1082,7 @@
10231082 case E820_TYPE_PRAM: return "Persistent Memory (legacy)";
10241083 case E820_TYPE_PMEM: return "Persistent Memory";
10251084 case E820_TYPE_RESERVED: return "Reserved";
1085
+ case E820_TYPE_SOFT_RESERVED: return "Soft Reserved";
10261086 default: return "Unknown E820 type";
10271087 }
10281088 }
....@@ -1038,6 +1098,7 @@
10381098 case E820_TYPE_PRAM: /* Fall-through: */
10391099 case E820_TYPE_PMEM: /* Fall-through: */
10401100 case E820_TYPE_RESERVED: /* Fall-through: */
1101
+ case E820_TYPE_SOFT_RESERVED: /* Fall-through: */
10411102 default: return IORESOURCE_MEM;
10421103 }
10431104 }
....@@ -1049,10 +1110,11 @@
10491110 case E820_TYPE_NVS: return IORES_DESC_ACPI_NV_STORAGE;
10501111 case E820_TYPE_PMEM: return IORES_DESC_PERSISTENT_MEMORY;
10511112 case E820_TYPE_PRAM: return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
1113
+ case E820_TYPE_RESERVED: return IORES_DESC_RESERVED;
1114
+ case E820_TYPE_SOFT_RESERVED: return IORES_DESC_SOFT_RESERVED;
10521115 case E820_TYPE_RESERVED_KERN: /* Fall-through: */
10531116 case E820_TYPE_RAM: /* Fall-through: */
10541117 case E820_TYPE_UNUSABLE: /* Fall-through: */
1055
- case E820_TYPE_RESERVED: /* Fall-through: */
10561118 default: return IORES_DESC_NONE;
10571119 }
10581120 }
....@@ -1064,11 +1126,12 @@
10641126 return true;
10651127
10661128 /*
1067
- * Treat persistent memory like device memory, i.e. reserve it
1068
- * for exclusive use of a driver
1129
+ * Treat persistent memory and other special memory ranges like
1130
+ * device memory, i.e. reserve it for exclusive use of a driver
10691131 */
10701132 switch (type) {
10711133 case E820_TYPE_RESERVED:
1134
+ case E820_TYPE_SOFT_RESERVED:
10721135 case E820_TYPE_PRAM:
10731136 case E820_TYPE_PMEM:
10741137 return false;
....@@ -1094,7 +1157,11 @@
10941157 struct resource *res;
10951158 u64 end;
10961159
1097
- res = alloc_bootmem(sizeof(*res) * e820_table->nr_entries);
1160
+ res = memblock_alloc(sizeof(*res) * e820_table->nr_entries,
1161
+ SMP_CACHE_BYTES);
1162
+ if (!res)
1163
+ panic("%s: Failed to allocate %zu bytes\n", __func__,
1164
+ sizeof(*res) * e820_table->nr_entries);
10981165 e820_res = res;
10991166
11001167 for (i = 0; i < e820_table->nr_entries; i++) {
....@@ -1267,6 +1334,9 @@
12671334 if (end != (resource_size_t)end)
12681335 continue;
12691336
1337
+ if (entry->type == E820_TYPE_SOFT_RESERVED)
1338
+ memblock_reserve(entry->addr, entry->size);
1339
+
12701340 if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
12711341 continue;
12721342