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