18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM 48c2ecf20Sopenharmony_ci * Added mmcra[slot] support: 58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2007 Will Schmidt <willschm@us.ibm.com>, IBM 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/oprofile.h> 98c2ecf20Sopenharmony_ci#include <linux/smp.h> 108c2ecf20Sopenharmony_ci#include <asm/firmware.h> 118c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 128c2ecf20Sopenharmony_ci#include <asm/processor.h> 138c2ecf20Sopenharmony_ci#include <asm/cputable.h> 148c2ecf20Sopenharmony_ci#include <asm/rtas.h> 158c2ecf20Sopenharmony_ci#include <asm/oprofile_impl.h> 168c2ecf20Sopenharmony_ci#include <asm/reg.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define dbg(args...) 198c2ecf20Sopenharmony_ci#define OPROFILE_PM_PMCSEL_MSK 0xffULL 208c2ecf20Sopenharmony_ci#define OPROFILE_PM_UNIT_SHIFT 60 218c2ecf20Sopenharmony_ci#define OPROFILE_PM_UNIT_MSK 0xfULL 228c2ecf20Sopenharmony_ci#define OPROFILE_MAX_PMC_NUM 3 238c2ecf20Sopenharmony_ci#define OPROFILE_PMSEL_FIELD_WIDTH 8 248c2ecf20Sopenharmony_ci#define OPROFILE_UNIT_FIELD_WIDTH 4 258c2ecf20Sopenharmony_ci#define MMCRA_SIAR_VALID_MASK 0x10000000ULL 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic unsigned long reset_value[OP_MAX_COUNTER]; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic int oprofile_running; 308c2ecf20Sopenharmony_cistatic int use_slot_nums; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ 338c2ecf20Sopenharmony_cistatic u32 mmcr0_val; 348c2ecf20Sopenharmony_cistatic u64 mmcr1_val; 358c2ecf20Sopenharmony_cistatic u64 mmcra_val; 368c2ecf20Sopenharmony_cistatic u32 cntr_marked_events; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int power7_marked_instr_event(u64 mmcr1) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci u64 psel, unit; 418c2ecf20Sopenharmony_ci int pmc, cntr_marked_events = 0; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* Given the MMCR1 value, look at the field for each counter to 448c2ecf20Sopenharmony_ci * determine if it is a marked event. Code based on the function 458c2ecf20Sopenharmony_ci * power7_marked_instr_event() in file arch/powerpc/perf/power7-pmu.c. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci for (pmc = 0; pmc < 4; pmc++) { 488c2ecf20Sopenharmony_ci psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK 498c2ecf20Sopenharmony_ci << (OPROFILE_MAX_PMC_NUM - pmc) 508c2ecf20Sopenharmony_ci * OPROFILE_PMSEL_FIELD_WIDTH); 518c2ecf20Sopenharmony_ci psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc) 528c2ecf20Sopenharmony_ci * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL; 538c2ecf20Sopenharmony_ci unit = mmcr1 & (OPROFILE_PM_UNIT_MSK 548c2ecf20Sopenharmony_ci << (OPROFILE_PM_UNIT_SHIFT 558c2ecf20Sopenharmony_ci - (pmc * OPROFILE_PMSEL_FIELD_WIDTH ))); 568c2ecf20Sopenharmony_ci unit = unit >> (OPROFILE_PM_UNIT_SHIFT 578c2ecf20Sopenharmony_ci - (pmc * OPROFILE_PMSEL_FIELD_WIDTH)); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci switch (psel >> 4) { 608c2ecf20Sopenharmony_ci case 2: 618c2ecf20Sopenharmony_ci cntr_marked_events |= (pmc == 1 || pmc == 3) << pmc; 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci case 3: 648c2ecf20Sopenharmony_ci if (psel == 0x3c) { 658c2ecf20Sopenharmony_ci cntr_marked_events |= (pmc == 0) << pmc; 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci if (psel == 0x3e) { 708c2ecf20Sopenharmony_ci cntr_marked_events |= (pmc != 1) << pmc; 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci cntr_marked_events |= 1 << pmc; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci case 4: 778c2ecf20Sopenharmony_ci case 5: 788c2ecf20Sopenharmony_ci cntr_marked_events |= (unit == 0xd) << pmc; 798c2ecf20Sopenharmony_ci break; 808c2ecf20Sopenharmony_ci case 6: 818c2ecf20Sopenharmony_ci if (psel == 0x64) 828c2ecf20Sopenharmony_ci cntr_marked_events |= (pmc >= 2) << pmc; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case 8: 858c2ecf20Sopenharmony_ci cntr_marked_events |= (unit == 0xd) << pmc; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci return cntr_marked_events; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int power4_reg_setup(struct op_counter_config *ctr, 938c2ecf20Sopenharmony_ci struct op_system_config *sys, 948c2ecf20Sopenharmony_ci int num_ctrs) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci int i; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * The performance counter event settings are given in the mmcr0, 1008c2ecf20Sopenharmony_ci * mmcr1 and mmcra values passed from the user in the 1018c2ecf20Sopenharmony_ci * op_system_config structure (sys variable). 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci mmcr0_val = sys->mmcr0; 1048c2ecf20Sopenharmony_ci mmcr1_val = sys->mmcr1; 1058c2ecf20Sopenharmony_ci mmcra_val = sys->mmcra; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci /* Power 7+ and newer architectures: 1088c2ecf20Sopenharmony_ci * Determine which counter events in the group (the group of events is 1098c2ecf20Sopenharmony_ci * specified by the bit settings in the MMCR1 register) are marked 1108c2ecf20Sopenharmony_ci * events for use in the interrupt handler. Do the calculation once 1118c2ecf20Sopenharmony_ci * before OProfile starts. Information is used in the interrupt 1128c2ecf20Sopenharmony_ci * handler. Starting with Power 7+ we only record the sample for 1138c2ecf20Sopenharmony_ci * marked events if the SIAR valid bit is set. For non marked events 1148c2ecf20Sopenharmony_ci * the sample is always recorded. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci if (pvr_version_is(PVR_POWER7p)) 1178c2ecf20Sopenharmony_ci cntr_marked_events = power7_marked_instr_event(mmcr1_val); 1188c2ecf20Sopenharmony_ci else 1198c2ecf20Sopenharmony_ci cntr_marked_events = 0; /* For older processors, set the bit map 1208c2ecf20Sopenharmony_ci * to zero so the sample will always be 1218c2ecf20Sopenharmony_ci * be recorded. 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) 1258c2ecf20Sopenharmony_ci reset_value[i] = 0x80000000UL - ctr[i].count; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* setup user and kernel profiling */ 1288c2ecf20Sopenharmony_ci if (sys->enable_kernel) 1298c2ecf20Sopenharmony_ci mmcr0_val &= ~MMCR0_KERNEL_DISABLE; 1308c2ecf20Sopenharmony_ci else 1318c2ecf20Sopenharmony_ci mmcr0_val |= MMCR0_KERNEL_DISABLE; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (sys->enable_user) 1348c2ecf20Sopenharmony_ci mmcr0_val &= ~MMCR0_PROBLEM_DISABLE; 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci mmcr0_val |= MMCR0_PROBLEM_DISABLE; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) || 1398c2ecf20Sopenharmony_ci pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) || 1408c2ecf20Sopenharmony_ci pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX) || 1418c2ecf20Sopenharmony_ci pvr_version_is(PVR_POWER5) || pvr_version_is(PVR_POWER5p)) 1428c2ecf20Sopenharmony_ci use_slot_nums = 1; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci return 0; 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciextern void ppc_enable_pmcs(void); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * Older CPUs require the MMCRA sample bit to be always set, but newer 1518c2ecf20Sopenharmony_ci * CPUs only want it set for some groups. Eventually we will remove all 1528c2ecf20Sopenharmony_ci * knowledge of this bit in the kernel, oprofile userspace should be 1538c2ecf20Sopenharmony_ci * setting it when required. 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * In order to keep current installations working we force the bit for 1568c2ecf20Sopenharmony_ci * those older CPUs. Once everyone has updated their oprofile userspace we 1578c2ecf20Sopenharmony_ci * can remove this hack. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_cistatic inline int mmcra_must_set_sample(void) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) || 1628c2ecf20Sopenharmony_ci pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) || 1638c2ecf20Sopenharmony_ci pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX)) 1648c2ecf20Sopenharmony_ci return 1; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int power4_cpu_setup(struct op_counter_config *ctr) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci unsigned int mmcr0 = mmcr0_val; 1728c2ecf20Sopenharmony_ci unsigned long mmcra = mmcra_val; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ppc_enable_pmcs(); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* set the freeze bit */ 1778c2ecf20Sopenharmony_ci mmcr0 |= MMCR0_FC; 1788c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR0, mmcr0); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; 1818c2ecf20Sopenharmony_ci mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; 1828c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR0, mmcr0); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR1, mmcr1_val); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (mmcra_must_set_sample()) 1878c2ecf20Sopenharmony_ci mmcra |= MMCRA_SAMPLE_ENABLE; 1888c2ecf20Sopenharmony_ci mtspr(SPRN_MMCRA, mmcra); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), 1918c2ecf20Sopenharmony_ci mfspr(SPRN_MMCR0)); 1928c2ecf20Sopenharmony_ci dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), 1938c2ecf20Sopenharmony_ci mfspr(SPRN_MMCR1)); 1948c2ecf20Sopenharmony_ci dbg("setup on cpu %d, mmcra %lx\n", smp_processor_id(), 1958c2ecf20Sopenharmony_ci mfspr(SPRN_MMCRA)); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int power4_start(struct op_counter_config *ctr) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci int i; 2038c2ecf20Sopenharmony_ci unsigned int mmcr0; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci /* set the PMM bit (see comment below) */ 2068c2ecf20Sopenharmony_ci mtmsr(mfmsr() | MSR_PMM); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { 2098c2ecf20Sopenharmony_ci if (ctr[i].enabled) { 2108c2ecf20Sopenharmony_ci classic_ctr_write(i, reset_value[i]); 2118c2ecf20Sopenharmony_ci } else { 2128c2ecf20Sopenharmony_ci classic_ctr_write(i, 0); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci mmcr0 = mfspr(SPRN_MMCR0); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* 2198c2ecf20Sopenharmony_ci * We must clear the PMAO bit on some (GQ) chips. Just do it 2208c2ecf20Sopenharmony_ci * all the time 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci mmcr0 &= ~MMCR0_PMAO; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* 2258c2ecf20Sopenharmony_ci * now clear the freeze bit, counting will not start until we 2268c2ecf20Sopenharmony_ci * rfid from this excetion, because only at that point will 2278c2ecf20Sopenharmony_ci * the PMM bit be cleared 2288c2ecf20Sopenharmony_ci */ 2298c2ecf20Sopenharmony_ci mmcr0 &= ~MMCR0_FC; 2308c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR0, mmcr0); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci oprofile_running = 1; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 2358c2ecf20Sopenharmony_ci return 0; 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic void power4_stop(void) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci unsigned int mmcr0; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* freeze counters */ 2438c2ecf20Sopenharmony_ci mmcr0 = mfspr(SPRN_MMCR0); 2448c2ecf20Sopenharmony_ci mmcr0 |= MMCR0_FC; 2458c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR0, mmcr0); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci oprofile_running = 0; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci mb(); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci/* Fake functions used by canonicalize_pc */ 2558c2ecf20Sopenharmony_cistatic void __used hypervisor_bucket(void) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic void __used rtas_bucket(void) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic void __used kernel_unknown_bucket(void) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/* 2688c2ecf20Sopenharmony_ci * On GQ and newer the MMCRA stores the HV and PR bits at the time 2698c2ecf20Sopenharmony_ci * the SIAR was sampled. We use that to work out if the SIAR was sampled in 2708c2ecf20Sopenharmony_ci * the hypervisor, our exception vectors or RTAS. 2718c2ecf20Sopenharmony_ci * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits 2728c2ecf20Sopenharmony_ci * to more accurately identify the address of the sampled instruction. The 2738c2ecf20Sopenharmony_ci * mmcra[slot] bits represent the slot number of a sampled instruction 2748c2ecf20Sopenharmony_ci * within an instruction group. The slot will contain a value between 1 2758c2ecf20Sopenharmony_ci * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_cistatic unsigned long get_pc(struct pt_regs *regs) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci unsigned long pc = mfspr(SPRN_SIAR); 2808c2ecf20Sopenharmony_ci unsigned long mmcra; 2818c2ecf20Sopenharmony_ci unsigned long slot; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* Can't do much about it */ 2848c2ecf20Sopenharmony_ci if (!cur_cpu_spec->oprofile_mmcra_sihv) 2858c2ecf20Sopenharmony_ci return pc; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci mmcra = mfspr(SPRN_MMCRA); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (use_slot_nums && (mmcra & MMCRA_SAMPLE_ENABLE)) { 2908c2ecf20Sopenharmony_ci slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT); 2918c2ecf20Sopenharmony_ci if (slot > 1) 2928c2ecf20Sopenharmony_ci pc += 4 * (slot - 1); 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* Were we in the hypervisor? */ 2968c2ecf20Sopenharmony_ci if (firmware_has_feature(FW_FEATURE_LPAR) && 2978c2ecf20Sopenharmony_ci (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) 2988c2ecf20Sopenharmony_ci /* function descriptor madness */ 2998c2ecf20Sopenharmony_ci return *((unsigned long *)hypervisor_bucket); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* We were in userspace, nothing to do */ 3028c2ecf20Sopenharmony_ci if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr) 3038c2ecf20Sopenharmony_ci return pc; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_RTAS 3068c2ecf20Sopenharmony_ci /* Were we in RTAS? */ 3078c2ecf20Sopenharmony_ci if (pc >= rtas.base && pc < (rtas.base + rtas.size)) 3088c2ecf20Sopenharmony_ci /* function descriptor madness */ 3098c2ecf20Sopenharmony_ci return *((unsigned long *)rtas_bucket); 3108c2ecf20Sopenharmony_ci#endif 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* Were we in our exception vectors or SLB real mode miss handler? */ 3138c2ecf20Sopenharmony_ci if (pc < 0x1000000UL) 3148c2ecf20Sopenharmony_ci return (unsigned long)__va(pc); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* Not sure where we were */ 3178c2ecf20Sopenharmony_ci if (!is_kernel_addr(pc)) 3188c2ecf20Sopenharmony_ci /* function descriptor madness */ 3198c2ecf20Sopenharmony_ci return *((unsigned long *)kernel_unknown_bucket); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return pc; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int get_kernel(unsigned long pc, unsigned long mmcra) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci int is_kernel; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if (!cur_cpu_spec->oprofile_mmcra_sihv) { 3298c2ecf20Sopenharmony_ci is_kernel = is_kernel_addr(pc); 3308c2ecf20Sopenharmony_ci } else { 3318c2ecf20Sopenharmony_ci is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return is_kernel; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic bool pmc_overflow(unsigned long val) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci if ((int)val < 0) 3408c2ecf20Sopenharmony_ci return true; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* 3438c2ecf20Sopenharmony_ci * Events on POWER7 can roll back if a speculative event doesn't 3448c2ecf20Sopenharmony_ci * eventually complete. Unfortunately in some rare cases they will 3458c2ecf20Sopenharmony_ci * raise a performance monitor exception. We need to catch this to 3468c2ecf20Sopenharmony_ci * ensure we reset the PMC. In all cases the PMC will be 256 or less 3478c2ecf20Sopenharmony_ci * cycles from overflow. 3488c2ecf20Sopenharmony_ci * 3498c2ecf20Sopenharmony_ci * We only do this if the first pass fails to find any overflowing 3508c2ecf20Sopenharmony_ci * PMCs because a user might set a period of less than 256 and we 3518c2ecf20Sopenharmony_ci * don't want to mistakenly reset them. 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_ci if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256)) 3548c2ecf20Sopenharmony_ci return true; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return false; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic void power4_handle_interrupt(struct pt_regs *regs, 3608c2ecf20Sopenharmony_ci struct op_counter_config *ctr) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci unsigned long pc; 3638c2ecf20Sopenharmony_ci int is_kernel; 3648c2ecf20Sopenharmony_ci int val; 3658c2ecf20Sopenharmony_ci int i; 3668c2ecf20Sopenharmony_ci unsigned int mmcr0; 3678c2ecf20Sopenharmony_ci unsigned long mmcra; 3688c2ecf20Sopenharmony_ci bool siar_valid = false; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci mmcra = mfspr(SPRN_MMCRA); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci pc = get_pc(regs); 3738c2ecf20Sopenharmony_ci is_kernel = get_kernel(pc, mmcra); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* set the PMM bit (see comment below) */ 3768c2ecf20Sopenharmony_ci mtmsr(mfmsr() | MSR_PMM); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci /* Check that the SIAR valid bit in MMCRA is set to 1. */ 3798c2ecf20Sopenharmony_ci if ((mmcra & MMCRA_SIAR_VALID_MASK) == MMCRA_SIAR_VALID_MASK) 3808c2ecf20Sopenharmony_ci siar_valid = true; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { 3838c2ecf20Sopenharmony_ci val = classic_ctr_read(i); 3848c2ecf20Sopenharmony_ci if (pmc_overflow(val)) { 3858c2ecf20Sopenharmony_ci if (oprofile_running && ctr[i].enabled) { 3868c2ecf20Sopenharmony_ci /* Power 7+ and newer architectures: 3878c2ecf20Sopenharmony_ci * If the event is a marked event, then only 3888c2ecf20Sopenharmony_ci * save the sample if the SIAR valid bit is 3898c2ecf20Sopenharmony_ci * set. If the event is not marked, then 3908c2ecf20Sopenharmony_ci * always save the sample. 3918c2ecf20Sopenharmony_ci * Note, the Sample enable bit in the MMCRA 3928c2ecf20Sopenharmony_ci * register must be set to 1 if the group 3938c2ecf20Sopenharmony_ci * contains a marked event. 3948c2ecf20Sopenharmony_ci */ 3958c2ecf20Sopenharmony_ci if ((siar_valid && 3968c2ecf20Sopenharmony_ci (cntr_marked_events & (1 << i))) 3978c2ecf20Sopenharmony_ci || !(cntr_marked_events & (1 << i))) 3988c2ecf20Sopenharmony_ci oprofile_add_ext_sample(pc, regs, i, 3998c2ecf20Sopenharmony_ci is_kernel); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci classic_ctr_write(i, reset_value[i]); 4028c2ecf20Sopenharmony_ci } else { 4038c2ecf20Sopenharmony_ci classic_ctr_write(i, 0); 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci mmcr0 = mfspr(SPRN_MMCR0); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* reset the perfmon trigger */ 4118c2ecf20Sopenharmony_ci mmcr0 |= MMCR0_PMXE; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* 4148c2ecf20Sopenharmony_ci * We must clear the PMAO bit on some (GQ) chips. Just do it 4158c2ecf20Sopenharmony_ci * all the time 4168c2ecf20Sopenharmony_ci */ 4178c2ecf20Sopenharmony_ci mmcr0 &= ~MMCR0_PMAO; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* Clear the appropriate bits in the MMCRA */ 4208c2ecf20Sopenharmony_ci mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear; 4218c2ecf20Sopenharmony_ci mtspr(SPRN_MMCRA, mmcra); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci /* 4248c2ecf20Sopenharmony_ci * now clear the freeze bit, counting will not start until we 4258c2ecf20Sopenharmony_ci * rfid from this exception, because only at that point will 4268c2ecf20Sopenharmony_ci * the PMM bit be cleared 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_ci mmcr0 &= ~MMCR0_FC; 4298c2ecf20Sopenharmony_ci mtspr(SPRN_MMCR0, mmcr0); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistruct op_powerpc_model op_model_power4 = { 4338c2ecf20Sopenharmony_ci .reg_setup = power4_reg_setup, 4348c2ecf20Sopenharmony_ci .cpu_setup = power4_cpu_setup, 4358c2ecf20Sopenharmony_ci .start = power4_start, 4368c2ecf20Sopenharmony_ci .stop = power4_stop, 4378c2ecf20Sopenharmony_ci .handle_interrupt = power4_handle_interrupt, 4388c2ecf20Sopenharmony_ci}; 439