12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 27ffd948fSMadhavan Srinivasan /* 37ffd948fSMadhavan Srinivasan * Common Performance counter support functions for PowerISA v2.07 processors. 47ffd948fSMadhavan Srinivasan * 57ffd948fSMadhavan Srinivasan * Copyright 2009 Paul Mackerras, IBM Corporation. 67ffd948fSMadhavan Srinivasan * Copyright 2013 Michael Ellerman, IBM Corporation. 77ffd948fSMadhavan Srinivasan * Copyright 2016 Madhavan Srinivasan, IBM Corporation. 87ffd948fSMadhavan Srinivasan */ 97ffd948fSMadhavan Srinivasan #include "isa207-common.h" 107ffd948fSMadhavan Srinivasan 1160b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(event, "config:0-49"); 1260b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(pmcxsel, "config:0-7"); 1360b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(mark, "config:8"); 1460b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(combine, "config:11"); 1560b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(unit, "config:12-15"); 1660b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(pmc, "config:16-19"); 1760b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(cache_sel, "config:20-23"); 1860b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(sample_mode, "config:24-28"); 1960b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(thresh_sel, "config:29-31"); 2060b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(thresh_stop, "config:32-35"); 2160b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(thresh_start, "config:36-39"); 2260b00025SMadhavan Srinivasan PMU_FORMAT_ATTR(thresh_cmp, "config:40-49"); 2360b00025SMadhavan Srinivasan 2460b00025SMadhavan Srinivasan struct attribute *isa207_pmu_format_attr[] = { 2560b00025SMadhavan Srinivasan &format_attr_event.attr, 2660b00025SMadhavan Srinivasan &format_attr_pmcxsel.attr, 2760b00025SMadhavan Srinivasan &format_attr_mark.attr, 2860b00025SMadhavan Srinivasan &format_attr_combine.attr, 2960b00025SMadhavan Srinivasan &format_attr_unit.attr, 3060b00025SMadhavan Srinivasan &format_attr_pmc.attr, 3160b00025SMadhavan Srinivasan &format_attr_cache_sel.attr, 3260b00025SMadhavan Srinivasan &format_attr_sample_mode.attr, 3360b00025SMadhavan Srinivasan &format_attr_thresh_sel.attr, 3460b00025SMadhavan Srinivasan &format_attr_thresh_stop.attr, 3560b00025SMadhavan Srinivasan &format_attr_thresh_start.attr, 3660b00025SMadhavan Srinivasan &format_attr_thresh_cmp.attr, 3760b00025SMadhavan Srinivasan NULL, 3860b00025SMadhavan Srinivasan }; 3960b00025SMadhavan Srinivasan 4060b00025SMadhavan Srinivasan struct attribute_group isa207_pmu_format_group = { 4160b00025SMadhavan Srinivasan .name = "format", 4260b00025SMadhavan Srinivasan .attrs = isa207_pmu_format_attr, 4360b00025SMadhavan Srinivasan }; 4460b00025SMadhavan Srinivasan 457ffd948fSMadhavan Srinivasan static inline bool event_is_fab_match(u64 event) 467ffd948fSMadhavan Srinivasan { 477ffd948fSMadhavan Srinivasan /* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */ 487ffd948fSMadhavan Srinivasan event &= 0xff0fe; 497ffd948fSMadhavan Srinivasan 507ffd948fSMadhavan Srinivasan /* PM_MRK_FAB_RSP_MATCH & PM_MRK_FAB_RSP_MATCH_CYC */ 517ffd948fSMadhavan Srinivasan return (event == 0x30056 || event == 0x4f052); 527ffd948fSMadhavan Srinivasan } 537ffd948fSMadhavan Srinivasan 54c7c3f568SMadhavan Srinivasan static bool is_event_valid(u64 event) 55c7c3f568SMadhavan Srinivasan { 56c7c3f568SMadhavan Srinivasan u64 valid_mask = EVENT_VALID_MASK; 57c7c3f568SMadhavan Srinivasan 58a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) 59a64e697cSAthira Rajeev valid_mask = p10_EVENT_VALID_MASK; 60a64e697cSAthira Rajeev else if (cpu_has_feature(CPU_FTR_ARCH_300)) 61c7c3f568SMadhavan Srinivasan valid_mask = p9_EVENT_VALID_MASK; 62c7c3f568SMadhavan Srinivasan 63c7c3f568SMadhavan Srinivasan return !(event & ~valid_mask); 64c7c3f568SMadhavan Srinivasan } 65c7c3f568SMadhavan Srinivasan 6678b4416aSMadhavan Srinivasan static inline bool is_event_marked(u64 event) 67c7c3f568SMadhavan Srinivasan { 6878b4416aSMadhavan Srinivasan if (event & EVENT_IS_MARKED) 6978b4416aSMadhavan Srinivasan return true; 70c7c3f568SMadhavan Srinivasan 7178b4416aSMadhavan Srinivasan return false; 7278b4416aSMadhavan Srinivasan } 7378b4416aSMadhavan Srinivasan 74a64e697cSAthira Rajeev static unsigned long sdar_mod_val(u64 event) 75a64e697cSAthira Rajeev { 76a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) 77a64e697cSAthira Rajeev return p10_SDAR_MODE(event); 78a64e697cSAthira Rajeev 79a64e697cSAthira Rajeev return p9_SDAR_MODE(event); 80a64e697cSAthira Rajeev } 81a64e697cSAthira Rajeev 8278b4416aSMadhavan Srinivasan static void mmcra_sdar_mode(u64 event, unsigned long *mmcra) 8378b4416aSMadhavan Srinivasan { 8478b4416aSMadhavan Srinivasan /* 8578b4416aSMadhavan Srinivasan * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in 8678b4416aSMadhavan Srinivasan * continous sampling mode. 8778b4416aSMadhavan Srinivasan * 8878b4416aSMadhavan Srinivasan * Incase of Power8: 8978b4416aSMadhavan Srinivasan * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling 9078b4416aSMadhavan Srinivasan * mode and will be un-changed when setting MMCRA[63] (Marked events). 9178b4416aSMadhavan Srinivasan * 92a64e697cSAthira Rajeev * Incase of Power9/power10: 9378b4416aSMadhavan Srinivasan * Marked event: MMCRA[SDAR_MODE] will be set to 0b00 ('No Updates'), 9478b4416aSMadhavan Srinivasan * or if group already have any marked events. 9578b4416aSMadhavan Srinivasan * For rest 9678b4416aSMadhavan Srinivasan * MMCRA[SDAR_MODE] will be set from event code. 9720dd4c62SMadhavan Srinivasan * If sdar_mode from event is zero, default to 0b01. Hardware 9820dd4c62SMadhavan Srinivasan * requires that we set a non-zero value. 9978b4416aSMadhavan Srinivasan */ 10078b4416aSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_ARCH_300)) { 10178b4416aSMadhavan Srinivasan if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE)) 10278b4416aSMadhavan Srinivasan *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES; 103a64e697cSAthira Rajeev else if (sdar_mod_val(event)) 104a64e697cSAthira Rajeev *mmcra |= sdar_mod_val(event) << MMCRA_SDAR_MODE_SHIFT; 10520dd4c62SMadhavan Srinivasan else 1067aa345d8SMadhavan Srinivasan *mmcra |= MMCRA_SDAR_MODE_DCACHE; 10778b4416aSMadhavan Srinivasan } else 10878b4416aSMadhavan Srinivasan *mmcra |= MMCRA_SDAR_MODE_TLB; 109c7c3f568SMadhavan Srinivasan } 110c7c3f568SMadhavan Srinivasan 111c7c3f568SMadhavan Srinivasan static u64 thresh_cmp_val(u64 value) 112c7c3f568SMadhavan Srinivasan { 1132bf1071aSNicholas Piggin if (cpu_has_feature(CPU_FTR_ARCH_300)) 114c7c3f568SMadhavan Srinivasan return value << p9_MMCRA_THR_CMP_SHIFT; 115c7c3f568SMadhavan Srinivasan 116c7c3f568SMadhavan Srinivasan return value << MMCRA_THR_CMP_SHIFT; 117c7c3f568SMadhavan Srinivasan } 118c7c3f568SMadhavan Srinivasan 119c7c3f568SMadhavan Srinivasan static unsigned long combine_from_event(u64 event) 120c7c3f568SMadhavan Srinivasan { 1212bf1071aSNicholas Piggin if (cpu_has_feature(CPU_FTR_ARCH_300)) 122c7c3f568SMadhavan Srinivasan return p9_EVENT_COMBINE(event); 123c7c3f568SMadhavan Srinivasan 124c7c3f568SMadhavan Srinivasan return EVENT_COMBINE(event); 125c7c3f568SMadhavan Srinivasan } 126c7c3f568SMadhavan Srinivasan 127c7c3f568SMadhavan Srinivasan static unsigned long combine_shift(unsigned long pmc) 128c7c3f568SMadhavan Srinivasan { 1292bf1071aSNicholas Piggin if (cpu_has_feature(CPU_FTR_ARCH_300)) 130c7c3f568SMadhavan Srinivasan return p9_MMCR1_COMBINE_SHIFT(pmc); 131c7c3f568SMadhavan Srinivasan 132c7c3f568SMadhavan Srinivasan return MMCR1_COMBINE_SHIFT(pmc); 133c7c3f568SMadhavan Srinivasan } 134c7c3f568SMadhavan Srinivasan 13578a16d9fSMadhavan Srinivasan static inline bool event_is_threshold(u64 event) 13678a16d9fSMadhavan Srinivasan { 13778a16d9fSMadhavan Srinivasan return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; 13878a16d9fSMadhavan Srinivasan } 13978a16d9fSMadhavan Srinivasan 14078a16d9fSMadhavan Srinivasan static bool is_thresh_cmp_valid(u64 event) 14178a16d9fSMadhavan Srinivasan { 14278a16d9fSMadhavan Srinivasan unsigned int cmp, exp; 14378a16d9fSMadhavan Srinivasan 14478a16d9fSMadhavan Srinivasan /* 14578a16d9fSMadhavan Srinivasan * Check the mantissa upper two bits are not zero, unless the 14678a16d9fSMadhavan Srinivasan * exponent is also zero. See the THRESH_CMP_MANTISSA doc. 147a64e697cSAthira Rajeev * Power10: thresh_cmp is replaced by l2_l3 event select. 14878a16d9fSMadhavan Srinivasan */ 149a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) 150a64e697cSAthira Rajeev return false; 151a64e697cSAthira Rajeev 15278a16d9fSMadhavan Srinivasan cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK; 15378a16d9fSMadhavan Srinivasan exp = cmp >> 7; 15478a16d9fSMadhavan Srinivasan 15578a16d9fSMadhavan Srinivasan if (exp && (cmp & 0x60) == 0) 15678a16d9fSMadhavan Srinivasan return false; 15778a16d9fSMadhavan Srinivasan 15878a16d9fSMadhavan Srinivasan return true; 15978a16d9fSMadhavan Srinivasan } 16078a16d9fSMadhavan Srinivasan 1612d46d487SMadhavan Srinivasan static unsigned int dc_ic_rld_quad_l1_sel(u64 event) 1622d46d487SMadhavan Srinivasan { 1632d46d487SMadhavan Srinivasan unsigned int cache; 1642d46d487SMadhavan Srinivasan 1652d46d487SMadhavan Srinivasan cache = (event >> EVENT_CACHE_SEL_SHIFT) & MMCR1_DC_IC_QUAL_MASK; 1662d46d487SMadhavan Srinivasan return cache; 1672d46d487SMadhavan Srinivasan } 1682d46d487SMadhavan Srinivasan 16979e96f8fSMadhavan Srinivasan static inline u64 isa207_find_source(u64 idx, u32 sub_idx) 17079e96f8fSMadhavan Srinivasan { 17179e96f8fSMadhavan Srinivasan u64 ret = PERF_MEM_NA; 17279e96f8fSMadhavan Srinivasan 17379e96f8fSMadhavan Srinivasan switch(idx) { 17479e96f8fSMadhavan Srinivasan case 0: 17579e96f8fSMadhavan Srinivasan /* Nothing to do */ 17679e96f8fSMadhavan Srinivasan break; 17779e96f8fSMadhavan Srinivasan case 1: 17879e96f8fSMadhavan Srinivasan ret = PH(LVL, L1); 17979e96f8fSMadhavan Srinivasan break; 18079e96f8fSMadhavan Srinivasan case 2: 18179e96f8fSMadhavan Srinivasan ret = PH(LVL, L2); 18279e96f8fSMadhavan Srinivasan break; 18379e96f8fSMadhavan Srinivasan case 3: 18479e96f8fSMadhavan Srinivasan ret = PH(LVL, L3); 18579e96f8fSMadhavan Srinivasan break; 18679e96f8fSMadhavan Srinivasan case 4: 18779e96f8fSMadhavan Srinivasan if (sub_idx <= 1) 18879e96f8fSMadhavan Srinivasan ret = PH(LVL, LOC_RAM); 18979e96f8fSMadhavan Srinivasan else if (sub_idx > 1 && sub_idx <= 2) 19079e96f8fSMadhavan Srinivasan ret = PH(LVL, REM_RAM1); 19179e96f8fSMadhavan Srinivasan else 19279e96f8fSMadhavan Srinivasan ret = PH(LVL, REM_RAM2); 19379e96f8fSMadhavan Srinivasan ret |= P(SNOOP, HIT); 19479e96f8fSMadhavan Srinivasan break; 19579e96f8fSMadhavan Srinivasan case 5: 19679e96f8fSMadhavan Srinivasan ret = PH(LVL, REM_CCE1); 19779e96f8fSMadhavan Srinivasan if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4)) 19879e96f8fSMadhavan Srinivasan ret |= P(SNOOP, HIT); 19979e96f8fSMadhavan Srinivasan else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5)) 20079e96f8fSMadhavan Srinivasan ret |= P(SNOOP, HITM); 20179e96f8fSMadhavan Srinivasan break; 20279e96f8fSMadhavan Srinivasan case 6: 20379e96f8fSMadhavan Srinivasan ret = PH(LVL, REM_CCE2); 20479e96f8fSMadhavan Srinivasan if ((sub_idx == 0) || (sub_idx == 2)) 20579e96f8fSMadhavan Srinivasan ret |= P(SNOOP, HIT); 20679e96f8fSMadhavan Srinivasan else if ((sub_idx == 1) || (sub_idx == 3)) 20779e96f8fSMadhavan Srinivasan ret |= P(SNOOP, HITM); 20879e96f8fSMadhavan Srinivasan break; 20979e96f8fSMadhavan Srinivasan case 7: 21079e96f8fSMadhavan Srinivasan ret = PM(LVL, L1); 21179e96f8fSMadhavan Srinivasan break; 21279e96f8fSMadhavan Srinivasan } 21379e96f8fSMadhavan Srinivasan 21479e96f8fSMadhavan Srinivasan return ret; 21579e96f8fSMadhavan Srinivasan } 21679e96f8fSMadhavan Srinivasan 21779e96f8fSMadhavan Srinivasan void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags, 21879e96f8fSMadhavan Srinivasan struct pt_regs *regs) 21979e96f8fSMadhavan Srinivasan { 22079e96f8fSMadhavan Srinivasan u64 idx; 22179e96f8fSMadhavan Srinivasan u32 sub_idx; 22279e96f8fSMadhavan Srinivasan u64 sier; 22379e96f8fSMadhavan Srinivasan u64 val; 22479e96f8fSMadhavan Srinivasan 22579e96f8fSMadhavan Srinivasan /* Skip if no SIER support */ 22679e96f8fSMadhavan Srinivasan if (!(flags & PPMU_HAS_SIER)) { 22779e96f8fSMadhavan Srinivasan dsrc->val = 0; 22879e96f8fSMadhavan Srinivasan return; 22979e96f8fSMadhavan Srinivasan } 23079e96f8fSMadhavan Srinivasan 23179e96f8fSMadhavan Srinivasan sier = mfspr(SPRN_SIER); 23279e96f8fSMadhavan Srinivasan val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; 23379e96f8fSMadhavan Srinivasan if (val == 1 || val == 2) { 23479e96f8fSMadhavan Srinivasan idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT; 23579e96f8fSMadhavan Srinivasan sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> ISA207_SIER_DATA_SRC_SHIFT; 23679e96f8fSMadhavan Srinivasan 23779e96f8fSMadhavan Srinivasan dsrc->val = isa207_find_source(idx, sub_idx); 23879e96f8fSMadhavan Srinivasan dsrc->val |= (val == 1) ? P(OP, LOAD) : P(OP, STORE); 23979e96f8fSMadhavan Srinivasan } 24079e96f8fSMadhavan Srinivasan } 24179e96f8fSMadhavan Srinivasan 242170a315fSMadhavan Srinivasan void isa207_get_mem_weight(u64 *weight) 243170a315fSMadhavan Srinivasan { 244170a315fSMadhavan Srinivasan u64 mmcra = mfspr(SPRN_MMCRA); 245170a315fSMadhavan Srinivasan u64 exp = MMCRA_THR_CTR_EXP(mmcra); 246170a315fSMadhavan Srinivasan u64 mantissa = MMCRA_THR_CTR_MANT(mmcra); 24717cfccc9SMadhavan Srinivasan u64 sier = mfspr(SPRN_SIER); 24817cfccc9SMadhavan Srinivasan u64 val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT; 249170a315fSMadhavan Srinivasan 25017cfccc9SMadhavan Srinivasan if (val == 0 || val == 7) 25117cfccc9SMadhavan Srinivasan *weight = 0; 25217cfccc9SMadhavan Srinivasan else 253170a315fSMadhavan Srinivasan *weight = mantissa << (2 * exp); 254170a315fSMadhavan Srinivasan } 25579e96f8fSMadhavan Srinivasan 2567ffd948fSMadhavan Srinivasan int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp) 2577ffd948fSMadhavan Srinivasan { 2587ffd948fSMadhavan Srinivasan unsigned int unit, pmc, cache, ebb; 2597ffd948fSMadhavan Srinivasan unsigned long mask, value; 2607ffd948fSMadhavan Srinivasan 2617ffd948fSMadhavan Srinivasan mask = value = 0; 2627ffd948fSMadhavan Srinivasan 263c7c3f568SMadhavan Srinivasan if (!is_event_valid(event)) 2647ffd948fSMadhavan Srinivasan return -1; 2657ffd948fSMadhavan Srinivasan 2667ffd948fSMadhavan Srinivasan pmc = (event >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 2677ffd948fSMadhavan Srinivasan unit = (event >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; 268a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) 269a64e697cSAthira Rajeev cache = (event >> EVENT_CACHE_SEL_SHIFT) & 270a64e697cSAthira Rajeev p10_EVENT_CACHE_SEL_MASK; 271a64e697cSAthira Rajeev else 272a64e697cSAthira Rajeev cache = (event >> EVENT_CACHE_SEL_SHIFT) & 273a64e697cSAthira Rajeev EVENT_CACHE_SEL_MASK; 2747ffd948fSMadhavan Srinivasan ebb = (event >> EVENT_EBB_SHIFT) & EVENT_EBB_MASK; 2757ffd948fSMadhavan Srinivasan 2767ffd948fSMadhavan Srinivasan if (pmc) { 2777ffd948fSMadhavan Srinivasan u64 base_event; 2787ffd948fSMadhavan Srinivasan 2797ffd948fSMadhavan Srinivasan if (pmc > 6) 2807ffd948fSMadhavan Srinivasan return -1; 2817ffd948fSMadhavan Srinivasan 2827ffd948fSMadhavan Srinivasan /* Ignore Linux defined bits when checking event below */ 2837ffd948fSMadhavan Srinivasan base_event = event & ~EVENT_LINUX_MASK; 2847ffd948fSMadhavan Srinivasan 2857ffd948fSMadhavan Srinivasan if (pmc >= 5 && base_event != 0x500fa && 2867ffd948fSMadhavan Srinivasan base_event != 0x600f4) 2877ffd948fSMadhavan Srinivasan return -1; 2887ffd948fSMadhavan Srinivasan 2897ffd948fSMadhavan Srinivasan mask |= CNST_PMC_MASK(pmc); 2907ffd948fSMadhavan Srinivasan value |= CNST_PMC_VAL(pmc); 2913b6c3adbSAthira Rajeev 2923b6c3adbSAthira Rajeev /* 2933b6c3adbSAthira Rajeev * PMC5 and PMC6 are used to count cycles and instructions and 2943b6c3adbSAthira Rajeev * they do not support most of the constraint bits. Add a check 2953b6c3adbSAthira Rajeev * to exclude PMC5/6 from most of the constraints except for 2963b6c3adbSAthira Rajeev * EBB/BHRB. 2973b6c3adbSAthira Rajeev */ 2983b6c3adbSAthira Rajeev if (pmc >= 5) 2993b6c3adbSAthira Rajeev goto ebb_bhrb; 3007ffd948fSMadhavan Srinivasan } 3017ffd948fSMadhavan Srinivasan 3027ffd948fSMadhavan Srinivasan if (pmc <= 4) { 3037ffd948fSMadhavan Srinivasan /* 3047ffd948fSMadhavan Srinivasan * Add to number of counters in use. Note this includes events with 3057ffd948fSMadhavan Srinivasan * a PMC of 0 - they still need a PMC, it's just assigned later. 3067ffd948fSMadhavan Srinivasan * Don't count events on PMC 5 & 6, there is only one valid event 3077ffd948fSMadhavan Srinivasan * on each of those counters, and they are handled above. 3087ffd948fSMadhavan Srinivasan */ 3097ffd948fSMadhavan Srinivasan mask |= CNST_NC_MASK; 3107ffd948fSMadhavan Srinivasan value |= CNST_NC_VAL; 3117ffd948fSMadhavan Srinivasan } 3127ffd948fSMadhavan Srinivasan 3137ffd948fSMadhavan Srinivasan if (unit >= 6 && unit <= 9) { 314*e924be7bSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) { 315*e924be7bSAthira Rajeev if (unit == 6) { 316a64e697cSAthira Rajeev mask |= CNST_L2L3_GROUP_MASK; 317a64e697cSAthira Rajeev value |= CNST_L2L3_GROUP_VAL(event >> p10_L2L3_EVENT_SHIFT); 318*e924be7bSAthira Rajeev } 319a64e697cSAthira Rajeev } else if (cpu_has_feature(CPU_FTR_ARCH_300)) { 32059029136SMadhavan Srinivasan mask |= CNST_CACHE_GROUP_MASK; 32159029136SMadhavan Srinivasan value |= CNST_CACHE_GROUP_VAL(event & 0xff); 32259029136SMadhavan Srinivasan 32359029136SMadhavan Srinivasan mask |= CNST_CACHE_PMC4_MASK; 32459029136SMadhavan Srinivasan if (pmc == 4) 32559029136SMadhavan Srinivasan value |= CNST_CACHE_PMC4_VAL; 32659029136SMadhavan Srinivasan } else if (cache & 0x7) { 3277ffd948fSMadhavan Srinivasan /* 3287ffd948fSMadhavan Srinivasan * L2/L3 events contain a cache selector field, which is 3297ffd948fSMadhavan Srinivasan * supposed to be programmed into MMCRC. However MMCRC is only 3307ffd948fSMadhavan Srinivasan * HV writable, and there is no API for guest kernels to modify 3317ffd948fSMadhavan Srinivasan * it. The solution is for the hypervisor to initialise the 3327ffd948fSMadhavan Srinivasan * field to zeroes, and for us to only ever allow events that 3337ffd948fSMadhavan Srinivasan * have a cache selector of zero. The bank selector (bit 3) is 3347ffd948fSMadhavan Srinivasan * irrelevant, as long as the rest of the value is 0. 3357ffd948fSMadhavan Srinivasan */ 3367ffd948fSMadhavan Srinivasan return -1; 33759029136SMadhavan Srinivasan } 3387ffd948fSMadhavan Srinivasan 3392d46d487SMadhavan Srinivasan } else if (cpu_has_feature(CPU_FTR_ARCH_300) || (event & EVENT_IS_L1)) { 3407ffd948fSMadhavan Srinivasan mask |= CNST_L1_QUAL_MASK; 3417ffd948fSMadhavan Srinivasan value |= CNST_L1_QUAL_VAL(cache); 3427ffd948fSMadhavan Srinivasan } 3437ffd948fSMadhavan Srinivasan 344d3afd28cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) { 345d3afd28cSAthira Rajeev mask |= CNST_RADIX_SCOPE_GROUP_MASK; 346d3afd28cSAthira Rajeev value |= CNST_RADIX_SCOPE_GROUP_VAL(event >> p10_EVENT_RADIX_SCOPE_QUAL_SHIFT); 347d3afd28cSAthira Rajeev } 348d3afd28cSAthira Rajeev 34978b4416aSMadhavan Srinivasan if (is_event_marked(event)) { 3507ffd948fSMadhavan Srinivasan mask |= CNST_SAMPLE_MASK; 3517ffd948fSMadhavan Srinivasan value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT); 3527ffd948fSMadhavan Srinivasan } 3537ffd948fSMadhavan Srinivasan 35478a16d9fSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_ARCH_300)) { 35578a16d9fSMadhavan Srinivasan if (event_is_threshold(event) && is_thresh_cmp_valid(event)) { 35678a16d9fSMadhavan Srinivasan mask |= CNST_THRESH_MASK; 35778a16d9fSMadhavan Srinivasan value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); 35878a16d9fSMadhavan Srinivasan } 35978a16d9fSMadhavan Srinivasan } else { 3607ffd948fSMadhavan Srinivasan /* 3617ffd948fSMadhavan Srinivasan * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, 3627ffd948fSMadhavan Srinivasan * the threshold control bits are used for the match value. 3637ffd948fSMadhavan Srinivasan */ 3647ffd948fSMadhavan Srinivasan if (event_is_fab_match(event)) { 3657ffd948fSMadhavan Srinivasan mask |= CNST_FAB_MATCH_MASK; 3667ffd948fSMadhavan Srinivasan value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT); 3677ffd948fSMadhavan Srinivasan } else { 36878a16d9fSMadhavan Srinivasan if (!is_thresh_cmp_valid(event)) 3697ffd948fSMadhavan Srinivasan return -1; 3707ffd948fSMadhavan Srinivasan 3717ffd948fSMadhavan Srinivasan mask |= CNST_THRESH_MASK; 3727ffd948fSMadhavan Srinivasan value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT); 3737ffd948fSMadhavan Srinivasan } 37478a16d9fSMadhavan Srinivasan } 3757ffd948fSMadhavan Srinivasan 3763b6c3adbSAthira Rajeev ebb_bhrb: 3777ffd948fSMadhavan Srinivasan if (!pmc && ebb) 3787ffd948fSMadhavan Srinivasan /* EBB events must specify the PMC */ 3797ffd948fSMadhavan Srinivasan return -1; 3807ffd948fSMadhavan Srinivasan 3817ffd948fSMadhavan Srinivasan if (event & EVENT_WANTS_BHRB) { 3827ffd948fSMadhavan Srinivasan if (!ebb) 3837ffd948fSMadhavan Srinivasan /* Only EBB events can request BHRB */ 3847ffd948fSMadhavan Srinivasan return -1; 3857ffd948fSMadhavan Srinivasan 3867ffd948fSMadhavan Srinivasan mask |= CNST_IFM_MASK; 3877ffd948fSMadhavan Srinivasan value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT); 3887ffd948fSMadhavan Srinivasan } 3897ffd948fSMadhavan Srinivasan 3907ffd948fSMadhavan Srinivasan /* 3917ffd948fSMadhavan Srinivasan * All events must agree on EBB, either all request it or none. 3927ffd948fSMadhavan Srinivasan * EBB events are pinned & exclusive, so this should never actually 3937ffd948fSMadhavan Srinivasan * hit, but we leave it as a fallback in case. 3947ffd948fSMadhavan Srinivasan */ 3957ffd948fSMadhavan Srinivasan mask |= CNST_EBB_VAL(ebb); 3967ffd948fSMadhavan Srinivasan value |= CNST_EBB_MASK; 3977ffd948fSMadhavan Srinivasan 3987ffd948fSMadhavan Srinivasan *maskp = mask; 3997ffd948fSMadhavan Srinivasan *valp = value; 4007ffd948fSMadhavan Srinivasan 4017ffd948fSMadhavan Srinivasan return 0; 4027ffd948fSMadhavan Srinivasan } 4037ffd948fSMadhavan Srinivasan 4047ffd948fSMadhavan Srinivasan int isa207_compute_mmcr(u64 event[], int n_ev, 40578d76819SAthira Rajeev unsigned int hwc[], struct mmcr_regs *mmcr, 4067ffd948fSMadhavan Srinivasan struct perf_event *pevents[]) 4077ffd948fSMadhavan Srinivasan { 4087ffd948fSMadhavan Srinivasan unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val; 409a64e697cSAthira Rajeev unsigned long mmcr3; 4107ffd948fSMadhavan Srinivasan unsigned int pmc, pmc_inuse; 4117ffd948fSMadhavan Srinivasan int i; 4127ffd948fSMadhavan Srinivasan 4137ffd948fSMadhavan Srinivasan pmc_inuse = 0; 4147ffd948fSMadhavan Srinivasan 4157ffd948fSMadhavan Srinivasan /* First pass to count resource use */ 4167ffd948fSMadhavan Srinivasan for (i = 0; i < n_ev; ++i) { 4177ffd948fSMadhavan Srinivasan pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 4187ffd948fSMadhavan Srinivasan if (pmc) 4197ffd948fSMadhavan Srinivasan pmc_inuse |= 1 << pmc; 4207ffd948fSMadhavan Srinivasan } 4217ffd948fSMadhavan Srinivasan 422a64e697cSAthira Rajeev mmcra = mmcr1 = mmcr2 = mmcr3 = 0; 4237ffd948fSMadhavan Srinivasan 4241cade527SAthira Rajeev /* 4251cade527SAthira Rajeev * Disable bhrb unless explicitly requested 4261cade527SAthira Rajeev * by setting MMCRA (BHRBRD) bit. 4271cade527SAthira Rajeev */ 4281cade527SAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) 4291cade527SAthira Rajeev mmcra |= MMCRA_BHRB_DISABLE; 4301cade527SAthira Rajeev 4317ffd948fSMadhavan Srinivasan /* Second pass: assign PMCs, set all MMCR1 fields */ 4327ffd948fSMadhavan Srinivasan for (i = 0; i < n_ev; ++i) { 4337ffd948fSMadhavan Srinivasan pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; 4347ffd948fSMadhavan Srinivasan unit = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK; 435c7c3f568SMadhavan Srinivasan combine = combine_from_event(event[i]); 4367ffd948fSMadhavan Srinivasan psel = event[i] & EVENT_PSEL_MASK; 4377ffd948fSMadhavan Srinivasan 4387ffd948fSMadhavan Srinivasan if (!pmc) { 4397ffd948fSMadhavan Srinivasan for (pmc = 1; pmc <= 4; ++pmc) { 4407ffd948fSMadhavan Srinivasan if (!(pmc_inuse & (1 << pmc))) 4417ffd948fSMadhavan Srinivasan break; 4427ffd948fSMadhavan Srinivasan } 4437ffd948fSMadhavan Srinivasan 4447ffd948fSMadhavan Srinivasan pmc_inuse |= 1 << pmc; 4457ffd948fSMadhavan Srinivasan } 4467ffd948fSMadhavan Srinivasan 4477ffd948fSMadhavan Srinivasan if (pmc <= 4) { 4487ffd948fSMadhavan Srinivasan mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc); 449c7c3f568SMadhavan Srinivasan mmcr1 |= combine << combine_shift(pmc); 4507ffd948fSMadhavan Srinivasan mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc); 4517ffd948fSMadhavan Srinivasan } 4527ffd948fSMadhavan Srinivasan 453c7c3f568SMadhavan Srinivasan /* In continuous sampling mode, update SDAR on TLB miss */ 45478b4416aSMadhavan Srinivasan mmcra_sdar_mode(event[i], &mmcra); 455c7c3f568SMadhavan Srinivasan 4562d46d487SMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_ARCH_300)) { 4572d46d487SMadhavan Srinivasan cache = dc_ic_rld_quad_l1_sel(event[i]); 4582d46d487SMadhavan Srinivasan mmcr1 |= (cache) << MMCR1_DC_IC_QUAL_SHIFT; 4592d46d487SMadhavan Srinivasan } else { 4607ffd948fSMadhavan Srinivasan if (event[i] & EVENT_IS_L1) { 4612d46d487SMadhavan Srinivasan cache = dc_ic_rld_quad_l1_sel(event[i]); 4622d46d487SMadhavan Srinivasan mmcr1 |= (cache) << MMCR1_DC_IC_QUAL_SHIFT; 4632d46d487SMadhavan Srinivasan } 4647ffd948fSMadhavan Srinivasan } 4657ffd948fSMadhavan Srinivasan 466d3afd28cSAthira Rajeev /* Set RADIX_SCOPE_QUAL bit */ 467d3afd28cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) { 468d3afd28cSAthira Rajeev val = (event[i] >> p10_EVENT_RADIX_SCOPE_QUAL_SHIFT) & 469d3afd28cSAthira Rajeev p10_EVENT_RADIX_SCOPE_QUAL_MASK; 470d3afd28cSAthira Rajeev mmcr1 |= val << p10_MMCR1_RADIX_SCOPE_QUAL_SHIFT; 471d3afd28cSAthira Rajeev } 472d3afd28cSAthira Rajeev 47378b4416aSMadhavan Srinivasan if (is_event_marked(event[i])) { 4747ffd948fSMadhavan Srinivasan mmcra |= MMCRA_SAMPLE_ENABLE; 4757ffd948fSMadhavan Srinivasan 4767ffd948fSMadhavan Srinivasan val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK; 4777ffd948fSMadhavan Srinivasan if (val) { 4787ffd948fSMadhavan Srinivasan mmcra |= (val & 3) << MMCRA_SAMP_MODE_SHIFT; 4797ffd948fSMadhavan Srinivasan mmcra |= (val >> 2) << MMCRA_SAMP_ELIG_SHIFT; 4807ffd948fSMadhavan Srinivasan } 4817ffd948fSMadhavan Srinivasan } 4827ffd948fSMadhavan Srinivasan 4837ffd948fSMadhavan Srinivasan /* 4847ffd948fSMadhavan Srinivasan * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC, 4857ffd948fSMadhavan Srinivasan * the threshold bits are used for the match value. 4867ffd948fSMadhavan Srinivasan */ 48778a16d9fSMadhavan Srinivasan if (!cpu_has_feature(CPU_FTR_ARCH_300) && event_is_fab_match(event[i])) { 4887ffd948fSMadhavan Srinivasan mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & 4897ffd948fSMadhavan Srinivasan EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; 4907ffd948fSMadhavan Srinivasan } else { 4917ffd948fSMadhavan Srinivasan val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK; 4927ffd948fSMadhavan Srinivasan mmcra |= val << MMCRA_THR_CTL_SHIFT; 4937ffd948fSMadhavan Srinivasan val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK; 4947ffd948fSMadhavan Srinivasan mmcra |= val << MMCRA_THR_SEL_SHIFT; 495a64e697cSAthira Rajeev if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 496a64e697cSAthira Rajeev val = (event[i] >> EVENT_THR_CMP_SHIFT) & 497a64e697cSAthira Rajeev EVENT_THR_CMP_MASK; 498c7c3f568SMadhavan Srinivasan mmcra |= thresh_cmp_val(val); 4997ffd948fSMadhavan Srinivasan } 500a64e697cSAthira Rajeev } 501a64e697cSAthira Rajeev 502a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31) && (unit == 6)) { 503a64e697cSAthira Rajeev val = (event[i] >> p10_L2L3_EVENT_SHIFT) & 504a64e697cSAthira Rajeev p10_EVENT_L2L3_SEL_MASK; 505a64e697cSAthira Rajeev mmcr2 |= val << p10_L2L3_SEL_SHIFT; 506a64e697cSAthira Rajeev } 5077ffd948fSMadhavan Srinivasan 5087ffd948fSMadhavan Srinivasan if (event[i] & EVENT_WANTS_BHRB) { 5097ffd948fSMadhavan Srinivasan val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK; 5107ffd948fSMadhavan Srinivasan mmcra |= val << MMCRA_IFM_SHIFT; 5117ffd948fSMadhavan Srinivasan } 5127ffd948fSMadhavan Srinivasan 5131cade527SAthira Rajeev /* set MMCRA (BHRBRD) to 0 if there is user request for BHRB */ 5141cade527SAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31) && 5151cade527SAthira Rajeev (has_branch_stack(pevents[i]) || (event[i] & EVENT_WANTS_BHRB))) 5161cade527SAthira Rajeev mmcra &= ~MMCRA_BHRB_DISABLE; 5171cade527SAthira Rajeev 5187ffd948fSMadhavan Srinivasan if (pevents[i]->attr.exclude_user) 5197ffd948fSMadhavan Srinivasan mmcr2 |= MMCR2_FCP(pmc); 5207ffd948fSMadhavan Srinivasan 5217ffd948fSMadhavan Srinivasan if (pevents[i]->attr.exclude_hv) 5227ffd948fSMadhavan Srinivasan mmcr2 |= MMCR2_FCH(pmc); 5237ffd948fSMadhavan Srinivasan 5247ffd948fSMadhavan Srinivasan if (pevents[i]->attr.exclude_kernel) { 5257ffd948fSMadhavan Srinivasan if (cpu_has_feature(CPU_FTR_HVMODE)) 5267ffd948fSMadhavan Srinivasan mmcr2 |= MMCR2_FCH(pmc); 5277ffd948fSMadhavan Srinivasan else 5287ffd948fSMadhavan Srinivasan mmcr2 |= MMCR2_FCS(pmc); 5297ffd948fSMadhavan Srinivasan } 5307ffd948fSMadhavan Srinivasan 531a64e697cSAthira Rajeev if (cpu_has_feature(CPU_FTR_ARCH_31)) { 532a64e697cSAthira Rajeev if (pmc <= 4) { 533a64e697cSAthira Rajeev val = (event[i] >> p10_EVENT_MMCR3_SHIFT) & 534a64e697cSAthira Rajeev p10_EVENT_MMCR3_MASK; 535a64e697cSAthira Rajeev mmcr3 |= val << MMCR3_SHIFT(pmc); 536a64e697cSAthira Rajeev } 537a64e697cSAthira Rajeev } 538a64e697cSAthira Rajeev 5397ffd948fSMadhavan Srinivasan hwc[i] = pmc - 1; 5407ffd948fSMadhavan Srinivasan } 5417ffd948fSMadhavan Srinivasan 5427ffd948fSMadhavan Srinivasan /* Return MMCRx values */ 54378d76819SAthira Rajeev mmcr->mmcr0 = 0; 5447ffd948fSMadhavan Srinivasan 5457ffd948fSMadhavan Srinivasan /* pmc_inuse is 1-based */ 5467ffd948fSMadhavan Srinivasan if (pmc_inuse & 2) 54778d76819SAthira Rajeev mmcr->mmcr0 = MMCR0_PMC1CE; 5487ffd948fSMadhavan Srinivasan 5497ffd948fSMadhavan Srinivasan if (pmc_inuse & 0x7c) 55078d76819SAthira Rajeev mmcr->mmcr0 |= MMCR0_PMCjCE; 5517ffd948fSMadhavan Srinivasan 5527ffd948fSMadhavan Srinivasan /* If we're not using PMC 5 or 6, freeze them */ 5537ffd948fSMadhavan Srinivasan if (!(pmc_inuse & 0x60)) 55478d76819SAthira Rajeev mmcr->mmcr0 |= MMCR0_FC56; 5557ffd948fSMadhavan Srinivasan 55678d76819SAthira Rajeev mmcr->mmcr1 = mmcr1; 55778d76819SAthira Rajeev mmcr->mmcra = mmcra; 55878d76819SAthira Rajeev mmcr->mmcr2 = mmcr2; 559a64e697cSAthira Rajeev mmcr->mmcr3 = mmcr3; 5607ffd948fSMadhavan Srinivasan 5617ffd948fSMadhavan Srinivasan return 0; 5627ffd948fSMadhavan Srinivasan } 5637ffd948fSMadhavan Srinivasan 56478d76819SAthira Rajeev void isa207_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr) 5657ffd948fSMadhavan Srinivasan { 5667ffd948fSMadhavan Srinivasan if (pmc <= 3) 56778d76819SAthira Rajeev mmcr->mmcr1 &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1)); 5687ffd948fSMadhavan Srinivasan } 569efe881afSMadhavan Srinivasan 570efe881afSMadhavan Srinivasan static int find_alternative(u64 event, const unsigned int ev_alt[][MAX_ALT], int size) 571efe881afSMadhavan Srinivasan { 572efe881afSMadhavan Srinivasan int i, j; 573efe881afSMadhavan Srinivasan 574efe881afSMadhavan Srinivasan for (i = 0; i < size; ++i) { 575efe881afSMadhavan Srinivasan if (event < ev_alt[i][0]) 576efe881afSMadhavan Srinivasan break; 577efe881afSMadhavan Srinivasan 578efe881afSMadhavan Srinivasan for (j = 0; j < MAX_ALT && ev_alt[i][j]; ++j) 579efe881afSMadhavan Srinivasan if (event == ev_alt[i][j]) 580efe881afSMadhavan Srinivasan return i; 581efe881afSMadhavan Srinivasan } 582efe881afSMadhavan Srinivasan 583efe881afSMadhavan Srinivasan return -1; 584efe881afSMadhavan Srinivasan } 585efe881afSMadhavan Srinivasan 58670a7e720SMadhavan Srinivasan int isa207_get_alternatives(u64 event, u64 alt[], int size, unsigned int flags, 58770a7e720SMadhavan Srinivasan const unsigned int ev_alt[][MAX_ALT]) 588efe881afSMadhavan Srinivasan { 589efe881afSMadhavan Srinivasan int i, j, num_alt = 0; 590efe881afSMadhavan Srinivasan u64 alt_event; 591efe881afSMadhavan Srinivasan 592efe881afSMadhavan Srinivasan alt[num_alt++] = event; 593efe881afSMadhavan Srinivasan i = find_alternative(event, ev_alt, size); 594efe881afSMadhavan Srinivasan if (i >= 0) { 595efe881afSMadhavan Srinivasan /* Filter out the original event, it's already in alt[0] */ 596efe881afSMadhavan Srinivasan for (j = 0; j < MAX_ALT; ++j) { 597efe881afSMadhavan Srinivasan alt_event = ev_alt[i][j]; 598efe881afSMadhavan Srinivasan if (alt_event && alt_event != event) 599efe881afSMadhavan Srinivasan alt[num_alt++] = alt_event; 600efe881afSMadhavan Srinivasan } 601efe881afSMadhavan Srinivasan } 602efe881afSMadhavan Srinivasan 60370a7e720SMadhavan Srinivasan if (flags & PPMU_ONLY_COUNT_RUN) { 60470a7e720SMadhavan Srinivasan /* 60570a7e720SMadhavan Srinivasan * We're only counting in RUN state, so PM_CYC is equivalent to 60670a7e720SMadhavan Srinivasan * PM_RUN_CYC and PM_INST_CMPL === PM_RUN_INST_CMPL. 60770a7e720SMadhavan Srinivasan */ 60870a7e720SMadhavan Srinivasan j = num_alt; 60970a7e720SMadhavan Srinivasan for (i = 0; i < num_alt; ++i) { 61070a7e720SMadhavan Srinivasan switch (alt[i]) { 61170a7e720SMadhavan Srinivasan case 0x1e: /* PMC_CYC */ 61270a7e720SMadhavan Srinivasan alt[j++] = 0x600f4; /* PM_RUN_CYC */ 61370a7e720SMadhavan Srinivasan break; 61470a7e720SMadhavan Srinivasan case 0x600f4: 61570a7e720SMadhavan Srinivasan alt[j++] = 0x1e; 61670a7e720SMadhavan Srinivasan break; 61770a7e720SMadhavan Srinivasan case 0x2: /* PM_INST_CMPL */ 61870a7e720SMadhavan Srinivasan alt[j++] = 0x500fa; /* PM_RUN_INST_CMPL */ 61970a7e720SMadhavan Srinivasan break; 62070a7e720SMadhavan Srinivasan case 0x500fa: 62170a7e720SMadhavan Srinivasan alt[j++] = 0x2; 62270a7e720SMadhavan Srinivasan break; 62370a7e720SMadhavan Srinivasan } 62470a7e720SMadhavan Srinivasan } 62570a7e720SMadhavan Srinivasan num_alt = j; 62670a7e720SMadhavan Srinivasan } 62770a7e720SMadhavan Srinivasan 628efe881afSMadhavan Srinivasan return num_alt; 629efe881afSMadhavan Srinivasan } 630