18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Common Performance counter support functions for PowerISA v2.07 processors. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2009 Paul Mackerras, IBM Corporation. 68c2ecf20Sopenharmony_ci * Copyright 2013 Michael Ellerman, IBM Corporation. 78c2ecf20Sopenharmony_ci * Copyright 2016 Madhavan Srinivasan, IBM Corporation. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include "isa207-common.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(event, "config:0-49"); 128c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(pmcxsel, "config:0-7"); 138c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(mark, "config:8"); 148c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(combine, "config:11"); 158c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(unit, "config:12-15"); 168c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(pmc, "config:16-19"); 178c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(cache_sel, "config:20-23"); 188c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(sample_mode, "config:24-28"); 198c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(thresh_sel, "config:29-31"); 208c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(thresh_stop, "config:32-35"); 218c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(thresh_start, "config:36-39"); 228c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(thresh_cmp, "config:40-49"); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct attribute *isa207_pmu_format_attr[] = { 258c2ecf20Sopenharmony_ci &format_attr_event.attr, 268c2ecf20Sopenharmony_ci &format_attr_pmcxsel.attr, 278c2ecf20Sopenharmony_ci &format_attr_mark.attr, 288c2ecf20Sopenharmony_ci &format_attr_combine.attr, 298c2ecf20Sopenharmony_ci &format_attr_unit.attr, 308c2ecf20Sopenharmony_ci &format_attr_pmc.attr, 318c2ecf20Sopenharmony_ci &format_attr_cache_sel.attr, 328c2ecf20Sopenharmony_ci &format_attr_sample_mode.attr, 338c2ecf20Sopenharmony_ci &format_attr_thresh_sel.attr, 348c2ecf20Sopenharmony_ci &format_attr_thresh_stop.attr, 358c2ecf20Sopenharmony_ci &format_attr_thresh_start.attr, 368c2ecf20Sopenharmony_ci &format_attr_thresh_cmp.attr, 378c2ecf20Sopenharmony_ci NULL, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistruct attribute_group isa207_pmu_format_group = { 418c2ecf20Sopenharmony_ci .name = "format", 428c2ecf20Sopenharmony_ci .attrs = isa207_pmu_format_attr, 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic inline bool event_is_fab_match(u64 event) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci /* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */ 488c2ecf20Sopenharmony_ci event &= 0xff0fe; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* PM_MRK_FAB_RSP_MATCH & PM_MRK_FAB_RSP_MATCH_CYC */ 518c2ecf20Sopenharmony_ci return (event == 0x30056 || event == 0x4f052); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic bool is_event_valid(u64 event) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci u64 valid_mask = EVENT_VALID_MASK; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 598c2ecf20Sopenharmony_ci valid_mask = p10_EVENT_VALID_MASK; 608c2ecf20Sopenharmony_ci else if (cpu_has_feature(CPU_FTR_ARCH_300)) 618c2ecf20Sopenharmony_ci valid_mask = p9_EVENT_VALID_MASK; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return !(event & ~valid_mask); 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic inline bool is_event_marked(u64 event) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci if (event & EVENT_IS_MARKED) 698c2ecf20Sopenharmony_ci return true; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return false; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic unsigned long sdar_mod_val(u64 event) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 778c2ecf20Sopenharmony_ci return p10_SDAR_MODE(event); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci return p9_SDAR_MODE(event); 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic void mmcra_sdar_mode(u64 event, unsigned long *mmcra) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci /* 858c2ecf20Sopenharmony_ci * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in 868c2ecf20Sopenharmony_ci * continous sampling mode. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * Incase of Power8: 898c2ecf20Sopenharmony_ci * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling 908c2ecf20Sopenharmony_ci * mode and will be un-changed when setting MMCRA[63] (Marked events). 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * Incase of Power9/power10: 938c2ecf20Sopenharmony_ci * Marked event: MMCRA[SDAR_MODE] will be set to 0b00 ('No Updates'), 948c2ecf20Sopenharmony_ci * or if group already have any marked events. 958c2ecf20Sopenharmony_ci * For rest 968c2ecf20Sopenharmony_ci * MMCRA[SDAR_MODE] will be set from event code. 978c2ecf20Sopenharmony_ci * If sdar_mode from event is zero, default to 0b01. Hardware 988c2ecf20Sopenharmony_ci * requires that we set a non-zero value. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 1018c2ecf20Sopenharmony_ci if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE)) 1028c2ecf20Sopenharmony_ci *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES; 1038c2ecf20Sopenharmony_ci else if (sdar_mod_val(event)) 1048c2ecf20Sopenharmony_ci *mmcra |= sdar_mod_val(event) << MMCRA_SDAR_MODE_SHIFT; 1058c2ecf20Sopenharmony_ci else 1068c2ecf20Sopenharmony_ci *mmcra |= MMCRA_SDAR_MODE_DCACHE; 1078c2ecf20Sopenharmony_ci } else 1088c2ecf20Sopenharmony_ci *mmcra |= MMCRA_SDAR_MODE_TLB; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic u64 thresh_cmp_val(u64 value) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 1148c2ecf20Sopenharmony_ci return value << p9_MMCRA_THR_CMP_SHIFT; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return value << MMCRA_THR_CMP_SHIFT; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic unsigned long combine_from_event(u64 event) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 1228c2ecf20Sopenharmony_ci return p9_EVENT_COMBINE(event); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return EVENT_COMBINE(event); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic unsigned long combine_shift(unsigned long pmc) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) 1308c2ecf20Sopenharmony_ci return p9_MMCR1_COMBINE_SHIFT(pmc); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return MMCR1_COMBINE_SHIFT(pmc); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic inline bool event_is_threshold(u64 event) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic bool is_thresh_cmp_valid(u64 event) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci unsigned int cmp, exp; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* 1458c2ecf20Sopenharmony_ci * Check the mantissa upper two bits are not zero, unless the 1468c2ecf20Sopenharmony_ci * exponent is also zero. See the THRESH_CMP_MANTISSA doc. 1478c2ecf20Sopenharmony_ci * Power10: thresh_cmp is replaced by l2_l3 event select. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 1508c2ecf20Sopenharmony_ci return false; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; 1538c2ecf20Sopenharmony_ci exp = cmp >> 7; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (exp && (cmp & 0x60) == 0) 1568c2ecf20Sopenharmony_ci return false; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return true; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic unsigned int dc_ic_rld_quad_l1_sel(u64 event) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci unsigned int cache; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci cache = (event >> EVENT_CACHE_SEL_SHIFT) & MMCR1_DC_IC_QUAL_MASK; 1668c2ecf20Sopenharmony_ci return cache; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic inline u64 isa207_find_source(u64 idx, u32 sub_idx) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci u64 ret = PERF_MEM_NA; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci switch(idx) { 1748c2ecf20Sopenharmony_ci case 0: 1758c2ecf20Sopenharmony_ci /* Nothing to do */ 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case 1: 1788c2ecf20Sopenharmony_ci ret = PH(LVL, L1); 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci case 2: 1818c2ecf20Sopenharmony_ci ret = PH(LVL, L2); 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case 3: 1848c2ecf20Sopenharmony_ci ret = PH(LVL, L3); 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci case 4: 1878c2ecf20Sopenharmony_ci if (sub_idx <= 1) 1888c2ecf20Sopenharmony_ci ret = PH(LVL, LOC_RAM); 1898c2ecf20Sopenharmony_ci else if (sub_idx > 1 && sub_idx <= 2) 1908c2ecf20Sopenharmony_ci ret = PH(LVL, REM_RAM1); 1918c2ecf20Sopenharmony_ci else 1928c2ecf20Sopenharmony_ci ret = PH(LVL, REM_RAM2); 1938c2ecf20Sopenharmony_ci ret |= P(SNOOP, HIT); 1948c2ecf20Sopenharmony_ci break; 1958c2ecf20Sopenharmony_ci case 5: 1968c2ecf20Sopenharmony_ci ret = PH(LVL, REM_CCE1); 1978c2ecf20Sopenharmony_ci if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4)) 1988c2ecf20Sopenharmony_ci ret |= P(SNOOP, HIT); 1998c2ecf20Sopenharmony_ci else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5)) 2008c2ecf20Sopenharmony_ci ret |= P(SNOOP, HITM); 2018c2ecf20Sopenharmony_ci break; 2028c2ecf20Sopenharmony_ci case 6: 2038c2ecf20Sopenharmony_ci ret = PH(LVL, REM_CCE2); 2048c2ecf20Sopenharmony_ci if ((sub_idx == 0) || (sub_idx == 2)) 2058c2ecf20Sopenharmony_ci ret |= P(SNOOP, HIT); 2068c2ecf20Sopenharmony_ci else if ((sub_idx == 1) || (sub_idx == 3)) 2078c2ecf20Sopenharmony_ci ret |= P(SNOOP, HITM); 2088c2ecf20Sopenharmony_ci break; 2098c2ecf20Sopenharmony_ci case 7: 2108c2ecf20Sopenharmony_ci ret = PM(LVL, L1); 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci return ret; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_civoid isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags, 2188c2ecf20Sopenharmony_ci struct pt_regs *regs) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci u64 idx; 2218c2ecf20Sopenharmony_ci u32 sub_idx; 2228c2ecf20Sopenharmony_ci u64 sier; 2238c2ecf20Sopenharmony_ci u64 val; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* Skip if no SIER support */ 2268c2ecf20Sopenharmony_ci if (!(flags & PPMU_HAS_SIER)) { 2278c2ecf20Sopenharmony_ci dsrc->val = 0; 2288c2ecf20Sopenharmony_ci return; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci sier = mfspr(SPRN_SIER); 2328c2ecf20Sopenharmony_ci val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; 2338c2ecf20Sopenharmony_ci if (val == 1 || val == 2) { 2348c2ecf20Sopenharmony_ci idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT; 2358c2ecf20Sopenharmony_ci sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci dsrc->val = isa207_find_source(idx, sub_idx); 2388c2ecf20Sopenharmony_ci dsrc->val |= (val == 1) ? P(OP, LOAD) : P(OP, STORE); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_civoid isa207_get_mem_weight(u64 *weight) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci u64 mmcra = mfspr(SPRN_MMCRA); 2458c2ecf20Sopenharmony_ci u64 exp = MMCRA_THR_CTR_EXP(mmcra); 2468c2ecf20Sopenharmony_ci u64 mantissa = MMCRA_THR_CTR_MANT(mmcra); 2478c2ecf20Sopenharmony_ci u64 sier = mfspr(SPRN_SIER); 2488c2ecf20Sopenharmony_ci u64 val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 2518c2ecf20Sopenharmony_ci mantissa = P10_MMCRA_THR_CTR_MANT(mmcra); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if (val == 0 || val == 7) 2548c2ecf20Sopenharmony_ci *weight = 0; 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci *weight = mantissa << (2 * exp); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciint isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci unsigned int unit, pmc, cache, ebb; 2628c2ecf20Sopenharmony_ci unsigned long mask, value; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci mask = value = 0; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci if (!is_event_valid(event)) 2678c2ecf20Sopenharmony_ci return -1; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 2708c2ecf20Sopenharmony_ci unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; 2718c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 2728c2ecf20Sopenharmony_ci cache = (event >> EVENT_CACHE_SEL_SHIFT) & 2738c2ecf20Sopenharmony_ci p10_EVENT_CACHE_SEL_MASK; 2748c2ecf20Sopenharmony_ci else 2758c2ecf20Sopenharmony_ci cache = (event >> EVENT_CACHE_SEL_SHIFT) & 2768c2ecf20Sopenharmony_ci EVENT_CACHE_SEL_MASK; 2778c2ecf20Sopenharmony_ci ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (pmc) { 2808c2ecf20Sopenharmony_ci u64 base_event; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (pmc > 6) 2838c2ecf20Sopenharmony_ci return -1; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Ignore Linux defined bits when checking event below */ 2868c2ecf20Sopenharmony_ci base_event = event & ~EVENT_LINUX_MASK; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (pmc >= 5 && base_event != 0x500fa && 2898c2ecf20Sopenharmony_ci base_event != 0x600f4) 2908c2ecf20Sopenharmony_ci return -1; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci mask |= CNST_PMC_MASK(pmc); 2938c2ecf20Sopenharmony_ci value |= CNST_PMC_VAL(pmc); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* 2968c2ecf20Sopenharmony_ci * PMC5 and PMC6 are used to count cycles and instructions and 2978c2ecf20Sopenharmony_ci * they do not support most of the constraint bits. Add a check 2988c2ecf20Sopenharmony_ci * to exclude PMC5/6 from most of the constraints except for 2998c2ecf20Sopenharmony_ci * EBB/BHRB. 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_ci if (pmc >= 5) 3028c2ecf20Sopenharmony_ci goto ebb_bhrb; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (pmc <= 4) { 3068c2ecf20Sopenharmony_ci /* 3078c2ecf20Sopenharmony_ci * Add to number of counters in use. Note this includes events with 3088c2ecf20Sopenharmony_ci * a PMC of 0 - they still need a PMC, it's just assigned later. 3098c2ecf20Sopenharmony_ci * Don't count events on PMC 5 & 6, there is only one valid event 3108c2ecf20Sopenharmony_ci * on each of those counters, and they are handled above. 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_ci mask |= CNST_NC_MASK; 3138c2ecf20Sopenharmony_ci value |= CNST_NC_VAL; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (unit >= 6 && unit <= 9) { 3178c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) { 3188c2ecf20Sopenharmony_ci if (unit == 6) { 3198c2ecf20Sopenharmony_ci mask |= CNST_L2L3_GROUP_MASK; 3208c2ecf20Sopenharmony_ci value |= CNST_L2L3_GROUP_VAL(event >> p10_L2L3_EVENT_SHIFT); 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci } else if (cpu_has_feature(CPU_FTR_ARCH_300)) { 3238c2ecf20Sopenharmony_ci mask |= CNST_CACHE_GROUP_MASK; 3248c2ecf20Sopenharmony_ci value |= CNST_CACHE_GROUP_VAL(event & 0xff); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci mask |= CNST_CACHE_PMC4_MASK; 3278c2ecf20Sopenharmony_ci if (pmc == 4) 3288c2ecf20Sopenharmony_ci value |= CNST_CACHE_PMC4_VAL; 3298c2ecf20Sopenharmony_ci } else if (cache & 0x7) { 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * L2/L3 events contain a cache selector field, which is 3328c2ecf20Sopenharmony_ci * supposed to be programmed into MMCRC. However MMCRC is only 3338c2ecf20Sopenharmony_ci * HV writable, and there is no API for guest kernels to modify 3348c2ecf20Sopenharmony_ci * it. The solution is for the hypervisor to initialise the 3358c2ecf20Sopenharmony_ci * field to zeroes, and for us to only ever allow events that 3368c2ecf20Sopenharmony_ci * have a cache selector of zero. The bank selector (bit 3) is 3378c2ecf20Sopenharmony_ci * irrelevant, as long as the rest of the value is 0. 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_ci return -1; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci } else if (cpu_has_feature(CPU_FTR_ARCH_300) || (event & EVENT_IS_L1)) { 3438c2ecf20Sopenharmony_ci mask |= CNST_L1_QUAL_MASK; 3448c2ecf20Sopenharmony_ci value |= CNST_L1_QUAL_VAL(cache); 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) { 3488c2ecf20Sopenharmony_ci mask |= CNST_RADIX_SCOPE_GROUP_MASK; 3498c2ecf20Sopenharmony_ci value |= CNST_RADIX_SCOPE_GROUP_VAL(event >> p10_EVENT_RADIX_SCOPE_QUAL_SHIFT); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (is_event_marked(event)) { 3538c2ecf20Sopenharmony_ci mask |= CNST_SAMPLE_MASK; 3548c2ecf20Sopenharmony_ci value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) { 3588c2ecf20Sopenharmony_ci if (event_is_threshold(event)) { 3598c2ecf20Sopenharmony_ci mask |= CNST_THRESH_CTL_SEL_MASK; 3608c2ecf20Sopenharmony_ci value |= CNST_THRESH_CTL_SEL_VAL(event >> EVENT_THRESH_SHIFT); 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci } else if (cpu_has_feature(CPU_FTR_ARCH_300)) { 3638c2ecf20Sopenharmony_ci if (event_is_threshold(event) && is_thresh_cmp_valid(event)) { 3648c2ecf20Sopenharmony_ci mask |= CNST_THRESH_MASK; 3658c2ecf20Sopenharmony_ci value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); 3668c2ecf20Sopenharmony_ci } else if (event_is_threshold(event)) 3678c2ecf20Sopenharmony_ci return -1; 3688c2ecf20Sopenharmony_ci } else { 3698c2ecf20Sopenharmony_ci /* 3708c2ecf20Sopenharmony_ci * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, 3718c2ecf20Sopenharmony_ci * the threshold control bits are used for the match value. 3728c2ecf20Sopenharmony_ci */ 3738c2ecf20Sopenharmony_ci if (event_is_fab_match(event)) { 3748c2ecf20Sopenharmony_ci mask |= CNST_FAB_MATCH_MASK; 3758c2ecf20Sopenharmony_ci value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT); 3768c2ecf20Sopenharmony_ci } else { 3778c2ecf20Sopenharmony_ci if (!is_thresh_cmp_valid(event)) 3788c2ecf20Sopenharmony_ci return -1; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci mask |= CNST_THRESH_MASK; 3818c2ecf20Sopenharmony_ci value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciebb_bhrb: 3868c2ecf20Sopenharmony_ci if (!pmc && ebb) 3878c2ecf20Sopenharmony_ci /* EBB events must specify the PMC */ 3888c2ecf20Sopenharmony_ci return -1; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci if (event & EVENT_WANTS_BHRB) { 3918c2ecf20Sopenharmony_ci if (!ebb) 3928c2ecf20Sopenharmony_ci /* Only EBB events can request BHRB */ 3938c2ecf20Sopenharmony_ci return -1; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci mask |= CNST_IFM_MASK; 3968c2ecf20Sopenharmony_ci value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci /* 4008c2ecf20Sopenharmony_ci * All events must agree on EBB, either all request it or none. 4018c2ecf20Sopenharmony_ci * EBB events are pinned & exclusive, so this should never actually 4028c2ecf20Sopenharmony_ci * hit, but we leave it as a fallback in case. 4038c2ecf20Sopenharmony_ci */ 4048c2ecf20Sopenharmony_ci mask |= CNST_EBB_MASK; 4058c2ecf20Sopenharmony_ci value |= CNST_EBB_VAL(ebb); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci *maskp = mask; 4088c2ecf20Sopenharmony_ci *valp = value; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci return 0; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ciint isa207_compute_mmcr(u64 event[], int n_ev, 4148c2ecf20Sopenharmony_ci unsigned int hwc[], struct mmcr_regs *mmcr, 4158c2ecf20Sopenharmony_ci struct perf_event *pevents[]) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val; 4188c2ecf20Sopenharmony_ci unsigned long mmcr3; 4198c2ecf20Sopenharmony_ci unsigned int pmc, pmc_inuse; 4208c2ecf20Sopenharmony_ci int i; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci pmc_inuse = 0; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* First pass to count resource use */ 4258c2ecf20Sopenharmony_ci for (i = 0; i < n_ev; ++i) { 4268c2ecf20Sopenharmony_ci pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 4278c2ecf20Sopenharmony_ci if (pmc) 4288c2ecf20Sopenharmony_ci pmc_inuse |= 1 << pmc; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci mmcra = mmcr1 = mmcr2 = mmcr3 = 0; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * Disable bhrb unless explicitly requested 4358c2ecf20Sopenharmony_ci * by setting MMCRA (BHRBRD) bit. 4368c2ecf20Sopenharmony_ci */ 4378c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 4388c2ecf20Sopenharmony_ci mmcra |= MMCRA_BHRB_DISABLE; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci /* Second pass: assign PMCs, set all MMCR1 fields */ 4418c2ecf20Sopenharmony_ci for (i = 0; i < n_ev; ++i) { 4428c2ecf20Sopenharmony_ci pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 4438c2ecf20Sopenharmony_ci unit = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; 4448c2ecf20Sopenharmony_ci combine = combine_from_event(event[i]); 4458c2ecf20Sopenharmony_ci psel = event[i] & EVENT_PSEL_MASK; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci if (!pmc) { 4488c2ecf20Sopenharmony_ci for (pmc = 1; pmc <= 4; ++pmc) { 4498c2ecf20Sopenharmony_ci if (!(pmc_inuse & (1 << pmc))) 4508c2ecf20Sopenharmony_ci break; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci pmc_inuse |= 1 << pmc; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (pmc <= 4) { 4578c2ecf20Sopenharmony_ci mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc); 4588c2ecf20Sopenharmony_ci mmcr1 |= combine << combine_shift(pmc); 4598c2ecf20Sopenharmony_ci mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc); 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci /* In continuous sampling mode, update SDAR on TLB miss */ 4638c2ecf20Sopenharmony_ci mmcra_sdar_mode(event[i], &mmcra); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_300)) { 4668c2ecf20Sopenharmony_ci cache = dc_ic_rld_quad_l1_sel(event[i]); 4678c2ecf20Sopenharmony_ci mmcr1 |= (cache) << MMCR1_DC_IC_QUAL_SHIFT; 4688c2ecf20Sopenharmony_ci } else { 4698c2ecf20Sopenharmony_ci if (event[i] & EVENT_IS_L1) { 4708c2ecf20Sopenharmony_ci cache = dc_ic_rld_quad_l1_sel(event[i]); 4718c2ecf20Sopenharmony_ci mmcr1 |= (cache) << MMCR1_DC_IC_QUAL_SHIFT; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci /* Set RADIX_SCOPE_QUAL bit */ 4768c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) { 4778c2ecf20Sopenharmony_ci val = (event[i] >> p10_EVENT_RADIX_SCOPE_QUAL_SHIFT) & 4788c2ecf20Sopenharmony_ci p10_EVENT_RADIX_SCOPE_QUAL_MASK; 4798c2ecf20Sopenharmony_ci mmcr1 |= val << p10_MMCR1_RADIX_SCOPE_QUAL_SHIFT; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci if (is_event_marked(event[i])) { 4838c2ecf20Sopenharmony_ci mmcra |= MMCRA_SAMPLE_ENABLE; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK; 4868c2ecf20Sopenharmony_ci if (val) { 4878c2ecf20Sopenharmony_ci mmcra |= (val & 3) << MMCRA_SAMP_MODE_SHIFT; 4888c2ecf20Sopenharmony_ci mmcra |= (val >> 2) << MMCRA_SAMP_ELIG_SHIFT; 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci /* 4938c2ecf20Sopenharmony_ci * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, 4948c2ecf20Sopenharmony_ci * the threshold bits are used for the match value. 4958c2ecf20Sopenharmony_ci */ 4968c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_300) && event_is_fab_match(event[i])) { 4978c2ecf20Sopenharmony_ci mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & 4988c2ecf20Sopenharmony_ci EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; 4998c2ecf20Sopenharmony_ci } else { 5008c2ecf20Sopenharmony_ci val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK; 5018c2ecf20Sopenharmony_ci mmcra |= val << MMCRA_THR_CTL_SHIFT; 5028c2ecf20Sopenharmony_ci val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; 5038c2ecf20Sopenharmony_ci mmcra |= val << MMCRA_THR_SEL_SHIFT; 5048c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 5058c2ecf20Sopenharmony_ci val = (event[i] >> EVENT_THR_CMP_SHIFT) & 5068c2ecf20Sopenharmony_ci EVENT_THR_CMP_MASK; 5078c2ecf20Sopenharmony_ci mmcra |= thresh_cmp_val(val); 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31) && (unit == 6)) { 5128c2ecf20Sopenharmony_ci val = (event[i] >> p10_L2L3_EVENT_SHIFT) & 5138c2ecf20Sopenharmony_ci p10_EVENT_L2L3_SEL_MASK; 5148c2ecf20Sopenharmony_ci mmcr2 |= val << p10_L2L3_SEL_SHIFT; 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (event[i] & EVENT_WANTS_BHRB) { 5188c2ecf20Sopenharmony_ci val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK; 5198c2ecf20Sopenharmony_ci mmcra |= val << MMCRA_IFM_SHIFT; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* set MMCRA (BHRBRD) to 0 if there is user request for BHRB */ 5238c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31) && 5248c2ecf20Sopenharmony_ci (has_branch_stack(pevents[i]) || (event[i] & EVENT_WANTS_BHRB))) 5258c2ecf20Sopenharmony_ci mmcra &= ~MMCRA_BHRB_DISABLE; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci if (pevents[i]->attr.exclude_user) 5288c2ecf20Sopenharmony_ci mmcr2 |= MMCR2_FCP(pmc); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (pevents[i]->attr.exclude_hv) 5318c2ecf20Sopenharmony_ci mmcr2 |= MMCR2_FCH(pmc); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (pevents[i]->attr.exclude_kernel) { 5348c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_HVMODE)) 5358c2ecf20Sopenharmony_ci mmcr2 |= MMCR2_FCH(pmc); 5368c2ecf20Sopenharmony_ci else 5378c2ecf20Sopenharmony_ci mmcr2 |= MMCR2_FCS(pmc); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) { 5418c2ecf20Sopenharmony_ci if (pmc <= 4) { 5428c2ecf20Sopenharmony_ci val = (event[i] >> p10_EVENT_MMCR3_SHIFT) & 5438c2ecf20Sopenharmony_ci p10_EVENT_MMCR3_MASK; 5448c2ecf20Sopenharmony_ci mmcr3 |= val << MMCR3_SHIFT(pmc); 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci hwc[i] = pmc - 1; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci /* Return MMCRx values */ 5528c2ecf20Sopenharmony_ci mmcr->mmcr0 = 0; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* pmc_inuse is 1-based */ 5558c2ecf20Sopenharmony_ci if (pmc_inuse & 2) 5568c2ecf20Sopenharmony_ci mmcr->mmcr0 = MMCR0_PMC1CE; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (pmc_inuse & 0x7c) 5598c2ecf20Sopenharmony_ci mmcr->mmcr0 |= MMCR0_PMCjCE; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci /* If we're not using PMC 5 or 6, freeze them */ 5628c2ecf20Sopenharmony_ci if (!(pmc_inuse & 0x60)) 5638c2ecf20Sopenharmony_ci mmcr->mmcr0 |= MMCR0_FC56; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* 5668c2ecf20Sopenharmony_ci * Set mmcr0 (PMCCEXT) for p10 which 5678c2ecf20Sopenharmony_ci * will restrict access to group B registers 5688c2ecf20Sopenharmony_ci * when MMCR0 PMCC=0b00. 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_31)) 5718c2ecf20Sopenharmony_ci mmcr->mmcr0 |= MMCR0_PMCCEXT; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci mmcr->mmcr1 = mmcr1; 5748c2ecf20Sopenharmony_ci mmcr->mmcra = mmcra; 5758c2ecf20Sopenharmony_ci mmcr->mmcr2 = mmcr2; 5768c2ecf20Sopenharmony_ci mmcr->mmcr3 = mmcr3; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci return 0; 5798c2ecf20Sopenharmony_ci} 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_civoid isa207_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci if (pmc <= 3) 5848c2ecf20Sopenharmony_ci mmcr->mmcr1 &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1)); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic int find_alternative(u64 event, const unsigned int ev_alt[][MAX_ALT], int size) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci int i, j; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci for (i = 0; i < size; ++i) { 5928c2ecf20Sopenharmony_ci if (event < ev_alt[i][0]) 5938c2ecf20Sopenharmony_ci break; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci for (j = 0; j < MAX_ALT && ev_alt[i][j]; ++j) 5968c2ecf20Sopenharmony_ci if (event == ev_alt[i][j]) 5978c2ecf20Sopenharmony_ci return i; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci return -1; 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ciint isa207_get_alternatives(u64 event, u64 alt[], int size, unsigned int flags, 6048c2ecf20Sopenharmony_ci const unsigned int ev_alt[][MAX_ALT]) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci int i, j, num_alt = 0; 6078c2ecf20Sopenharmony_ci u64 alt_event; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci alt[num_alt++] = event; 6108c2ecf20Sopenharmony_ci i = find_alternative(event, ev_alt, size); 6118c2ecf20Sopenharmony_ci if (i >= 0) { 6128c2ecf20Sopenharmony_ci /* Filter out the original event, it's already in alt[0] */ 6138c2ecf20Sopenharmony_ci for (j = 0; j < MAX_ALT; ++j) { 6148c2ecf20Sopenharmony_ci alt_event = ev_alt[i][j]; 6158c2ecf20Sopenharmony_ci if (alt_event && alt_event != event) 6168c2ecf20Sopenharmony_ci alt[num_alt++] = alt_event; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (flags & PPMU_ONLY_COUNT_RUN) { 6218c2ecf20Sopenharmony_ci /* 6228c2ecf20Sopenharmony_ci * We're only counting in RUN state, so PM_CYC is equivalent to 6238c2ecf20Sopenharmony_ci * PM_RUN_CYC and PM_INST_CMPL === PM_RUN_INST_CMPL. 6248c2ecf20Sopenharmony_ci */ 6258c2ecf20Sopenharmony_ci j = num_alt; 6268c2ecf20Sopenharmony_ci for (i = 0; i < num_alt; ++i) { 6278c2ecf20Sopenharmony_ci switch (alt[i]) { 6288c2ecf20Sopenharmony_ci case 0x1e: /* PMC_CYC */ 6298c2ecf20Sopenharmony_ci alt[j++] = 0x600f4; /* PM_RUN_CYC */ 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci case 0x600f4: 6328c2ecf20Sopenharmony_ci alt[j++] = 0x1e; 6338c2ecf20Sopenharmony_ci break; 6348c2ecf20Sopenharmony_ci case 0x2: /* PM_INST_CMPL */ 6358c2ecf20Sopenharmony_ci alt[j++] = 0x500fa; /* PM_RUN_INST_CMPL */ 6368c2ecf20Sopenharmony_ci break; 6378c2ecf20Sopenharmony_ci case 0x500fa: 6388c2ecf20Sopenharmony_ci alt[j++] = 0x2; 6398c2ecf20Sopenharmony_ci break; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci num_alt = j; 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci return num_alt; 6468c2ecf20Sopenharmony_ci} 647