.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2017, Nicholas Piggin, IBM Corporation |
---|
3 | | - * Licensed under GPLv2. |
---|
4 | 4 | */ |
---|
5 | 5 | |
---|
6 | 6 | #define pr_fmt(fmt) "dt-cpu-ftrs: " fmt |
---|
.. | .. |
---|
17 | 17 | |
---|
18 | 18 | #include <asm/cputable.h> |
---|
19 | 19 | #include <asm/dt_cpu_ftrs.h> |
---|
| 20 | +#include <asm/mce.h> |
---|
20 | 21 | #include <asm/mmu.h> |
---|
21 | 22 | #include <asm/oprofile_impl.h> |
---|
22 | 23 | #include <asm/prom.h> |
---|
.. | .. |
---|
24 | 25 | |
---|
25 | 26 | |
---|
26 | 27 | /* Device-tree visible constants follow */ |
---|
27 | | -#define ISA_V2_07B 2070 |
---|
28 | 28 | #define ISA_V3_0B 3000 |
---|
| 29 | +#define ISA_V3_1 3100 |
---|
29 | 30 | |
---|
30 | 31 | #define USABLE_PR (1U << 0) |
---|
31 | 32 | #define USABLE_OS (1U << 1) |
---|
.. | .. |
---|
64 | 65 | * Set up the base CPU |
---|
65 | 66 | */ |
---|
66 | 67 | |
---|
67 | | -extern long __machine_check_early_realmode_p8(struct pt_regs *regs); |
---|
68 | | -extern long __machine_check_early_realmode_p9(struct pt_regs *regs); |
---|
69 | | - |
---|
70 | 68 | static int hv_mode; |
---|
71 | 69 | |
---|
72 | 70 | static struct { |
---|
.. | .. |
---|
74 | 72 | u64 lpcr_clear; |
---|
75 | 73 | u64 hfscr; |
---|
76 | 74 | u64 fscr; |
---|
| 75 | + u64 pcr; |
---|
77 | 76 | } system_registers; |
---|
78 | 77 | |
---|
79 | 78 | static void (*init_pmu_registers)(void); |
---|
.. | .. |
---|
101 | 100 | if (hv_mode) { |
---|
102 | 101 | mtspr(SPRN_LPID, 0); |
---|
103 | 102 | mtspr(SPRN_HFSCR, system_registers.hfscr); |
---|
104 | | - mtspr(SPRN_PCR, 0); |
---|
| 103 | + mtspr(SPRN_PCR, system_registers.pcr); |
---|
105 | 104 | } |
---|
106 | 105 | mtspr(SPRN_FSCR, system_registers.fscr); |
---|
107 | 106 | |
---|
.. | .. |
---|
139 | 138 | /* Initialize the base environment -- clear FSCR/HFSCR. */ |
---|
140 | 139 | hv_mode = !!(mfmsr() & MSR_HV); |
---|
141 | 140 | if (hv_mode) { |
---|
142 | | - /* CPU_FTR_HVMODE is used early in PACA setup */ |
---|
143 | 141 | cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE; |
---|
144 | 142 | mtspr(SPRN_HFSCR, 0); |
---|
145 | 143 | } |
---|
146 | 144 | mtspr(SPRN_FSCR, 0); |
---|
| 145 | + mtspr(SPRN_PCR, PCR_MASK); |
---|
147 | 146 | |
---|
148 | 147 | /* |
---|
149 | 148 | * LPCR does not get cleared, to match behaviour with secondaries |
---|
.. | .. |
---|
335 | 334 | #ifdef CONFIG_PPC_RADIX_MMU |
---|
336 | 335 | cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX; |
---|
337 | 336 | cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE; |
---|
| 337 | + cur_cpu_spec->mmu_features |= MMU_FTR_GTSE; |
---|
338 | 338 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU; |
---|
339 | 339 | |
---|
340 | 340 | return 1; |
---|
.. | .. |
---|
444 | 444 | cur_cpu_spec->num_pmcs = 6; |
---|
445 | 445 | cur_cpu_spec->pmc_type = PPC_PMC_IBM; |
---|
446 | 446 | cur_cpu_spec->oprofile_cpu_type = "ppc64/power9"; |
---|
| 447 | + |
---|
| 448 | + return 1; |
---|
| 449 | +} |
---|
| 450 | + |
---|
| 451 | +static void init_pmu_power10(void) |
---|
| 452 | +{ |
---|
| 453 | + init_pmu_power9(); |
---|
| 454 | + |
---|
| 455 | + mtspr(SPRN_MMCR3, 0); |
---|
| 456 | + mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE); |
---|
| 457 | + mtspr(SPRN_MMCR0, MMCR0_PMCCEXT); |
---|
| 458 | +} |
---|
| 459 | + |
---|
| 460 | +static int __init feat_enable_pmu_power10(struct dt_cpu_feature *f) |
---|
| 461 | +{ |
---|
| 462 | + hfscr_pmu_enable(); |
---|
| 463 | + |
---|
| 464 | + init_pmu_power10(); |
---|
| 465 | + init_pmu_registers = init_pmu_power10; |
---|
| 466 | + |
---|
| 467 | + cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA; |
---|
| 468 | + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT; |
---|
| 469 | + |
---|
| 470 | + cur_cpu_spec->num_pmcs = 6; |
---|
| 471 | + cur_cpu_spec->pmc_type = PPC_PMC_IBM; |
---|
| 472 | + cur_cpu_spec->oprofile_cpu_type = "ppc64/power10"; |
---|
| 473 | + |
---|
| 474 | + return 1; |
---|
| 475 | +} |
---|
| 476 | + |
---|
| 477 | +static int __init feat_enable_mce_power10(struct dt_cpu_feature *f) |
---|
| 478 | +{ |
---|
| 479 | + cur_cpu_spec->platform = "power10"; |
---|
| 480 | + cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p10; |
---|
447 | 481 | |
---|
448 | 482 | return 1; |
---|
449 | 483 | } |
---|
.. | .. |
---|
560 | 594 | return 1; |
---|
561 | 595 | } |
---|
562 | 596 | |
---|
| 597 | +static int __init feat_enable_mma(struct dt_cpu_feature *f) |
---|
| 598 | +{ |
---|
| 599 | + u64 pcr; |
---|
| 600 | + |
---|
| 601 | + feat_enable(f); |
---|
| 602 | + pcr = mfspr(SPRN_PCR); |
---|
| 603 | + pcr &= ~PCR_MMA_DIS; |
---|
| 604 | + mtspr(SPRN_PCR, pcr); |
---|
| 605 | + |
---|
| 606 | + return 1; |
---|
| 607 | +} |
---|
| 608 | + |
---|
563 | 609 | struct dt_cpu_feature_match { |
---|
564 | 610 | const char *name; |
---|
565 | 611 | int (*enable)(struct dt_cpu_feature *f); |
---|
.. | .. |
---|
573 | 619 | {"little-endian", feat_enable_le, CPU_FTR_REAL_LE}, |
---|
574 | 620 | {"smt", feat_enable_smt, 0}, |
---|
575 | 621 | {"interrupt-facilities", feat_enable, 0}, |
---|
| 622 | + {"system-call-vectored", feat_enable, 0}, |
---|
576 | 623 | {"timer-facilities", feat_enable, 0}, |
---|
577 | 624 | {"timer-facilities-v3", feat_enable, 0}, |
---|
578 | 625 | {"debug-facilities", feat_enable, 0}, |
---|
.. | .. |
---|
624 | 671 | {"group-start-register", feat_enable, 0}, |
---|
625 | 672 | {"pc-relative-addressing", feat_enable, 0}, |
---|
626 | 673 | {"machine-check-power9", feat_enable_mce_power9, 0}, |
---|
| 674 | + {"machine-check-power10", feat_enable_mce_power10, 0}, |
---|
627 | 675 | {"performance-monitor-power9", feat_enable_pmu_power9, 0}, |
---|
| 676 | + {"performance-monitor-power10", feat_enable_pmu_power10, 0}, |
---|
628 | 677 | {"event-based-branch-v3", feat_enable, 0}, |
---|
629 | 678 | {"random-number-generator", feat_enable, 0}, |
---|
630 | 679 | {"system-call-vectored", feat_disable, 0}, |
---|
.. | .. |
---|
633 | 682 | {"vector-binary128", feat_enable, 0}, |
---|
634 | 683 | {"vector-binary16", feat_enable, 0}, |
---|
635 | 684 | {"wait-v3", feat_enable, 0}, |
---|
| 685 | + {"prefix-instructions", feat_enable, 0}, |
---|
| 686 | + {"matrix-multiply-assist", feat_enable_mma, 0}, |
---|
| 687 | + {"debug-facilities-v31", feat_enable, CPU_FTR_DAWR1}, |
---|
636 | 688 | }; |
---|
637 | 689 | |
---|
638 | 690 | static bool __initdata using_dt_cpu_ftrs; |
---|
.. | .. |
---|
658 | 710 | { |
---|
659 | 711 | pr_info("setup for ISA %d\n", isa); |
---|
660 | 712 | |
---|
661 | | - if (isa >= 3000) { |
---|
| 713 | + if (isa >= ISA_V3_0B) { |
---|
662 | 714 | cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_300; |
---|
663 | 715 | cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_00; |
---|
| 716 | + } |
---|
| 717 | + |
---|
| 718 | + if (isa >= ISA_V3_1) { |
---|
| 719 | + cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_31; |
---|
| 720 | + cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_1; |
---|
664 | 721 | } |
---|
665 | 722 | } |
---|
666 | 723 | |
---|
.. | .. |
---|
734 | 791 | /* |
---|
735 | 792 | * Not all quirks can be derived from the cpufeatures device tree. |
---|
736 | 793 | */ |
---|
737 | | - if ((version & 0xffffefff) == 0x004e0200) |
---|
738 | | - ; /* DD2.0 has no feature flag */ |
---|
739 | | - else if ((version & 0xffffefff) == 0x004e0201) |
---|
| 794 | + if ((version & 0xffffefff) == 0x004e0200) { |
---|
| 795 | + /* DD2.0 has no feature flag */ |
---|
| 796 | + cur_cpu_spec->cpu_features |= CPU_FTR_P9_RADIX_PREFETCH_BUG; |
---|
| 797 | + } else if ((version & 0xffffefff) == 0x004e0201) { |
---|
740 | 798 | cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; |
---|
741 | | - else if ((version & 0xffffefff) == 0x004e0202) { |
---|
| 799 | + cur_cpu_spec->cpu_features |= CPU_FTR_P9_RADIX_PREFETCH_BUG; |
---|
| 800 | + } else if ((version & 0xffffefff) == 0x004e0202) { |
---|
742 | 801 | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST; |
---|
743 | 802 | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG; |
---|
744 | 803 | cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; |
---|
745 | | - } else if ((version & 0xffff0000) == 0x004e0000) |
---|
| 804 | + } else if ((version & 0xffff0000) == 0x004e0000) { |
---|
746 | 805 | /* DD2.1 and up have DD2_1 */ |
---|
747 | 806 | cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1; |
---|
| 807 | + } |
---|
748 | 808 | |
---|
749 | 809 | if ((version & 0xffff0000) == 0x004e0000) { |
---|
750 | 810 | cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); |
---|
.. | .. |
---|
752 | 812 | } |
---|
753 | 813 | |
---|
754 | 814 | update_tlbie_feature_flag(version); |
---|
755 | | - /* |
---|
756 | | - * PKEY was not in the initial base or feature node |
---|
757 | | - * specification, but it should become optional in the next |
---|
758 | | - * cpu feature version sequence. |
---|
759 | | - */ |
---|
760 | | - cur_cpu_spec->cpu_features |= CPU_FTR_PKEY; |
---|
761 | 815 | } |
---|
762 | 816 | |
---|
763 | 817 | static void __init cpufeatures_setup_finished(void) |
---|
.. | .. |
---|
775 | 829 | system_registers.lpcr = mfspr(SPRN_LPCR); |
---|
776 | 830 | system_registers.hfscr = mfspr(SPRN_HFSCR); |
---|
777 | 831 | system_registers.fscr = mfspr(SPRN_FSCR); |
---|
| 832 | + system_registers.pcr = mfspr(SPRN_PCR); |
---|
778 | 833 | |
---|
779 | 834 | pr_info("final cpu/mmu features = 0x%016lx 0x%08x\n", |
---|
780 | 835 | cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features); |
---|
.. | .. |
---|
846 | 901 | int len; |
---|
847 | 902 | |
---|
848 | 903 | f = &dt_cpu_features[i]; |
---|
849 | | - memset(f, 0, sizeof(struct dt_cpu_feature)); |
---|
850 | 904 | |
---|
851 | 905 | f->node = node; |
---|
852 | 906 | |
---|
.. | .. |
---|
1041 | 1095 | /* Count and allocate space for cpu features */ |
---|
1042 | 1096 | of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes, |
---|
1043 | 1097 | &nr_dt_cpu_features); |
---|
1044 | | - dt_cpu_features = __va( |
---|
1045 | | - memblock_alloc(sizeof(struct dt_cpu_feature)* |
---|
1046 | | - nr_dt_cpu_features, PAGE_SIZE)); |
---|
| 1098 | + dt_cpu_features = memblock_alloc(sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, PAGE_SIZE); |
---|
| 1099 | + if (!dt_cpu_features) |
---|
| 1100 | + panic("%s: Failed to allocate %zu bytes align=0x%lx\n", |
---|
| 1101 | + __func__, |
---|
| 1102 | + sizeof(struct dt_cpu_feature) * nr_dt_cpu_features, |
---|
| 1103 | + PAGE_SIZE); |
---|
1047 | 1104 | |
---|
1048 | 1105 | cpufeatures_setup_start(isa); |
---|
1049 | 1106 | |
---|