| .. | .. |
|---|
| 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 | |
|---|