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