.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Procedures for creating, accessing and interpreting the device tree. |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * |
---|
7 | 8 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. |
---|
8 | 9 | * {engebret|bergner}@us.ibm.com |
---|
9 | | - * |
---|
10 | | - * This program is free software; you can redistribute it and/or |
---|
11 | | - * modify it under the terms of the GNU General Public License |
---|
12 | | - * as published by the Free Software Foundation; either version |
---|
13 | | - * 2 of the License, or (at your option) any later version. |
---|
14 | 10 | */ |
---|
15 | 11 | |
---|
16 | 12 | #undef DEBUG |
---|
.. | .. |
---|
34 | 30 | #include <linux/of_fdt.h> |
---|
35 | 31 | #include <linux/libfdt.h> |
---|
36 | 32 | #include <linux/cpu.h> |
---|
| 33 | +#include <linux/pgtable.h> |
---|
37 | 34 | |
---|
38 | 35 | #include <asm/prom.h> |
---|
39 | 36 | #include <asm/rtas.h> |
---|
.. | .. |
---|
45 | 42 | #include <asm/smp.h> |
---|
46 | 43 | #include <asm/mmu.h> |
---|
47 | 44 | #include <asm/paca.h> |
---|
48 | | -#include <asm/pgtable.h> |
---|
49 | 45 | #include <asm/powernv.h> |
---|
50 | 46 | #include <asm/iommu.h> |
---|
51 | 47 | #include <asm/btext.h> |
---|
.. | .. |
---|
59 | 55 | #include <asm/firmware.h> |
---|
60 | 56 | #include <asm/dt_cpu_ftrs.h> |
---|
61 | 57 | #include <asm/drmem.h> |
---|
| 58 | +#include <asm/ultravisor.h> |
---|
62 | 59 | |
---|
63 | 60 | #include <mm/mmu_decl.h> |
---|
64 | 61 | |
---|
.. | .. |
---|
99 | 96 | if (!initrd_start) |
---|
100 | 97 | return 0; |
---|
101 | 98 | |
---|
102 | | - return (start + size) > _ALIGN_DOWN(initrd_start, PAGE_SIZE) && |
---|
103 | | - start <= _ALIGN_UP(initrd_end, PAGE_SIZE); |
---|
| 99 | + return (start + size) > ALIGN_DOWN(initrd_start, PAGE_SIZE) && |
---|
| 100 | + start <= ALIGN(initrd_end, PAGE_SIZE); |
---|
104 | 101 | #else |
---|
105 | 102 | return 0; |
---|
106 | 103 | #endif |
---|
.. | .. |
---|
124 | 121 | size = fdt_totalsize(initial_boot_params); |
---|
125 | 122 | |
---|
126 | 123 | if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || |
---|
127 | | - overlaps_crashkernel(start, size) || |
---|
128 | | - overlaps_initrd(start, size)) { |
---|
129 | | - p = __va(memblock_alloc(size, PAGE_SIZE)); |
---|
| 124 | + !memblock_is_memory(start + size - 1) || |
---|
| 125 | + overlaps_crashkernel(start, size) || overlaps_initrd(start, size)) { |
---|
| 126 | + p = memblock_alloc_raw(size, PAGE_SIZE); |
---|
| 127 | + if (!p) |
---|
| 128 | + panic("Failed to allocate %lu bytes to move device tree\n", |
---|
| 129 | + size); |
---|
130 | 130 | memcpy(p, initial_boot_params, size); |
---|
131 | 131 | initial_boot_params = p; |
---|
132 | 132 | DBG("Moved device tree to 0x%px\n", p); |
---|
.. | .. |
---|
163 | 163 | { .pabyte = 0, .pabit = 6, .cpu_features = CPU_FTR_NOEXECUTE }, |
---|
164 | 164 | { .pabyte = 1, .pabit = 2, .mmu_features = MMU_FTR_CI_LARGE_PAGE }, |
---|
165 | 165 | #ifdef CONFIG_PPC_RADIX_MMU |
---|
166 | | - { .pabyte = 40, .pabit = 0, .mmu_features = MMU_FTR_TYPE_RADIX }, |
---|
| 166 | + { .pabyte = 40, .pabit = 0, .mmu_features = MMU_FTR_TYPE_RADIX | MMU_FTR_GTSE }, |
---|
167 | 167 | #endif |
---|
168 | 168 | { .pabyte = 1, .pabit = 1, .invert = 1, .cpu_features = CPU_FTR_NODSISRALIGN }, |
---|
169 | 169 | { .pabyte = 5, .pabit = 0, .cpu_features = CPU_FTR_REAL_LE, |
---|
.. | .. |
---|
175 | 175 | */ |
---|
176 | 176 | { .pabyte = 22, .pabit = 0, .cpu_features = CPU_FTR_TM_COMP, |
---|
177 | 177 | .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP }, |
---|
| 178 | + |
---|
| 179 | + { .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 }, |
---|
178 | 180 | }; |
---|
179 | 181 | |
---|
180 | 182 | static void __init scan_features(unsigned long node, const unsigned char *ftrs, |
---|
.. | .. |
---|
468 | 470 | * This contains a list of memory blocks along with NUMA affinity |
---|
469 | 471 | * information. |
---|
470 | 472 | */ |
---|
471 | | -static void __init early_init_drmem_lmb(struct drmem_lmb *lmb, |
---|
472 | | - const __be32 **usm) |
---|
| 473 | +static int __init early_init_drmem_lmb(struct drmem_lmb *lmb, |
---|
| 474 | + const __be32 **usm, |
---|
| 475 | + void *data) |
---|
473 | 476 | { |
---|
474 | 477 | u64 base, size; |
---|
475 | 478 | int is_kexec_kdump = 0, rngs; |
---|
.. | .. |
---|
484 | 487 | */ |
---|
485 | 488 | if ((lmb->flags & DRCONF_MEM_RESERVED) || |
---|
486 | 489 | !(lmb->flags & DRCONF_MEM_ASSIGNED)) |
---|
487 | | - return; |
---|
| 490 | + return 0; |
---|
488 | 491 | |
---|
489 | 492 | if (*usm) |
---|
490 | 493 | is_kexec_kdump = 1; |
---|
.. | .. |
---|
499 | 502 | */ |
---|
500 | 503 | rngs = dt_mem_next_cell(dt_root_size_cells, usm); |
---|
501 | 504 | if (!rngs) /* there are no (base, size) duple */ |
---|
502 | | - return; |
---|
| 505 | + return 0; |
---|
503 | 506 | } |
---|
504 | 507 | |
---|
505 | 508 | do { |
---|
.. | .. |
---|
515 | 518 | size = 0x80000000ul - base; |
---|
516 | 519 | } |
---|
517 | 520 | |
---|
| 521 | + if (!validate_mem_limit(base, &size)) |
---|
| 522 | + continue; |
---|
| 523 | + |
---|
518 | 524 | DBG("Adding: %llx -> %llx\n", base, size); |
---|
519 | | - if (validate_mem_limit(base, &size)) |
---|
520 | | - memblock_add(base, size); |
---|
| 525 | + memblock_add(base, size); |
---|
| 526 | + |
---|
| 527 | + if (lmb->flags & DRCONF_MEM_HOTREMOVABLE) |
---|
| 528 | + memblock_mark_hotplug(base, size); |
---|
521 | 529 | } while (--rngs); |
---|
| 530 | + |
---|
| 531 | + return 0; |
---|
522 | 532 | } |
---|
523 | 533 | #endif /* CONFIG_PPC_PSERIES */ |
---|
524 | 534 | |
---|
.. | .. |
---|
529 | 539 | #ifdef CONFIG_PPC_PSERIES |
---|
530 | 540 | if (depth == 1 && |
---|
531 | 541 | strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) { |
---|
532 | | - walk_drmem_lmbs_early(node, early_init_drmem_lmb); |
---|
| 542 | + walk_drmem_lmbs_early(node, NULL, early_init_drmem_lmb); |
---|
533 | 543 | return 0; |
---|
534 | 544 | } |
---|
535 | 545 | #endif |
---|
.. | .. |
---|
623 | 633 | #ifdef CONFIG_BLK_DEV_INITRD |
---|
624 | 634 | /* Then reserve the initrd, if any */ |
---|
625 | 635 | if (initrd_start && (initrd_end > initrd_start)) { |
---|
626 | | - memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE), |
---|
627 | | - _ALIGN_UP(initrd_end, PAGE_SIZE) - |
---|
628 | | - _ALIGN_DOWN(initrd_start, PAGE_SIZE)); |
---|
| 636 | + memblock_reserve(ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE), |
---|
| 637 | + ALIGN(initrd_end, PAGE_SIZE) - |
---|
| 638 | + ALIGN_DOWN(initrd_start, PAGE_SIZE)); |
---|
629 | 639 | } |
---|
630 | 640 | #endif /* CONFIG_BLK_DEV_INITRD */ |
---|
631 | 641 | |
---|
.. | .. |
---|
720 | 730 | #ifdef CONFIG_PPC_POWERNV |
---|
721 | 731 | /* Some machines might need OPAL info for debugging, grab it now. */ |
---|
722 | 732 | of_scan_flat_dt(early_init_dt_scan_opal, NULL); |
---|
| 733 | + |
---|
| 734 | + /* Scan tree for ultravisor feature */ |
---|
| 735 | + of_scan_flat_dt(early_init_dt_scan_ultravisor, NULL); |
---|
723 | 736 | #endif |
---|
724 | 737 | |
---|
725 | | -#ifdef CONFIG_FA_DUMP |
---|
| 738 | +#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP) |
---|
726 | 739 | /* scan tree to see if dump is active during last boot */ |
---|
727 | 740 | of_scan_flat_dt(early_init_dt_scan_fw_dump, NULL); |
---|
728 | 741 | #endif |
---|
.. | .. |
---|
737 | 750 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
---|
738 | 751 | of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); |
---|
739 | 752 | |
---|
| 753 | + /* |
---|
| 754 | + * As generic code authors expect to be able to use static keys |
---|
| 755 | + * in early_param() handlers, we initialize the static keys just |
---|
| 756 | + * before parsing early params (it's fine to call jump_label_init() |
---|
| 757 | + * more than once). |
---|
| 758 | + */ |
---|
| 759 | + jump_label_init(); |
---|
740 | 760 | parse_early_param(); |
---|
741 | 761 | |
---|
742 | 762 | /* make sure we've parsed cmdline for mem= before this */ |
---|
.. | .. |
---|
749 | 769 | if (PHYSICAL_START > MEMORY_START) |
---|
750 | 770 | memblock_reserve(MEMORY_START, 0x8000); |
---|
751 | 771 | reserve_kdump_trampoline(); |
---|
752 | | -#ifdef CONFIG_FA_DUMP |
---|
| 772 | +#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP) |
---|
753 | 773 | /* |
---|
754 | 774 | * If we fail to reserve memory for firmware-assisted dump then |
---|
755 | 775 | * fallback to kexec based kdump. |
---|
.. | .. |
---|
762 | 782 | /* Ensure that total memory size is page-aligned. */ |
---|
763 | 783 | limit = ALIGN(memory_limit ?: memblock_phys_mem_size(), PAGE_SIZE); |
---|
764 | 784 | memblock_enforce_memory_limit(limit); |
---|
| 785 | + |
---|
| 786 | +#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_4K_PAGES) |
---|
| 787 | + if (!early_radix_enabled()) |
---|
| 788 | + memblock_cap_memory_range(0, 1UL << (H_MAX_PHYSMEM_BITS)); |
---|
| 789 | +#endif |
---|
765 | 790 | |
---|
766 | 791 | memblock_allow_resize(); |
---|
767 | 792 | memblock_dump_all(); |
---|
.. | .. |
---|
807 | 832 | /* Now try to figure out if we are running on LPAR and so on */ |
---|
808 | 833 | pseries_probe_fw_features(); |
---|
809 | 834 | |
---|
| 835 | + /* |
---|
| 836 | + * Initialize pkey features and default AMR/IAMR values |
---|
| 837 | + */ |
---|
| 838 | + pkey_early_init_devtree(); |
---|
| 839 | + |
---|
810 | 840 | #ifdef CONFIG_PPC_PS3 |
---|
811 | 841 | /* Identify PS3 firmware */ |
---|
812 | 842 | if (of_flat_dt_is_compatible(of_get_flat_dt_root(), "sony,ps3")) |
---|