1
2
3
4
5
6
7
8
9
10
11
12#include <linux/crash_dump.h>
13#include <linux/memblock.h>
14#include <linux/suspend.h>
15#include <linux/acpi.h>
16#include <linux/firmware-map.h>
17#include <linux/sort.h>
18#include <linux/memory_hotplug.h>
19
20#include <asm/e820/api.h>
21#include <asm/setup.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59static struct e820_table e820_table_init __initdata;
60static struct e820_table e820_table_kexec_init __initdata;
61static struct e820_table e820_table_firmware_init __initdata;
62
63struct e820_table *e820_table __refdata = &e820_table_init;
64struct e820_table *e820_table_kexec __refdata = &e820_table_kexec_init;
65struct e820_table *e820_table_firmware __refdata = &e820_table_firmware_init;
66
67
68unsigned long pci_mem_start = 0xaeedbabe;
69#ifdef CONFIG_PCI
70EXPORT_SYMBOL(pci_mem_start);
71#endif
72
73
74
75
76
77static bool _e820__mapped_any(struct e820_table *table,
78 u64 start, u64 end, enum e820_type type)
79{
80 int i;
81
82 for (i = 0; i < table->nr_entries; i++) {
83 struct e820_entry *entry = &table->entries[i];
84
85 if (type && entry->type != type)
86 continue;
87 if (entry->addr >= end || entry->addr + entry->size <= start)
88 continue;
89 return true;
90 }
91 return false;
92}
93
94bool 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}
98EXPORT_SYMBOL_GPL(e820__mapped_raw_any);
99
100bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
101{
102 return _e820__mapped_any(e820_table, start, end, type);
103}
104EXPORT_SYMBOL_GPL(e820__mapped_any);
105
106
107
108
109
110
111
112static struct e820_entry *__e820__mapped_all(u64 start, u64 end,
113 enum e820_type type)
114{
115 int i;
116
117 for (i = 0; i < e820_table->nr_entries; i++) {
118 struct e820_entry *entry = &e820_table->entries[i];
119
120 if (type && entry->type != type)
121 continue;
122
123
124 if (entry->addr >= end || entry->addr + entry->size <= start)
125 continue;
126
127
128
129
130
131 if (entry->addr <= start)
132 start = entry->addr + entry->size;
133
134
135
136
137
138 if (start >= end)
139 return entry;
140 }
141
142 return NULL;
143}
144
145
146
147
148bool __init e820__mapped_all(u64 start, u64 end, enum e820_type type)
149{
150 return __e820__mapped_all(start, end, type);
151}
152
153
154
155
156int e820__get_entry_type(u64 start, u64 end)
157{
158 struct e820_entry *entry = __e820__mapped_all(start, end, 0);
159
160 return entry ? entry->type : -EINVAL;
161}
162
163
164
165
166static void __init __e820__range_add(struct e820_table *table, u64 start, u64 size, enum e820_type type)
167{
168 int x = table->nr_entries;
169
170 if (x >= ARRAY_SIZE(table->entries)) {
171 pr_err("too many entries; ignoring [mem %#010llx-%#010llx]\n",
172 start, start + size - 1);
173 return;
174 }
175
176 table->entries[x].addr = start;
177 table->entries[x].size = size;
178 table->entries[x].type = type;
179 table->nr_entries++;
180}
181
182void __init e820__range_add(u64 start, u64 size, enum e820_type type)
183{
184 __e820__range_add(e820_table, start, size, type);
185}
186
187static void __init e820_print_type(enum e820_type type)
188{
189 switch (type) {
190 case E820_TYPE_RAM:
191 case E820_TYPE_RESERVED_KERN: pr_cont("usable"); break;
192 case E820_TYPE_RESERVED: pr_cont("reserved"); break;
193 case E820_TYPE_SOFT_RESERVED: pr_cont("soft reserved"); break;
194 case E820_TYPE_ACPI: pr_cont("ACPI data"); break;
195 case E820_TYPE_NVS: pr_cont("ACPI NVS"); break;
196 case E820_TYPE_UNUSABLE: pr_cont("unusable"); break;
197 case E820_TYPE_PMEM:
198 case E820_TYPE_PRAM: pr_cont("persistent (type %u)", type); break;
199 default: pr_cont("type %u", type); break;
200 }
201}
202
203void __init e820__print_table(char *who)
204{
205 int i;
206
207 for (i = 0; i < e820_table->nr_entries; i++) {
208 pr_info("%s: [mem %#018Lx-%#018Lx] ",
209 who,
210 e820_table->entries[i].addr,
211 e820_table->entries[i].addr + e820_table->entries[i].size - 1);
212
213 e820_print_type(e820_table->entries[i].type);
214 pr_cont("\n");
215 }
216}
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279struct change_member {
280
281 struct e820_entry *entry;
282
283 unsigned long long addr;
284};
285
286static struct change_member change_point_list[2*E820_MAX_ENTRIES] __initdata;
287static struct change_member *change_point[2*E820_MAX_ENTRIES] __initdata;
288static struct e820_entry *overlap_list[E820_MAX_ENTRIES] __initdata;
289static struct e820_entry new_entries[E820_MAX_ENTRIES] __initdata;
290
291static int __init cpcompare(const void *a, const void *b)
292{
293 struct change_member * const *app = a, * const *bpp = b;
294 const struct change_member *ap = *app, *bp = *bpp;
295
296
297
298
299
300
301
302 if (ap->addr != bp->addr)
303 return ap->addr > bp->addr ? 1 : -1;
304
305 return (ap->addr != ap->entry->addr) - (bp->addr != bp->entry->addr);
306}
307
308static bool e820_nomerge(enum e820_type type)
309{
310
311
312
313
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
322int __init e820__update_table(struct e820_table *table)
323{
324 struct e820_entry *entries = table->entries;
325 u32 max_nr_entries = ARRAY_SIZE(table->entries);
326 enum e820_type current_type, last_type;
327 unsigned long long last_addr;
328 u32 new_nr_entries, overlap_entries;
329 u32 i, chg_idx, chg_nr;
330
331
332 if (table->nr_entries < 2)
333 return -1;
334
335 BUG_ON(table->nr_entries > max_nr_entries);
336
337
338 for (i = 0; i < table->nr_entries; i++) {
339 if (entries[i].addr + entries[i].size < entries[i].addr)
340 return -1;
341 }
342
343
344 for (i = 0; i < 2 * table->nr_entries; i++)
345 change_point[i] = &change_point_list[i];
346
347
348
349
350
351 chg_idx = 0;
352 for (i = 0; i < table->nr_entries; i++) {
353 if (entries[i].size != 0) {
354 change_point[chg_idx]->addr = entries[i].addr;
355 change_point[chg_idx++]->entry = &entries[i];
356 change_point[chg_idx]->addr = entries[i].addr + entries[i].size;
357 change_point[chg_idx++]->entry = &entries[i];
358 }
359 }
360 chg_nr = chg_idx;
361
362
363 sort(change_point, chg_nr, sizeof(*change_point), cpcompare, NULL);
364
365
366 overlap_entries = 0;
367 new_nr_entries = 0;
368 last_type = 0;
369 last_addr = 0;
370
371
372 for (chg_idx = 0; chg_idx < chg_nr; chg_idx++) {
373
374 if (change_point[chg_idx]->addr == change_point[chg_idx]->entry->addr) {
375
376 overlap_list[overlap_entries++] = change_point[chg_idx]->entry;
377 } else {
378
379 for (i = 0; i < overlap_entries; i++) {
380 if (overlap_list[i] == change_point[chg_idx]->entry)
381 overlap_list[i] = overlap_list[overlap_entries-1];
382 }
383 overlap_entries--;
384 }
385
386
387
388
389
390 current_type = 0;
391 for (i = 0; i < overlap_entries; i++) {
392 if (overlap_list[i]->type > current_type)
393 current_type = overlap_list[i]->type;
394 }
395
396
397 if (current_type != last_type || e820_nomerge(current_type)) {
398 if (last_type != 0) {
399 new_entries[new_nr_entries].size = change_point[chg_idx]->addr - last_addr;
400
401 if (new_entries[new_nr_entries].size != 0)
402
403 if (++new_nr_entries >= max_nr_entries)
404 break;
405 }
406 if (current_type != 0) {
407 new_entries[new_nr_entries].addr = change_point[chg_idx]->addr;
408 new_entries[new_nr_entries].type = current_type;
409 last_addr = change_point[chg_idx]->addr;
410 }
411 last_type = current_type;
412 }
413 }
414
415
416 memcpy(entries, new_entries, new_nr_entries*sizeof(*entries));
417 table->nr_entries = new_nr_entries;
418
419 return 0;
420}
421
422static int __init __append_e820_table(struct boot_e820_entry *entries, u32 nr_entries)
423{
424 struct boot_e820_entry *entry = entries;
425
426 while (nr_entries) {
427 u64 start = entry->addr;
428 u64 size = entry->size;
429 u64 end = start + size - 1;
430 u32 type = entry->type;
431
432
433 if (start > end && likely(size))
434 return -1;
435
436 e820__range_add(start, size, type);
437
438 entry++;
439 nr_entries--;
440 }
441 return 0;
442}
443
444
445
446
447
448
449
450
451
452
453static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entries)
454{
455
456 if (nr_entries < 2)
457 return -1;
458
459 return __append_e820_table(entries, nr_entries);
460}
461
462static u64 __init
463__e820__range_update(struct e820_table *table, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
464{
465 u64 end;
466 unsigned int i;
467 u64 real_updated_size = 0;
468
469 BUG_ON(old_type == new_type);
470
471 if (size > (ULLONG_MAX - start))
472 size = ULLONG_MAX - start;
473
474 end = start + size;
475 printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1);
476 e820_print_type(old_type);
477 pr_cont(" ==> ");
478 e820_print_type(new_type);
479 pr_cont("\n");
480
481 for (i = 0; i < table->nr_entries; i++) {
482 struct e820_entry *entry = &table->entries[i];
483 u64 final_start, final_end;
484 u64 entry_end;
485
486 if (entry->type != old_type)
487 continue;
488
489 entry_end = entry->addr + entry->size;
490
491
492 if (entry->addr >= start && entry_end <= end) {
493 entry->type = new_type;
494 real_updated_size += entry->size;
495 continue;
496 }
497
498
499 if (entry->addr < start && entry_end > end) {
500 __e820__range_add(table, start, size, new_type);
501 __e820__range_add(table, end, entry_end - end, entry->type);
502 entry->size = start - entry->addr;
503 real_updated_size += size;
504 continue;
505 }
506
507
508 final_start = max(start, entry->addr);
509 final_end = min(end, entry_end);
510 if (final_start >= final_end)
511 continue;
512
513 __e820__range_add(table, final_start, final_end - final_start, new_type);
514
515 real_updated_size += final_end - final_start;
516
517
518
519
520
521 entry->size -= final_end - final_start;
522 if (entry->addr < final_start)
523 continue;
524
525 entry->addr = final_end;
526 }
527 return real_updated_size;
528}
529
530u64 __init e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
531{
532 return __e820__range_update(e820_table, start, size, old_type, new_type);
533}
534
535static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type)
536{
537 return __e820__range_update(e820_table_kexec, start, size, old_type, new_type);
538}
539
540
541u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type)
542{
543 int i;
544 u64 end;
545 u64 real_removed_size = 0;
546
547 if (size > (ULLONG_MAX - start))
548 size = ULLONG_MAX - start;
549
550 end = start + size;
551 printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", start, end - 1);
552 if (check_type)
553 e820_print_type(old_type);
554 pr_cont("\n");
555
556 for (i = 0; i < e820_table->nr_entries; i++) {
557 struct e820_entry *entry = &e820_table->entries[i];
558 u64 final_start, final_end;
559 u64 entry_end;
560
561 if (check_type && entry->type != old_type)
562 continue;
563
564 entry_end = entry->addr + entry->size;
565
566
567 if (entry->addr >= start && entry_end <= end) {
568 real_removed_size += entry->size;
569 memset(entry, 0, sizeof(*entry));
570 continue;
571 }
572
573
574 if (entry->addr < start && entry_end > end) {
575 e820__range_add(end, entry_end - end, entry->type);
576 entry->size = start - entry->addr;
577 real_removed_size += size;
578 continue;
579 }
580
581
582 final_start = max(start, entry->addr);
583 final_end = min(end, entry_end);
584 if (final_start >= final_end)
585 continue;
586
587 real_removed_size += final_end - final_start;
588
589
590
591
592
593 entry->size -= final_end - final_start;
594 if (entry->addr < final_start)
595 continue;
596
597 entry->addr = final_end;
598 }
599 return real_removed_size;
600}
601
602void __init e820__update_table_print(void)
603{
604 if (e820__update_table(e820_table))
605 return;
606
607 pr_info("modified physical RAM map:\n");
608 e820__print_table("modified");
609}
610
611static void __init e820__update_table_kexec(void)
612{
613 e820__update_table(e820_table_kexec);
614}
615
616#define MAX_GAP_END 0x100000000ull
617
618
619
620
621static int __init e820_search_gap(unsigned long *gapstart, unsigned long *gapsize)
622{
623 unsigned long long last = MAX_GAP_END;
624 int i = e820_table->nr_entries;
625 int found = 0;
626
627 while (--i >= 0) {
628 unsigned long long start = e820_table->entries[i].addr;
629 unsigned long long end = start + e820_table->entries[i].size;
630
631
632
633
634
635 if (last > end) {
636 unsigned long gap = last - end;
637
638 if (gap >= *gapsize) {
639 *gapsize = gap;
640 *gapstart = end;
641 found = 1;
642 }
643 }
644 if (start < last)
645 last = start;
646 }
647 return found;
648}
649
650
651
652
653
654
655
656
657
658__init void e820__setup_pci_gap(void)
659{
660 unsigned long gapstart, gapsize;
661 int found;
662
663 gapsize = 0x400000;
664 found = e820_search_gap(&gapstart, &gapsize);
665
666 if (!found) {
667#ifdef CONFIG_X86_64
668 gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
669 pr_err("Cannot find an available gap in the 32-bit address range\n");
670 pr_err("PCI devices with unassigned 32-bit BARs may not work!\n");
671#else
672 gapstart = 0x10000000;
673#endif
674 }
675
676
677
678
679 pci_mem_start = gapstart;
680
681 pr_info("[mem %#010lx-%#010lx] available for PCI devices\n",
682 gapstart, gapstart + gapsize - 1);
683}
684
685
686
687
688
689
690
691
692
693
694
695
696
697__init void e820__reallocate_tables(void)
698{
699 struct e820_table *n;
700 int size;
701
702 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table->nr_entries;
703 n = kmemdup(e820_table, size, GFP_KERNEL);
704 BUG_ON(!n);
705 e820_table = n;
706
707 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_kexec->nr_entries;
708 n = kmemdup(e820_table_kexec, size, GFP_KERNEL);
709 BUG_ON(!n);
710 e820_table_kexec = n;
711
712 size = offsetof(struct e820_table, entries) + sizeof(struct e820_entry)*e820_table_firmware->nr_entries;
713 n = kmemdup(e820_table_firmware, size, GFP_KERNEL);
714 BUG_ON(!n);
715 e820_table_firmware = n;
716}
717
718
719
720
721
722
723
724void __init e820__memory_setup_extended(u64 phys_addr, u32 data_len)
725{
726 int entries;
727 struct boot_e820_entry *extmap;
728 struct setup_data *sdata;
729
730 sdata = early_memremap(phys_addr, data_len);
731 entries = sdata->len / sizeof(*extmap);
732 extmap = (struct boot_e820_entry *)(sdata->data);
733
734 __append_e820_table(extmap, entries);
735 e820__update_table(e820_table);
736
737 memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec));
738 memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware));
739
740 early_memunmap(sdata, data_len);
741 pr_info("extended physical RAM map:\n");
742 e820__print_table("extended");
743}
744
745
746
747
748
749
750
751
752
753void __init e820__register_nosave_regions(unsigned long limit_pfn)
754{
755 int i;
756 unsigned long pfn = 0;
757
758 for (i = 0; i < e820_table->nr_entries; i++) {
759 struct e820_entry *entry = &e820_table->entries[i];
760
761 if (pfn < PFN_UP(entry->addr))
762 register_nosave_region(pfn, PFN_UP(entry->addr));
763
764 pfn = PFN_DOWN(entry->addr + entry->size);
765
766 if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
767 register_nosave_region(PFN_UP(entry->addr), pfn);
768
769 if (pfn >= limit_pfn)
770 break;
771 }
772}
773
774#ifdef CONFIG_ACPI
775
776
777
778
779static int __init e820__register_nvs_regions(void)
780{
781 int i;
782
783 for (i = 0; i < e820_table->nr_entries; i++) {
784 struct e820_entry *entry = &e820_table->entries[i];
785
786 if (entry->type == E820_TYPE_NVS)
787 acpi_nvs_register(entry->addr, entry->size);
788 }
789
790 return 0;
791}
792core_initcall(e820__register_nvs_regions);
793#endif
794
795
796
797
798
799
800
801
802
803u64 __init e820__memblock_alloc_reserved(u64 size, u64 align)
804{
805 u64 addr;
806
807 addr = memblock_phys_alloc(size, align);
808 if (addr) {
809 e820__range_update_kexec(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
810 pr_info("update e820_table_kexec for e820__memblock_alloc_reserved()\n");
811 e820__update_table_kexec();
812 }
813
814 return addr;
815}
816
817#ifdef CONFIG_X86_32
818# ifdef CONFIG_X86_PAE
819# define MAX_ARCH_PFN (1ULL<<(36-PAGE_SHIFT))
820# else
821# define MAX_ARCH_PFN (1ULL<<(32-PAGE_SHIFT))
822# endif
823#else
824# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT
825#endif
826
827
828
829
830static unsigned long __init e820_end_pfn(unsigned long limit_pfn, enum e820_type type)
831{
832 int i;
833 unsigned long last_pfn = 0;
834 unsigned long max_arch_pfn = MAX_ARCH_PFN;
835
836 for (i = 0; i < e820_table->nr_entries; i++) {
837 struct e820_entry *entry = &e820_table->entries[i];
838 unsigned long start_pfn;
839 unsigned long end_pfn;
840
841 if (entry->type != type)
842 continue;
843
844 start_pfn = entry->addr >> PAGE_SHIFT;
845 end_pfn = (entry->addr + entry->size) >> PAGE_SHIFT;
846
847 if (start_pfn >= limit_pfn)
848 continue;
849 if (end_pfn > limit_pfn) {
850 last_pfn = limit_pfn;
851 break;
852 }
853 if (end_pfn > last_pfn)
854 last_pfn = end_pfn;
855 }
856
857 if (last_pfn > max_arch_pfn)
858 last_pfn = max_arch_pfn;
859
860 pr_info("last_pfn = %#lx max_arch_pfn = %#lx\n",
861 last_pfn, max_arch_pfn);
862 return last_pfn;
863}
864
865unsigned long __init e820__end_of_ram_pfn(void)
866{
867 return e820_end_pfn(MAX_ARCH_PFN, E820_TYPE_RAM);
868}
869
870unsigned long __init e820__end_of_low_ram_pfn(void)
871{
872 return e820_end_pfn(1UL << (32 - PAGE_SHIFT), E820_TYPE_RAM);
873}
874
875static void __init early_panic(char *msg)
876{
877 early_printk(msg);
878 panic(msg);
879}
880
881static int userdef __initdata;
882
883
884static int __init parse_memopt(char *p)
885{
886 u64 mem_size;
887
888 if (!p)
889 return -EINVAL;
890
891 if (!strcmp(p, "nopentium")) {
892#ifdef CONFIG_X86_32
893 setup_clear_cpu_cap(X86_FEATURE_PSE);
894 return 0;
895#else
896 pr_warn("mem=nopentium ignored! (only supported on x86_32)\n");
897 return -EINVAL;
898#endif
899 }
900
901 userdef = 1;
902 mem_size = memparse(p, &p);
903
904
905 if (mem_size == 0)
906 return -EINVAL;
907
908 e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
909
910#ifdef CONFIG_MEMORY_HOTPLUG
911 max_mem_size = mem_size;
912#endif
913
914 return 0;
915}
916early_param("mem", parse_memopt);
917
918static int __init parse_memmap_one(char *p)
919{
920 char *oldp;
921 u64 start_at, mem_size;
922
923 if (!p)
924 return -EINVAL;
925
926 if (!strncmp(p, "exactmap", 8)) {
927 e820_table->nr_entries = 0;
928 userdef = 1;
929 return 0;
930 }
931
932 oldp = p;
933 mem_size = memparse(p, &p);
934 if (p == oldp)
935 return -EINVAL;
936
937 userdef = 1;
938 if (*p == '@') {
939 start_at = memparse(p+1, &p);
940 e820__range_add(start_at, mem_size, E820_TYPE_RAM);
941 } else if (*p == '#') {
942 start_at = memparse(p+1, &p);
943 e820__range_add(start_at, mem_size, E820_TYPE_ACPI);
944 } else if (*p == '$') {
945 start_at = memparse(p+1, &p);
946 e820__range_add(start_at, mem_size, E820_TYPE_RESERVED);
947 } else if (*p == '!') {
948 start_at = memparse(p+1, &p);
949 e820__range_add(start_at, mem_size, E820_TYPE_PRAM);
950 } else if (*p == '%') {
951 enum e820_type from = 0, to = 0;
952
953 start_at = memparse(p + 1, &p);
954 if (*p == '-')
955 from = simple_strtoull(p + 1, &p, 0);
956 if (*p == '+')
957 to = simple_strtoull(p + 1, &p, 0);
958 if (*p != '\0')
959 return -EINVAL;
960 if (from && to)
961 e820__range_update(start_at, mem_size, from, to);
962 else if (to)
963 e820__range_add(start_at, mem_size, to);
964 else if (from)
965 e820__range_remove(start_at, mem_size, from, 1);
966 else
967 e820__range_remove(start_at, mem_size, 0, 0);
968 } else {
969 e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
970 }
971
972 return *p == '\0' ? 0 : -EINVAL;
973}
974
975static int __init parse_memmap_opt(char *str)
976{
977 while (str) {
978 char *k = strchr(str, ',');
979
980 if (k)
981 *k++ = 0;
982
983 parse_memmap_one(str);
984 str = k;
985 }
986
987 return 0;
988}
989early_param("memmap", parse_memmap_opt);
990
991
992
993
994
995
996void __init e820__reserve_setup_data(void)
997{
998 struct setup_data *data;
999 u64 pa_data;
1000
1001 pa_data = boot_params.hdr.setup_data;
1002 if (!pa_data)
1003 return;
1004
1005 while (pa_data) {
1006 data = early_memremap(pa_data, sizeof(*data));
1007 e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1008
1009
1010
1011
1012
1013 if (data->type != SETUP_EFI)
1014 e820__range_update_kexec(pa_data,
1015 sizeof(*data) + data->len,
1016 E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1017
1018 if (data->type == SETUP_INDIRECT &&
1019 ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
1020 e820__range_update(((struct setup_indirect *)data->data)->addr,
1021 ((struct setup_indirect *)data->data)->len,
1022 E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1023 e820__range_update_kexec(((struct setup_indirect *)data->data)->addr,
1024 ((struct setup_indirect *)data->data)->len,
1025 E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
1026 }
1027
1028 pa_data = data->next;
1029 early_memunmap(data, sizeof(*data));
1030 }
1031
1032 e820__update_table(e820_table);
1033 e820__update_table(e820_table_kexec);
1034
1035 pr_info("extended physical RAM map:\n");
1036 e820__print_table("reserve setup_data");
1037}
1038
1039
1040
1041
1042
1043
1044void __init e820__finish_early_params(void)
1045{
1046 if (userdef) {
1047 if (e820__update_table(e820_table) < 0)
1048 early_panic("Invalid user supplied memory map");
1049
1050 pr_info("user-defined physical RAM map:\n");
1051 e820__print_table("user");
1052 }
1053}
1054
1055static const char *__init e820_type_to_string(struct e820_entry *entry)
1056{
1057 switch (entry->type) {
1058 case E820_TYPE_RESERVED_KERN:
1059 case E820_TYPE_RAM: return "System RAM";
1060 case E820_TYPE_ACPI: return "ACPI Tables";
1061 case E820_TYPE_NVS: return "ACPI Non-volatile Storage";
1062 case E820_TYPE_UNUSABLE: return "Unusable memory";
1063 case E820_TYPE_PRAM: return "Persistent Memory (legacy)";
1064 case E820_TYPE_PMEM: return "Persistent Memory";
1065 case E820_TYPE_RESERVED: return "Reserved";
1066 case E820_TYPE_SOFT_RESERVED: return "Soft Reserved";
1067 default: return "Unknown E820 type";
1068 }
1069}
1070
1071static unsigned long __init e820_type_to_iomem_type(struct e820_entry *entry)
1072{
1073 switch (entry->type) {
1074 case E820_TYPE_RESERVED_KERN:
1075 case E820_TYPE_RAM: return IORESOURCE_SYSTEM_RAM;
1076 case E820_TYPE_ACPI:
1077 case E820_TYPE_NVS:
1078 case E820_TYPE_UNUSABLE:
1079 case E820_TYPE_PRAM:
1080 case E820_TYPE_PMEM:
1081 case E820_TYPE_RESERVED:
1082 case E820_TYPE_SOFT_RESERVED:
1083 default: return IORESOURCE_MEM;
1084 }
1085}
1086
1087static unsigned long __init e820_type_to_iores_desc(struct e820_entry *entry)
1088{
1089 switch (entry->type) {
1090 case E820_TYPE_ACPI: return IORES_DESC_ACPI_TABLES;
1091 case E820_TYPE_NVS: return IORES_DESC_ACPI_NV_STORAGE;
1092 case E820_TYPE_PMEM: return IORES_DESC_PERSISTENT_MEMORY;
1093 case E820_TYPE_PRAM: return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
1094 case E820_TYPE_RESERVED: return IORES_DESC_RESERVED;
1095 case E820_TYPE_SOFT_RESERVED: return IORES_DESC_SOFT_RESERVED;
1096 case E820_TYPE_RESERVED_KERN:
1097 case E820_TYPE_RAM:
1098 case E820_TYPE_UNUSABLE:
1099 default: return IORES_DESC_NONE;
1100 }
1101}
1102
1103static bool __init do_mark_busy(enum e820_type type, struct resource *res)
1104{
1105
1106 if (res->start < (1ULL<<20))
1107 return true;
1108
1109
1110
1111
1112
1113 switch (type) {
1114 case E820_TYPE_RESERVED:
1115 case E820_TYPE_SOFT_RESERVED:
1116 case E820_TYPE_PRAM:
1117 case E820_TYPE_PMEM:
1118 return false;
1119 case E820_TYPE_RESERVED_KERN:
1120 case E820_TYPE_RAM:
1121 case E820_TYPE_ACPI:
1122 case E820_TYPE_NVS:
1123 case E820_TYPE_UNUSABLE:
1124 default:
1125 return true;
1126 }
1127}
1128
1129
1130
1131
1132
1133static struct resource __initdata *e820_res;
1134
1135void __init e820__reserve_resources(void)
1136{
1137 int i;
1138 struct resource *res;
1139 u64 end;
1140
1141 res = memblock_alloc(sizeof(*res) * e820_table->nr_entries,
1142 SMP_CACHE_BYTES);
1143 if (!res)
1144 panic("%s: Failed to allocate %zu bytes\n", __func__,
1145 sizeof(*res) * e820_table->nr_entries);
1146 e820_res = res;
1147
1148 for (i = 0; i < e820_table->nr_entries; i++) {
1149 struct e820_entry *entry = e820_table->entries + i;
1150
1151 end = entry->addr + entry->size - 1;
1152 if (end != (resource_size_t)end) {
1153 res++;
1154 continue;
1155 }
1156 res->start = entry->addr;
1157 res->end = end;
1158 res->name = e820_type_to_string(entry);
1159 res->flags = e820_type_to_iomem_type(entry);
1160 res->desc = e820_type_to_iores_desc(entry);
1161
1162
1163
1164
1165
1166
1167 if (do_mark_busy(entry->type, res)) {
1168 res->flags |= IORESOURCE_BUSY;
1169 insert_resource(&iomem_resource, res);
1170 }
1171 res++;
1172 }
1173
1174
1175 for (i = 0; i < e820_table_firmware->nr_entries; i++) {
1176 struct e820_entry *entry = e820_table_firmware->entries + i;
1177
1178 firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry));
1179 }
1180}
1181
1182
1183
1184
1185static unsigned long __init ram_alignment(resource_size_t pos)
1186{
1187 unsigned long mb = pos >> 20;
1188
1189
1190 if (!mb)
1191 return 64*1024;
1192
1193
1194 if (mb < 16)
1195 return 1024*1024;
1196
1197
1198 return 64*1024*1024;
1199}
1200
1201#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
1202
1203void __init e820__reserve_resources_late(void)
1204{
1205 int i;
1206 struct resource *res;
1207
1208 res = e820_res;
1209 for (i = 0; i < e820_table->nr_entries; i++) {
1210 if (!res->parent && res->end)
1211 insert_resource_expand_to_fit(&iomem_resource, res);
1212 res++;
1213 }
1214
1215
1216
1217
1218
1219 for (i = 0; i < e820_table->nr_entries; i++) {
1220 struct e820_entry *entry = &e820_table->entries[i];
1221 u64 start, end;
1222
1223 if (entry->type != E820_TYPE_RAM)
1224 continue;
1225
1226 start = entry->addr + entry->size;
1227 end = round_up(start, ram_alignment(start)) - 1;
1228 if (end > MAX_RESOURCE_SIZE)
1229 end = MAX_RESOURCE_SIZE;
1230 if (start >= end)
1231 continue;
1232
1233 printk(KERN_DEBUG "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", start, end);
1234 reserve_region_with_split(&iomem_resource, start, end, "RAM buffer");
1235 }
1236}
1237
1238
1239
1240
1241char *__init e820__memory_setup_default(void)
1242{
1243 char *who = "BIOS-e820";
1244
1245
1246
1247
1248
1249
1250
1251 if (append_e820_table(boot_params.e820_table, boot_params.e820_entries) < 0) {
1252 u64 mem_size;
1253
1254
1255 if (boot_params.alt_mem_k < boot_params.screen_info.ext_mem_k) {
1256 mem_size = boot_params.screen_info.ext_mem_k;
1257 who = "BIOS-88";
1258 } else {
1259 mem_size = boot_params.alt_mem_k;
1260 who = "BIOS-e801";
1261 }
1262
1263 e820_table->nr_entries = 0;
1264 e820__range_add(0, LOWMEMSIZE(), E820_TYPE_RAM);
1265 e820__range_add(HIGH_MEMORY, mem_size << 10, E820_TYPE_RAM);
1266 }
1267
1268
1269 e820__update_table(e820_table);
1270
1271 return who;
1272}
1273
1274
1275
1276
1277
1278
1279void __init e820__memory_setup(void)
1280{
1281 char *who;
1282
1283
1284 BUILD_BUG_ON(sizeof(struct boot_e820_entry) != 20);
1285
1286 who = x86_init.resources.memory_setup();
1287
1288 memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec));
1289 memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware));
1290
1291 pr_info("BIOS-provided physical RAM map:\n");
1292 e820__print_table(who);
1293}
1294
1295void __init e820__memblock_setup(void)
1296{
1297 int i;
1298 u64 end;
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309 memblock_allow_resize();
1310
1311 for (i = 0; i < e820_table->nr_entries; i++) {
1312 struct e820_entry *entry = &e820_table->entries[i];
1313
1314 end = entry->addr + entry->size;
1315 if (end != (resource_size_t)end)
1316 continue;
1317
1318 if (entry->type == E820_TYPE_SOFT_RESERVED)
1319 memblock_reserve(entry->addr, entry->size);
1320
1321 if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
1322 continue;
1323
1324 memblock_add(entry->addr, entry->size);
1325 }
1326
1327
1328 memblock_trim_memory(PAGE_SIZE);
1329
1330 memblock_dump_all();
1331}
1332