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 if (*p == '%') {
928 enum e820_type from = 0, to = 0;
929
930 start_at = memparse(p + 1, &p);
931 if (*p == '-')
932 from = simple_strtoull(p + 1, &p, 0);
933 if (*p == '+')
934 to = simple_strtoull(p + 1, &p, 0);
935 if (*p != '\0')
936 return -EINVAL;
937 if (from && to)
938 e820__range_update(start_at, mem_size, from, to);
939 else if (to)
940 e820__range_add(start_at, mem_size, to);
941 else if (from)
942 e820__range_remove(start_at, mem_size, from, 1);
943 else
944 e820__range_remove(start_at, mem_size, 0, 0);
945 } else {
946 e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
947 }
948
949 return *p == '\0' ? 0 : -EINVAL;
950}
951
952static int __init parse_memmap_opt(char *str)
953{
954 while (str) {
955 char *k = strchr(str, ',');
956
957 if (k)
958 *k++ = 0;
959
960 parse_memmap_one(str);
961 str = k;
962 }
963
964 return 0;
965}
966early_param("memmap", parse_memmap_opt);
967
968
969
970
971
972
973void __init e820__reserve_setup_data(void)
974{
975 struct setup_data *data;
976 u64 pa_data;
977
978 pa_data = boot_params.hdr.setup_data;
979 if (!pa_data)
980 return;
981
982 while (pa_data) {
983 data = early_memremap(pa_data, sizeof(*data));
984 e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
985 e820__range_update_kexec(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
986 pa_data = data->next;
987 early_memunmap(data, sizeof(*data));
988 }
989
990 e820__update_table(e820_table);
991 e820__update_table(e820_table_kexec);
992
993 pr_info("extended physical RAM map:\n");
994 e820__print_table("reserve setup_data");
995}
996
997
998
999
1000
1001
1002void __init e820__finish_early_params(void)
1003{
1004 if (userdef) {
1005 if (e820__update_table(e820_table) < 0)
1006 early_panic("Invalid user supplied memory map");
1007
1008 pr_info("e820: user-defined physical RAM map:\n");
1009 e820__print_table("user");
1010 }
1011}
1012
1013static const char *__init e820_type_to_string(struct e820_entry *entry)
1014{
1015 switch (entry->type) {
1016 case E820_TYPE_RESERVED_KERN:
1017 case E820_TYPE_RAM: return "System RAM";
1018 case E820_TYPE_ACPI: return "ACPI Tables";
1019 case E820_TYPE_NVS: return "ACPI Non-volatile Storage";
1020 case E820_TYPE_UNUSABLE: return "Unusable memory";
1021 case E820_TYPE_PRAM: return "Persistent Memory (legacy)";
1022 case E820_TYPE_PMEM: return "Persistent Memory";
1023 case E820_TYPE_RESERVED: return "Reserved";
1024 default: return "Unknown E820 type";
1025 }
1026}
1027
1028static unsigned long __init e820_type_to_iomem_type(struct e820_entry *entry)
1029{
1030 switch (entry->type) {
1031 case E820_TYPE_RESERVED_KERN:
1032 case E820_TYPE_RAM: return IORESOURCE_SYSTEM_RAM;
1033 case E820_TYPE_ACPI:
1034 case E820_TYPE_NVS:
1035 case E820_TYPE_UNUSABLE:
1036 case E820_TYPE_PRAM:
1037 case E820_TYPE_PMEM:
1038 case E820_TYPE_RESERVED:
1039 default: return IORESOURCE_MEM;
1040 }
1041}
1042
1043static unsigned long __init e820_type_to_iores_desc(struct e820_entry *entry)
1044{
1045 switch (entry->type) {
1046 case E820_TYPE_ACPI: return IORES_DESC_ACPI_TABLES;
1047 case E820_TYPE_NVS: return IORES_DESC_ACPI_NV_STORAGE;
1048 case E820_TYPE_PMEM: return IORES_DESC_PERSISTENT_MEMORY;
1049 case E820_TYPE_PRAM: return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
1050 case E820_TYPE_RESERVED_KERN:
1051 case E820_TYPE_RAM:
1052 case E820_TYPE_UNUSABLE:
1053 case E820_TYPE_RESERVED:
1054 default: return IORES_DESC_NONE;
1055 }
1056}
1057
1058static bool __init do_mark_busy(enum e820_type type, struct resource *res)
1059{
1060
1061 if (res->start < (1ULL<<20))
1062 return true;
1063
1064
1065
1066
1067
1068 switch (type) {
1069 case E820_TYPE_RESERVED:
1070 case E820_TYPE_PRAM:
1071 case E820_TYPE_PMEM:
1072 return false;
1073 case E820_TYPE_RESERVED_KERN:
1074 case E820_TYPE_RAM:
1075 case E820_TYPE_ACPI:
1076 case E820_TYPE_NVS:
1077 case E820_TYPE_UNUSABLE:
1078 default:
1079 return true;
1080 }
1081}
1082
1083
1084
1085
1086
1087static struct resource __initdata *e820_res;
1088
1089void __init e820__reserve_resources(void)
1090{
1091 int i;
1092 struct resource *res;
1093 u64 end;
1094
1095 res = alloc_bootmem(sizeof(*res) * e820_table->nr_entries);
1096 e820_res = res;
1097
1098 for (i = 0; i < e820_table->nr_entries; i++) {
1099 struct e820_entry *entry = e820_table->entries + i;
1100
1101 end = entry->addr + entry->size - 1;
1102 if (end != (resource_size_t)end) {
1103 res++;
1104 continue;
1105 }
1106 res->start = entry->addr;
1107 res->end = end;
1108 res->name = e820_type_to_string(entry);
1109 res->flags = e820_type_to_iomem_type(entry);
1110 res->desc = e820_type_to_iores_desc(entry);
1111
1112
1113
1114
1115
1116
1117 if (do_mark_busy(entry->type, res)) {
1118 res->flags |= IORESOURCE_BUSY;
1119 insert_resource(&iomem_resource, res);
1120 }
1121 res++;
1122 }
1123
1124
1125 for (i = 0; i < e820_table_firmware->nr_entries; i++) {
1126 struct e820_entry *entry = e820_table_firmware->entries + i;
1127
1128 firmware_map_add_early(entry->addr, entry->addr + entry->size, e820_type_to_string(entry));
1129 }
1130}
1131
1132
1133
1134
1135static unsigned long __init ram_alignment(resource_size_t pos)
1136{
1137 unsigned long mb = pos >> 20;
1138
1139
1140 if (!mb)
1141 return 64*1024;
1142
1143
1144 if (mb < 16)
1145 return 1024*1024;
1146
1147
1148 return 64*1024*1024;
1149}
1150
1151#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
1152
1153void __init e820__reserve_resources_late(void)
1154{
1155 int i;
1156 struct resource *res;
1157
1158 res = e820_res;
1159 for (i = 0; i < e820_table->nr_entries; i++) {
1160 if (!res->parent && res->end)
1161 insert_resource_expand_to_fit(&iomem_resource, res);
1162 res++;
1163 }
1164
1165
1166
1167
1168
1169 for (i = 0; i < e820_table->nr_entries; i++) {
1170 struct e820_entry *entry = &e820_table->entries[i];
1171 u64 start, end;
1172
1173 if (entry->type != E820_TYPE_RAM)
1174 continue;
1175
1176 start = entry->addr + entry->size;
1177 end = round_up(start, ram_alignment(start)) - 1;
1178 if (end > MAX_RESOURCE_SIZE)
1179 end = MAX_RESOURCE_SIZE;
1180 if (start >= end)
1181 continue;
1182
1183 printk(KERN_DEBUG "e820: reserve RAM buffer [mem %#010llx-%#010llx]\n", start, end);
1184 reserve_region_with_split(&iomem_resource, start, end, "RAM buffer");
1185 }
1186}
1187
1188
1189
1190
1191char *__init e820__memory_setup_default(void)
1192{
1193 char *who = "BIOS-e820";
1194
1195
1196
1197
1198
1199
1200
1201 if (append_e820_table(boot_params.e820_table, boot_params.e820_entries) < 0) {
1202 u64 mem_size;
1203
1204
1205 if (boot_params.alt_mem_k < boot_params.screen_info.ext_mem_k) {
1206 mem_size = boot_params.screen_info.ext_mem_k;
1207 who = "BIOS-88";
1208 } else {
1209 mem_size = boot_params.alt_mem_k;
1210 who = "BIOS-e801";
1211 }
1212
1213 e820_table->nr_entries = 0;
1214 e820__range_add(0, LOWMEMSIZE(), E820_TYPE_RAM);
1215 e820__range_add(HIGH_MEMORY, mem_size << 10, E820_TYPE_RAM);
1216 }
1217
1218
1219 e820__update_table(e820_table);
1220
1221 return who;
1222}
1223
1224
1225
1226
1227
1228
1229void __init e820__memory_setup(void)
1230{
1231 char *who;
1232
1233
1234 BUILD_BUG_ON(sizeof(struct boot_e820_entry) != 20);
1235
1236 who = x86_init.resources.memory_setup();
1237
1238 memcpy(e820_table_kexec, e820_table, sizeof(*e820_table_kexec));
1239 memcpy(e820_table_firmware, e820_table, sizeof(*e820_table_firmware));
1240
1241 pr_info("e820: BIOS-provided physical RAM map:\n");
1242 e820__print_table(who);
1243}
1244
1245void __init e820__memblock_setup(void)
1246{
1247 int i;
1248 u64 end;
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259 memblock_allow_resize();
1260
1261 for (i = 0; i < e820_table->nr_entries; i++) {
1262 struct e820_entry *entry = &e820_table->entries[i];
1263
1264 end = entry->addr + entry->size;
1265 if (end != (resource_size_t)end)
1266 continue;
1267
1268 if (entry->type != E820_TYPE_RAM && entry->type != E820_TYPE_RESERVED_KERN)
1269 continue;
1270
1271 memblock_add(entry->addr, entry->size);
1272 }
1273
1274
1275 memblock_trim_memory(PAGE_SIZE);
1276
1277 memblock_dump_all();
1278}
1279