|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_common.c: set of functions common to all PMU models
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2009 Google, Inc
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@gmail.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Based on:
|
|
Packit |
577717 |
* Copyright (c) 2001-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
#include <limits.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include <perfmon/pfmlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfmlib_pmu_t *pfmlib_pmus[]=
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_IA64
|
|
Packit |
577717 |
#if 0
|
|
Packit |
577717 |
&montecito_support,
|
|
Packit |
577717 |
&itanium2_support,
|
|
Packit |
577717 |
&itanium_support,
|
|
Packit |
577717 |
&generic_ia64_support, /* must always be last for IA-64 */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_I386
|
|
Packit |
577717 |
/* 32-bit only processors */
|
|
Packit |
577717 |
&intel_pii_support,
|
|
Packit |
577717 |
&intel_ppro_support,
|
|
Packit |
577717 |
&intel_p6_support,
|
|
Packit |
577717 |
&intel_pm_support,
|
|
Packit |
577717 |
&intel_coreduo_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_X86
|
|
Packit |
577717 |
/* 32 and 64 bit processors */
|
|
Packit |
577717 |
&netburst_support,
|
|
Packit |
577717 |
&netburst_p_support,
|
|
Packit |
577717 |
&amd64_k7_support,
|
|
Packit |
577717 |
&amd64_k8_revb_support,
|
|
Packit |
577717 |
&amd64_k8_revc_support,
|
|
Packit |
577717 |
&amd64_k8_revd_support,
|
|
Packit |
577717 |
&amd64_k8_reve_support,
|
|
Packit |
577717 |
&amd64_k8_revf_support,
|
|
Packit |
577717 |
&amd64_k8_revg_support,
|
|
Packit |
577717 |
&amd64_fam10h_barcelona_support,
|
|
Packit |
577717 |
&amd64_fam10h_shanghai_support,
|
|
Packit |
577717 |
&amd64_fam10h_istanbul_support,
|
|
Packit |
577717 |
&amd64_fam11h_turion_support,
|
|
Packit |
577717 |
&amd64_fam12h_llano_support,
|
|
Packit |
577717 |
&amd64_fam14h_bobcat_support,
|
|
Packit |
577717 |
&amd64_fam15h_interlagos_support,
|
|
Packit |
577717 |
&amd64_fam15h_nb_support,
|
|
Packit |
577717 |
&amd64_fam16h_support,
|
|
Packit |
577717 |
&amd64_fam17h_support,
|
|
Packit |
577717 |
&intel_core_support,
|
|
Packit |
577717 |
&intel_atom_support,
|
|
Packit |
577717 |
&intel_nhm_support,
|
|
Packit |
577717 |
&intel_nhm_ex_support,
|
|
Packit |
577717 |
&intel_nhm_unc_support,
|
|
Packit |
577717 |
&intel_wsm_sp_support,
|
|
Packit |
577717 |
&intel_wsm_dp_support,
|
|
Packit |
577717 |
&intel_wsm_unc_support,
|
|
Packit |
577717 |
&intel_snb_support,
|
|
Packit |
577717 |
&intel_snb_unc_cbo0_support,
|
|
Packit |
577717 |
&intel_snb_unc_cbo1_support,
|
|
Packit |
577717 |
&intel_snb_unc_cbo2_support,
|
|
Packit |
577717 |
&intel_snb_unc_cbo3_support,
|
|
Packit |
577717 |
&intel_snb_ep_support,
|
|
Packit |
577717 |
&intel_ivb_support,
|
|
Packit |
577717 |
&intel_ivb_unc_cbo0_support,
|
|
Packit |
577717 |
&intel_ivb_unc_cbo1_support,
|
|
Packit |
577717 |
&intel_ivb_unc_cbo2_support,
|
|
Packit |
577717 |
&intel_ivb_unc_cbo3_support,
|
|
Packit |
577717 |
&intel_ivb_ep_support,
|
|
Packit |
577717 |
&intel_hsw_support,
|
|
Packit |
577717 |
&intel_hsw_ep_support,
|
|
Packit |
577717 |
&intel_bdw_support,
|
|
Packit |
577717 |
&intel_bdw_ep_support,
|
|
Packit |
577717 |
&intel_skl_support,
|
|
Packit |
577717 |
&intel_skx_support,
|
|
Packit |
577717 |
&intel_rapl_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb0_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb1_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb2_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb3_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb4_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb5_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb6_support,
|
|
Packit |
577717 |
&intel_snbep_unc_cb7_support,
|
|
Packit |
577717 |
&intel_snbep_unc_ha_support,
|
|
Packit |
577717 |
&intel_snbep_unc_imc0_support,
|
|
Packit |
577717 |
&intel_snbep_unc_imc1_support,
|
|
Packit |
577717 |
&intel_snbep_unc_imc2_support,
|
|
Packit |
577717 |
&intel_snbep_unc_imc3_support,
|
|
Packit |
577717 |
&intel_snbep_unc_pcu_support,
|
|
Packit |
577717 |
&intel_snbep_unc_qpi0_support,
|
|
Packit |
577717 |
&intel_snbep_unc_qpi1_support,
|
|
Packit |
577717 |
&intel_snbep_unc_ubo_support,
|
|
Packit |
577717 |
&intel_snbep_unc_r2pcie_support,
|
|
Packit |
577717 |
&intel_snbep_unc_r3qpi0_support,
|
|
Packit |
577717 |
&intel_snbep_unc_r3qpi1_support,
|
|
Packit |
577717 |
&intel_knc_support,
|
|
Packit |
577717 |
&intel_slm_support,
|
|
Packit |
577717 |
&intel_glm_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb0_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb1_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb2_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb3_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb4_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb5_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb6_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb7_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb8_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb9_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb10_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb11_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb12_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb13_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_cb14_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_ha0_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_ha1_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc0_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc1_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc2_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc3_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc4_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc5_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc6_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_imc7_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_pcu_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_qpi0_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_qpi1_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_qpi2_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_ubo_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_r2pcie_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_r3qpi0_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_r3qpi1_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_r3qpi2_support,
|
|
Packit |
577717 |
&intel_ivbep_unc_irp_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb2_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb3_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb4_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb5_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb6_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb7_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb8_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb9_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb10_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb11_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb12_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb13_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb14_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb15_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb16_support,
|
|
Packit |
577717 |
&intel_hswep_unc_cb17_support,
|
|
Packit |
577717 |
&intel_hswep_unc_ha0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_ha1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc2_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc3_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc4_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc5_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc6_support,
|
|
Packit |
577717 |
&intel_hswep_unc_imc7_support,
|
|
Packit |
577717 |
&intel_hswep_unc_pcu_support,
|
|
Packit |
577717 |
&intel_hswep_unc_qpi0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_qpi1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_sb0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_sb1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_sb2_support,
|
|
Packit |
577717 |
&intel_hswep_unc_sb3_support,
|
|
Packit |
577717 |
&intel_hswep_unc_ubo_support,
|
|
Packit |
577717 |
&intel_hswep_unc_r2pcie_support,
|
|
Packit |
577717 |
&intel_hswep_unc_r3qpi0_support,
|
|
Packit |
577717 |
&intel_hswep_unc_r3qpi1_support,
|
|
Packit |
577717 |
&intel_hswep_unc_r3qpi2_support,
|
|
Packit |
577717 |
&intel_hswep_unc_irp_support,
|
|
Packit |
577717 |
&intel_knl_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc0_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc1_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc2_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc3_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc4_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc5_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc_uclk0_support,
|
|
Packit |
577717 |
&intel_knl_unc_imc_uclk1_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk0_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk1_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk2_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk3_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk4_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk5_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk6_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_uclk7_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk0_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk1_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk2_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk3_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk4_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk5_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk6_support,
|
|
Packit |
577717 |
&intel_knl_unc_edc_eclk7_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha0_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha1_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha2_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha3_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha4_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha5_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha6_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha7_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha8_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha9_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha10_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha11_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha12_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha13_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha14_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha15_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha16_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha17_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha18_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha19_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha20_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha21_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha22_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha23_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha24_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha25_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha26_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha27_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha28_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha29_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha30_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha31_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha32_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha33_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha34_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha35_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha36_support,
|
|
Packit |
577717 |
&intel_knl_unc_cha37_support,
|
|
Packit |
577717 |
&intel_knl_unc_m2pcie_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb2_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb3_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb4_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb5_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb6_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb7_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb8_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb9_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb10_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb11_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb12_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb13_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb14_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb15_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb16_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb17_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb18_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb19_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb20_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb21_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb22_support,
|
|
Packit |
577717 |
&intel_bdx_unc_cb23_support,
|
|
Packit |
577717 |
&intel_bdx_unc_ubo_support,
|
|
Packit |
577717 |
&intel_bdx_unc_sbo0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_sbo1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_sbo2_support,
|
|
Packit |
577717 |
&intel_bdx_unc_sbo3_support,
|
|
Packit |
577717 |
&intel_bdx_unc_ha0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_ha1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc2_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc3_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc4_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc5_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc6_support,
|
|
Packit |
577717 |
&intel_bdx_unc_imc7_support,
|
|
Packit |
577717 |
&intel_bdx_unc_irp_support,
|
|
Packit |
577717 |
&intel_bdx_unc_pcu_support,
|
|
Packit |
577717 |
&intel_bdx_unc_qpi0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_qpi1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_qpi2_support,
|
|
Packit |
577717 |
&intel_bdx_unc_r2pcie_support,
|
|
Packit |
577717 |
&intel_bdx_unc_r3qpi0_support,
|
|
Packit |
577717 |
&intel_bdx_unc_r3qpi1_support,
|
|
Packit |
577717 |
&intel_bdx_unc_r3qpi2_support,
|
|
Packit |
577717 |
&intel_x86_arch_support, /* must always be last for x86 */
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_MIPS
|
|
Packit |
577717 |
&mips_74k_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SICORTEX
|
|
Packit |
577717 |
&sicortex_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_POWERPC
|
|
Packit |
577717 |
&power4_support,
|
|
Packit |
577717 |
&ppc970_support,
|
|
Packit |
577717 |
&ppc970mp_support,
|
|
Packit |
577717 |
&power5_support,
|
|
Packit |
577717 |
&power5p_support,
|
|
Packit |
577717 |
&power6_support,
|
|
Packit |
577717 |
&power7_support,
|
|
Packit |
577717 |
&power8_support,
|
|
Packit |
577717 |
&power9_support,
|
|
Packit |
577717 |
&torrent_support,
|
|
Packit |
577717 |
&powerpc_nest_mcs_read_support,
|
|
Packit |
577717 |
&powerpc_nest_mcs_write_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_SPARC
|
|
Packit |
577717 |
&sparc_ultra12_support,
|
|
Packit |
577717 |
&sparc_ultra3_support,
|
|
Packit |
577717 |
&sparc_ultra3i_support,
|
|
Packit |
577717 |
&sparc_ultra3plus_support,
|
|
Packit |
577717 |
&sparc_ultra4plus_support,
|
|
Packit |
577717 |
&sparc_niagara1_support,
|
|
Packit |
577717 |
&sparc_niagara2_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_CELL
|
|
Packit |
577717 |
&cell_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_ARM
|
|
Packit |
577717 |
&arm_cortex_a7_support,
|
|
Packit |
577717 |
&arm_cortex_a8_support,
|
|
Packit |
577717 |
&arm_cortex_a9_support,
|
|
Packit |
577717 |
&arm_cortex_a15_support,
|
|
Packit |
577717 |
&arm_1176_support,
|
|
Packit |
577717 |
&arm_qcom_krait_support,
|
|
Packit |
577717 |
&arm_cortex_a57_support,
|
|
Packit |
577717 |
&arm_cortex_a53_support,
|
|
Packit |
577717 |
&arm_xgene_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_ARM64
|
|
Packit |
577717 |
&arm_cortex_a57_support,
|
|
Packit |
577717 |
&arm_cortex_a53_support,
|
|
Packit |
577717 |
&arm_xgene_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef CONFIG_PFMLIB_ARCH_S390X
|
|
Packit |
577717 |
&s390x_cpum_cf_support,
|
|
Packit |
577717 |
&s390x_cpum_sf_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#ifdef __linux__
|
|
Packit |
577717 |
&perf_event_support,
|
|
Packit |
577717 |
&perf_event_raw_support,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
#define PFMLIB_NUM_PMUS (int)(sizeof(pfmlib_pmus)/sizeof(pfmlib_pmu_t *))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfmlib_os_t pfmlib_os_none;
|
|
Packit |
577717 |
pfmlib_os_t *pfmlib_os = &pfmlib_os_none;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfmlib_os_t *pfmlib_oses[]={
|
|
Packit |
577717 |
&pfmlib_os_none,
|
|
Packit |
577717 |
#ifdef __linux__
|
|
Packit |
577717 |
&pfmlib_os_perf,
|
|
Packit |
577717 |
&pfmlib_os_perf_ext,
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
#define PFMLIB_NUM_OSES (int)(sizeof(pfmlib_oses)/sizeof(pfmlib_os_t *))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* Mapping table from PMU index to pfmlib_pmu_t
|
|
Packit |
577717 |
* table is populated from pfmlib_pmus[] when the library
|
|
Packit |
577717 |
* is initialized.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Some entries can be NULL if PMU is not implemented on host
|
|
Packit |
577717 |
* architecture or if the initialization failed.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static pfmlib_pmu_t *pfmlib_pmus_map[PFM_PMU_MAX];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define pfmlib_for_each_pmu_event(p, e) \
|
|
Packit |
577717 |
for(e=(p)->get_event_first((p)); e != -1; e = (p)->get_event_next((p), e))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define for_each_pmu_event_attr(u, i) \
|
|
Packit |
577717 |
for((u)=0; (u) < (i)->nattrs; (u) = (u)+1)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define pfmlib_for_each_pmu(x) \
|
|
Packit |
577717 |
for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define pfmlib_for_each_pmu(x) \
|
|
Packit |
577717 |
for((x)= 0 ; (x) < PFMLIB_NUM_PMUS; (x)++)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define pfmlib_for_each_os(x) \
|
|
Packit |
577717 |
for((x)= 0 ; (x) < PFMLIB_NUM_OSES; (x)++)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_config_t pfm_cfg;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
__pfm_dbprintf(const char *fmt, ...)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
va_list ap;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_cfg.debug == 0)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
va_start(ap, fmt);
|
|
Packit |
577717 |
vfprintf(pfm_cfg.fp, fmt, ap);
|
|
Packit |
577717 |
va_end(ap);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
__pfm_vbprintf(const char *fmt, ...)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
va_list ap;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_cfg.verbose == 0)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
va_start(ap, fmt);
|
|
Packit |
577717 |
vfprintf(pfm_cfg.fp, fmt, ap);
|
|
Packit |
577717 |
va_end(ap);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_getl: our own equivalent to GNU getline() extension.
|
|
Packit |
577717 |
* This avoids a dependency on having a C library with
|
|
Packit |
577717 |
* support for getline().
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfmlib_getl(char **buffer, size_t *len, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#define GETL_DFL_LEN 32
|
|
Packit |
577717 |
char *b;
|
|
Packit |
577717 |
int c;
|
|
Packit |
577717 |
size_t maxsz, maxi, d, i = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!len || !fp || !buffer || (*buffer && *len < 2))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
b = *buffer;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!b)
|
|
Packit |
577717 |
*len = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
maxsz = *len;
|
|
Packit |
577717 |
maxi = maxsz - 2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while ((c = fgetc(fp)) != EOF) {
|
|
Packit |
577717 |
if (maxsz == 0 || i == maxi) {
|
|
Packit |
577717 |
if (maxsz == 0)
|
|
Packit |
577717 |
maxsz = GETL_DFL_LEN;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
maxsz <<= 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (*buffer)
|
|
Packit |
577717 |
d = &b[i] - *buffer;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
d = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*buffer = realloc(*buffer, maxsz);
|
|
Packit |
577717 |
if (!*buffer)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
b = *buffer + d;
|
|
Packit |
577717 |
maxi = maxsz - d - 2;
|
|
Packit |
577717 |
i = 0;
|
|
Packit |
577717 |
*len = maxsz;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
b[i++] = c;
|
|
Packit |
577717 |
if (c == '\n')
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
b[i] = '\0';
|
|
Packit |
577717 |
return c != EOF ? 0 : -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* append fmt+args to str such that the string is no
|
|
Packit |
577717 |
* more than max characters incl. null termination
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfmlib_strconcat(char *str, size_t max, const char *fmt, ...)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
va_list ap;
|
|
Packit |
577717 |
size_t len, todo;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
len = strlen(str);
|
|
Packit |
577717 |
todo = max - strlen(str);
|
|
Packit |
577717 |
va_start(ap, fmt);
|
|
Packit |
577717 |
vsnprintf(str+len, todo, fmt, ap);
|
|
Packit |
577717 |
va_end(ap);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* compact all pattrs starting from index i
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfmlib_compact_pattrs(pfmlib_event_desc_t *e, int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j = i+1; j < e->npattrs; j++)
|
|
Packit |
577717 |
e->pattrs[j - 1] = e->pattrs[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->npattrs--;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfmlib_compact_attrs(pfmlib_event_desc_t *e, int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j = i+1; j < e->nattrs; j++)
|
|
Packit |
577717 |
e->attrs[j - 1] = e->attrs[j];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->nattrs--;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* 0 : different attribute
|
|
Packit |
577717 |
* 1 : exactly same attribute (duplicate can be removed)
|
|
Packit |
577717 |
* -1 : same attribute but value differ, this is an error
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
pfmlib_same_attr(pfmlib_event_desc_t *d, int i, int j)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a1, *a2;
|
|
Packit |
577717 |
pfmlib_attr_t *b1, *b2;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
a1 = attr(d, i);
|
|
Packit |
577717 |
a2 = attr(d, j);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
b1 = d->attrs+i;
|
|
Packit |
577717 |
b2 = d->attrs+j;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a1->idx == a2->idx
|
|
Packit |
577717 |
&& a1->type == a2->type
|
|
Packit |
577717 |
&& a1->ctrl == a2->ctrl) {
|
|
Packit |
577717 |
if (b1->ival == b2->ival)
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
pfmlib_pmu_active(pfmlib_pmu_t *pmu)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return !!(pmu->flags & PFMLIB_PMU_FL_ACTIVE);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
pfmlib_pmu_initialized(pfmlib_pmu_t *pmu)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return !!(pmu->flags & PFMLIB_PMU_FL_INIT);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline pfm_pmu_t
|
|
Packit |
577717 |
idx2pmu(int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (pfm_pmu_t)(idx >> PFMLIB_PMU_SHIFT) & PFMLIB_PMU_MASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline pfmlib_pmu_t *
|
|
Packit |
577717 |
pmu2pmuidx(pfm_pmu_t pmu)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/* pfm_pmu_t is unsigned int enum, so
|
|
Packit |
577717 |
* just need to check for upper bound
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pmu >= PFM_PMU_MAX)
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfmlib_pmus_map[pmu];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* external opaque idx -> PMU + internal idx
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static pfmlib_pmu_t *
|
|
Packit |
577717 |
pfmlib_idx2pidx(int idx, int *pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
pfm_pmu_t pmu_id;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (idx < 0)
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu_id = idx2pmu(idx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pmu2pmuidx(pmu_id);
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*pidx = idx & PFMLIB_PMU_PIDX_MASK;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->event_is_valid(pmu, *pidx))
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pmu;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfmlib_os_t *
|
|
Packit |
577717 |
pfmlib_find_os(pfm_os_t id)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int o;
|
|
Packit |
577717 |
pfmlib_os_t *os;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_os(o) {
|
|
Packit |
577717 |
os = pfmlib_oses[o];
|
|
Packit |
577717 |
if (os->id == id && (os->flags & PFMLIB_OS_FL_ACTIVATED))
|
|
Packit |
577717 |
return os;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
size_t
|
|
Packit |
577717 |
pfmlib_check_struct(void *st, size_t usz, size_t refsz, size_t sz)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
size_t rsz = sz;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if user size is zero, then use ABI0 size
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (usz == 0)
|
|
Packit |
577717 |
usz = refsz;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* cannot be smaller than ABI0 size
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (usz < refsz) {
|
|
Packit |
577717 |
DPRINT("pfmlib_check_struct: user size too small %zu\n", usz);
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if bigger than current ABI, then check that none
|
|
Packit |
577717 |
* of the extra bits are set. This is to avoid mistake
|
|
Packit |
577717 |
* by caller assuming the library set those bits.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (usz > sz) {
|
|
Packit |
577717 |
char *addr = (char *)st + sz;
|
|
Packit |
577717 |
char *end = (char *)st + usz;
|
|
Packit |
577717 |
while (addr != end) {
|
|
Packit |
577717 |
if (*addr++) {
|
|
Packit |
577717 |
DPRINT("pfmlib_check_struct: invalid extra bits\n");
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return rsz;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check environment variables for:
|
|
Packit |
577717 |
* LIBPFM_VERBOSE : enable verbose output (must be 1)
|
|
Packit |
577717 |
* LIBPFM_DEBUG : enable debug output (must be 1)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfmlib_init_env(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *str;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_cfg.fp = stderr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_VERBOSE");
|
|
Packit |
577717 |
if (str && isdigit((int)*str))
|
|
Packit |
577717 |
pfm_cfg.verbose = *str - '0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_DEBUG");
|
|
Packit |
577717 |
if (str && isdigit((int)*str))
|
|
Packit |
577717 |
pfm_cfg.debug = *str - '0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_DEBUG_STDOUT");
|
|
Packit |
577717 |
if (str)
|
|
Packit |
577717 |
pfm_cfg.fp = stdout;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_cfg.forced_pmu = getenv("LIBPFM_FORCE_PMU");
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_ENCODE_INACTIVE");
|
|
Packit |
577717 |
if (str)
|
|
Packit |
577717 |
pfm_cfg.inactive = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
str = getenv("LIBPFM_DISABLED_PMUS");
|
|
Packit |
577717 |
if (str)
|
|
Packit |
577717 |
pfm_cfg.blacklist_pmus = str;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_pmu_sanity_checks(pfmlib_pmu_t *p)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check event can be encoded
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p->pme_count >= (1<< PFMLIB_PMU_SHIFT)) {
|
|
Packit |
577717 |
DPRINT("too many events for %s\n", p->desc);
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (p->max_encoding > PFMLIB_MAX_ENCODING) {
|
|
Packit |
577717 |
DPRINT("max encoding too high (%d > %d) for %s\n",
|
|
Packit |
577717 |
p->max_encoding, PFMLIB_MAX_ENCODING, p->desc);
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfmlib_build_fstr(pfmlib_event_desc_t *e, char **fstr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
/* nothing to do */
|
|
Packit |
577717 |
if (!fstr)
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*fstr = malloc(strlen(e->fstr) + 2 + strlen(e->pmu->name) + 1);
|
|
Packit |
577717 |
if (*fstr)
|
|
Packit |
577717 |
sprintf(*fstr, "%s::%s", e->pmu->name, e->fstr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return *fstr ? PFM_SUCCESS : PFM_ERR_NOMEM;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_pmu_activate(pfmlib_pmu_t *p)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (p->pmu_init) {
|
|
Packit |
577717 |
ret = p->pmu_init(p);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
p->flags |= PFMLIB_PMU_FL_ACTIVE;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("activated %s\n", p->desc);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
pfmlib_match_forced_pmu(const char *name)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const char *p;
|
|
Packit |
577717 |
size_t l;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip any lower level specifier */
|
|
Packit |
577717 |
p = strchr(pfm_cfg.forced_pmu, ',');
|
|
Packit |
577717 |
if (p)
|
|
Packit |
577717 |
l = p - pfm_cfg.forced_pmu;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
l = strlen(pfm_cfg.forced_pmu);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return !strncasecmp(name, pfm_cfg.forced_pmu, l);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_is_blacklisted_pmu(pfmlib_pmu_t *p)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
char *q, *buffer;
|
|
Packit |
577717 |
int ret = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfm_cfg.blacklist_pmus)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* scan list for matching PMU names, we accept substrings.
|
|
Packit |
577717 |
* for instance: snbep does match snbep*
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
buffer = strdup(pfm_cfg.blacklist_pmus);
|
|
Packit |
577717 |
if (!buffer)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
strcpy (buffer, pfm_cfg.blacklist_pmus);
|
|
Packit |
577717 |
for (q = strtok (buffer, ","); q != NULL; q = strtok (NULL, ",")) {
|
|
Packit |
577717 |
if (strstr (p->name, q) != NULL) {
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = 0;
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
free(buffer);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_init_pmus(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *p;
|
|
Packit |
577717 |
int i, ret;
|
|
Packit |
577717 |
int nsuccess = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* activate all detected PMUs
|
|
Packit |
577717 |
* when forced, only the designated PMU
|
|
Packit |
577717 |
* is setup and activated
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_for_each_pmu(i) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
p = pfmlib_pmus[i];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("trying %s\n", p->desc);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfm_cfg.forced_pmu)
|
|
Packit |
577717 |
ret = p->pmu_detect(p);
|
|
Packit |
577717 |
else if (!pfmlib_match_forced_pmu(p->name))
|
|
Packit |
577717 |
ret = PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* basic checks
|
|
Packit |
577717 |
* failure causes PMU to not be available
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pfmlib_pmu_sanity_checks(p) != PFM_SUCCESS)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfmlib_is_blacklisted_pmu(p)) {
|
|
Packit |
577717 |
DPRINT("%d PMU blacklisted, skipping initialization\n");
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
p->flags |= PFMLIB_PMU_FL_INIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* populate mapping table
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_pmus_map[p->pmu] = p;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check if exported by OS if needed
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (p->os_detect[pfmlib_os->id]) {
|
|
Packit |
577717 |
ret = p->os_detect[pfmlib_os->id](p);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
DPRINT("%s PMU not exported by OS\n", p->name);
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_pmu_activate(p);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS)
|
|
Packit |
577717 |
nsuccess++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_cfg.forced_pmu) {
|
|
Packit |
577717 |
__pfm_vbprintf("PMU forced to %s (%s) : %s\n",
|
|
Packit |
577717 |
p->name,
|
|
Packit |
577717 |
p->desc,
|
|
Packit |
577717 |
ret == PFM_SUCCESS ? "success" : "failure");
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
DPRINT("%d PMU detected out of %d supported\n", nsuccess, PFMLIB_NUM_PMUS);
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfmlib_init_os(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int o;
|
|
Packit |
577717 |
pfmlib_os_t *os;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_os(o) {
|
|
Packit |
577717 |
os = pfmlib_oses[o];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!os->detect)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (os->detect(os) != PFM_SUCCESS)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (os != &pfmlib_os_none && pfmlib_os == &pfmlib_os_none)
|
|
Packit |
577717 |
pfmlib_os = os;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("OS layer %s activated\n", os->name);
|
|
Packit |
577717 |
os->flags = PFMLIB_OS_FL_ACTIVATED;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
DPRINT("default OS layer: %s\n", pfmlib_os->name);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_initialize(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* not atomic
|
|
Packit |
577717 |
* if initialization already done, then reurn previous return value
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pfm_cfg.initdone)
|
|
Packit |
577717 |
return pfm_cfg.initret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* generic sanity checks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (PFM_PMU_MAX & (~PFMLIB_PMU_MASK)) {
|
|
Packit |
577717 |
DPRINT("PFM_PMU_MAX exceeds PFMLIB_PMU_MASK\n");
|
|
Packit |
577717 |
ret = PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_init_env();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* must be done before pfmlib_init_pmus() */
|
|
Packit |
577717 |
pfmlib_init_os();
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_init_pmus();
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_cfg.initdone = 1;
|
|
Packit |
577717 |
pfm_cfg.initret = ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfm_terminate(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_pmu(i) {
|
|
Packit |
577717 |
pmu = pfmlib_pmus[i];
|
|
Packit |
577717 |
if (!pfmlib_pmu_active(pmu))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (pmu->pmu_terminate)
|
|
Packit |
577717 |
pmu->pmu_terminate(pmu);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pfm_cfg.initdone = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_find_event(const char *str)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_parse_event(str, &e);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS) {
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* save index so we can return it
|
|
Packit |
577717 |
* and free the pattrs data that was
|
|
Packit |
577717 |
* allocated in pfmlib_parse_event()
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfmlib_pidx2idx(e.pmu, e.event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_sanitize_event(pfmlib_event_desc_t *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int i, j, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* fail if duplicate attributes are found
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for(i=0; i < d->nattrs; i++) {
|
|
Packit |
577717 |
for(j=i+1; j < d->nattrs; j++) {
|
|
Packit |
577717 |
ret = pfmlib_same_attr(d, i, j);
|
|
Packit |
577717 |
if (ret == 1)
|
|
Packit |
577717 |
pfmlib_compact_attrs(d, j);
|
|
Packit |
577717 |
else if (ret == -1)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_parse_event_attr(char *str, pfmlib_event_desc_t *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *ainfo;
|
|
Packit |
577717 |
char *s, *p, *q, *endptr;
|
|
Packit |
577717 |
char yes[2] = "y";
|
|
Packit |
577717 |
pfm_attr_t type;
|
|
Packit |
577717 |
int aidx = 0, has_val, has_raw_um = 0, has_um = 0;
|
|
Packit |
577717 |
int ret = PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
s = str;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
while(s) {
|
|
Packit |
577717 |
p = s;
|
|
Packit |
577717 |
strsep(&p, PFMLIB_ATTR_DELIM);
|
|
Packit |
577717 |
/* if (p)
|
|
Packit |
577717 |
*p++ = '\0'; */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
q = strchr(s, '=');
|
|
Packit |
577717 |
if (q)
|
|
Packit |
577717 |
*q++ = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
has_val = !!q;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for raw umasks in hexdecimal only
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (*s == '0' && tolower(*(s+1)) == 'x') {
|
|
Packit |
577717 |
char *endptr = NULL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* can only have one raw umask */
|
|
Packit |
577717 |
if (has_raw_um || has_um) {
|
|
Packit |
577717 |
DPRINT("cannot mix raw umask with umask\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!(d->pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)) {
|
|
Packit |
577717 |
DPRINT("PMU %s does not support RAW umasks\n", d->pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* we have reserved an entry at the end of pattrs */
|
|
Packit |
577717 |
aidx = d->npattrs;
|
|
Packit |
577717 |
ainfo = d->pattrs + aidx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ainfo->name = "RAW_UMASK";
|
|
Packit |
577717 |
ainfo->type = PFM_ATTR_RAW_UMASK;
|
|
Packit |
577717 |
ainfo->ctrl = PFM_ATTR_CTRL_PMU;
|
|
Packit |
577717 |
/* can handle up to 64-bit raw umask */
|
|
Packit |
577717 |
ainfo->idx = strtoull(s, &endptr, 0);
|
|
Packit |
577717 |
ainfo->equiv= NULL;
|
|
Packit |
577717 |
if (*endptr) {
|
|
Packit |
577717 |
DPRINT("raw umask (%s) is not a number\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
has_raw_um = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
goto found_attr;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(aidx = 0; aidx < d->npattrs; aidx++) {
|
|
Packit |
577717 |
if (!strcasecmp(d->pattrs[aidx].name, s)) {
|
|
Packit |
577717 |
ainfo = d->pattrs + aidx;
|
|
Packit |
577717 |
/* disambiguate modifier and umask
|
|
Packit |
577717 |
* with the same name : snb::L2_LINES_IN:I:I=1
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (has_val && ainfo->type == PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
goto found_attr;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
DPRINT("cannot find attribute %s\n", s);
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
found_attr:
|
|
Packit |
577717 |
type = ainfo->type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (type == PFM_ATTR_UMASK) {
|
|
Packit |
577717 |
has_um = 1;
|
|
Packit |
577717 |
if (has_raw_um) {
|
|
Packit |
577717 |
DPRINT("cannot mix raw umask with umask\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ainfo->equiv) {
|
|
Packit |
577717 |
char *z;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* cannot have equiv for attributes with value */
|
|
Packit |
577717 |
if (has_val)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* copy because it is const */
|
|
Packit |
577717 |
z = strdup(ainfo->equiv);
|
|
Packit |
577717 |
if (!z)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_parse_event_attr(z, d);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
free(z);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
s = p;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we tolerate missing value for boolean attributes.
|
|
Packit |
577717 |
* Presence of the attribute is equivalent to
|
|
Packit |
577717 |
* attr=1, i.e., attribute is set
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (type != PFM_ATTR_UMASK && type != PFM_ATTR_RAW_UMASK && !has_val) {
|
|
Packit |
577717 |
if (type != PFM_ATTR_MOD_BOOL)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
s = yes; /* no const */
|
|
Packit |
577717 |
goto handle_bool;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
d->attrs[d->nattrs].ival = 0;
|
|
Packit |
577717 |
if ((type == PFM_ATTR_UMASK || type == PFM_ATTR_RAW_UMASK) && has_val)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (has_val) {
|
|
Packit |
577717 |
s = q;
|
|
Packit |
577717 |
handle_bool:
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
if (!strlen(s))
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
if (d->nattrs == PFMLIB_MAX_ATTRS) {
|
|
Packit |
577717 |
DPRINT("too many attributes\n");
|
|
Packit |
577717 |
ret = PFM_ERR_TOOMANY;
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
endptr = NULL;
|
|
Packit |
577717 |
switch(type) {
|
|
Packit |
577717 |
case PFM_ATTR_MOD_BOOL:
|
|
Packit |
577717 |
if (strlen(s) > 1)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (tolower((int)*s) == 'y'
|
|
Packit |
577717 |
|| tolower((int)*s) == 't' || *s == '1')
|
|
Packit |
577717 |
d->attrs[d->nattrs].ival = 1;
|
|
Packit |
577717 |
else if (tolower((int)*s) == 'n'
|
|
Packit |
577717 |
|| tolower((int)*s) == 'f' || *s == '0')
|
|
Packit |
577717 |
d->attrs[d->nattrs].ival = 0;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PFM_ATTR_MOD_INTEGER:
|
|
Packit |
577717 |
d->attrs[d->nattrs].ival = strtoull(s, &endptr, 0);
|
|
Packit |
577717 |
if (*endptr != '\0')
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
d->attrs[d->nattrs].id = aidx;
|
|
Packit |
577717 |
d->nattrs++;
|
|
Packit |
577717 |
s = p;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_build_event_pattrs(pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
pfmlib_os_t *os;
|
|
Packit |
577717 |
int i, ret, pmu_nattrs = 0, os_nattrs = 0;
|
|
Packit |
577717 |
int npattrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* cannot satisfy request for an OS that was not activated
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
os = pfmlib_find_os(e->osid);
|
|
Packit |
577717 |
if (!os)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = e->pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* get actual PMU number of attributes for the event */
|
|
Packit |
577717 |
if (pmu->get_event_nattrs)
|
|
Packit |
577717 |
pmu_nattrs = pmu->get_event_nattrs(pmu, e->event);
|
|
Packit |
577717 |
if (os && os->get_os_nattrs)
|
|
Packit |
577717 |
os_nattrs += os->get_os_nattrs(os, e);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
npattrs = pmu_nattrs + os_nattrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* add extra entry for raw umask, if supported
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pmu->flags & PFMLIB_PMU_FL_RAW_UMASK)
|
|
Packit |
577717 |
npattrs++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (npattrs) {
|
|
Packit |
577717 |
e->pattrs = malloc(npattrs * sizeof(*e->pattrs));
|
|
Packit |
577717 |
if (!e->pattrs)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* collect all actual PMU attrs */
|
|
Packit |
577717 |
for(i = 0; i < pmu_nattrs; i++) {
|
|
Packit |
577717 |
ret = pmu->get_event_attr_info(pmu, e->event, i, e->pattrs+i);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
e->npattrs = pmu_nattrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (os_nattrs) {
|
|
Packit |
577717 |
if (e->osid == os->id && os->get_os_attr_info) {
|
|
Packit |
577717 |
os->get_os_attr_info(os, e);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for conflicts between HW and OS attributes
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pmu->validate_pattrs[e->osid])
|
|
Packit |
577717 |
pmu->validate_pattrs[e->osid](pmu, e);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
for (i = 0; i < e->npattrs; i++)
|
|
Packit |
577717 |
DPRINT("%d %d %d %d %d %s\n", e->event, i, e->pattrs[i].type, e->pattrs[i].ctrl, e->pattrs[i].idx, e->pattrs[i].name);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
free(e->pattrs);
|
|
Packit |
577717 |
e->pattrs = NULL;
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfmlib_release_event(pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
free(e->pattrs);
|
|
Packit |
577717 |
e->pattrs = NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
match_event(void *this, pfmlib_event_desc_t *d, const char *e, const char *s)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return strcasecmp(e, s);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_parse_equiv_event(const char *event, pfmlib_event_desc_t *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = d->pmu;
|
|
Packit |
577717 |
pfm_event_info_t einfo;
|
|
Packit |
577717 |
int (*match)(void *this, pfmlib_event_desc_t *d, const char *e, const char *s);
|
|
Packit |
577717 |
char *str, *s, *p;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* create copy because string is const
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
s = str = strdup(event);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
p = s;
|
|
Packit |
577717 |
strsep(&p, PFMLIB_ATTR_DELIM);
|
|
Packit |
577717 |
/* if (p)
|
|
Packit |
577717 |
*p++ = '\0'; */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
match = pmu->match_event ? pmu->match_event : match_event;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_pmu_event(pmu, i) {
|
|
Packit |
577717 |
ret = pmu->get_event_info(pmu, i, &einfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
if (!match(pmu, d, einfo.name, s))
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
return PFM_ERR_NOTFOUND;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
d->pmu = pmu;
|
|
Packit |
577717 |
d->event = i; /* private index */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* build_event_pattrs and parse_event_attr
|
|
Packit |
577717 |
* cannot be factorized with pfmlib_parse_event()
|
|
Packit |
577717 |
* because equivalent event may add its own attributes
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfmlib_build_event_pattrs(d);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_parse_event_attr(p, d);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS)
|
|
Packit |
577717 |
ret = pfmlib_sanitize_event(d);
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
pfmlib_release_event(d);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfmlib_parse_event(const char *event, pfmlib_event_desc_t *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_event_info_t einfo;
|
|
Packit |
577717 |
char *str, *s, *p;
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
int (*match)(void *this, pfmlib_event_desc_t *d, const char *e, const char *s);
|
|
Packit |
577717 |
const char *pname = NULL;
|
|
Packit |
577717 |
int i, j, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* support only one event at a time.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
p = strpbrk(event, PFMLIB_EVENT_DELIM);
|
|
Packit |
577717 |
if (p)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* create copy because string is const
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
s = str = strdup(event);
|
|
Packit |
577717 |
if (!str)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* check for optional PMU name */
|
|
Packit |
577717 |
p = strstr(s, PFMLIB_PMU_DELIM);
|
|
Packit |
577717 |
if (p) {
|
|
Packit |
577717 |
*p = '\0';
|
|
Packit |
577717 |
pname = s;
|
|
Packit |
577717 |
s = p + strlen(PFMLIB_PMU_DELIM);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
p = s;
|
|
Packit |
577717 |
strsep(&p, PFMLIB_ATTR_DELIM);
|
|
Packit |
577717 |
/* if (p)
|
|
Packit |
577717 |
*p++ = '\0'; */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* for each pmu
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_for_each_pmu(j) {
|
|
Packit |
577717 |
pmu = pfmlib_pmus[j];
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if no explicit PMU name is given, then
|
|
Packit |
577717 |
* only look for active PMU models
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!pname && !pfmlib_pmu_active(pmu))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check for requested PMU name,
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pname && strcasecmp(pname, pmu->name))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* only allow event on inactive PMU if enabled via
|
|
Packit |
577717 |
* environement variable
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pname && !pfmlib_pmu_active(pmu) && !pfm_cfg.inactive)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
match = pmu->match_event ? pmu->match_event : match_event;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* for each event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_for_each_pmu_event(pmu, i) {
|
|
Packit |
577717 |
ret = pmu->get_event_info(pmu, i, &einfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
if (!match(pmu, d, einfo.name, s))
|
|
Packit |
577717 |
goto found;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
return PFM_ERR_NOTFOUND;
|
|
Packit |
577717 |
found:
|
|
Packit |
577717 |
d->pmu = pmu;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* handle equivalence
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (einfo.equiv) {
|
|
Packit |
577717 |
ret = pfmlib_parse_equiv_event(einfo.equiv, d);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
d->event = i; /* private index */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_build_event_pattrs(d);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* parse attributes from original event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfmlib_parse_event_attr(p, d);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS)
|
|
Packit |
577717 |
ret = pfmlib_sanitize_event(d);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < d->nattrs; i++) {
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a = attr(d, i);
|
|
Packit |
577717 |
if (a->type != PFM_ATTR_RAW_UMASK)
|
|
Packit |
577717 |
DPRINT("%d %d %d %s\n", d->event, i, a->idx, d->pattrs[d->attrs[i].id].name);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
DPRINT("%d %d RAW_UMASK (0x%x)\n", d->event, i, a->idx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
free(str);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
pfmlib_release_event(d);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* sorry, only English supported at this point! */
|
|
Packit |
577717 |
static const char *pfmlib_err_list[]=
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
"success",
|
|
Packit |
577717 |
"not supported",
|
|
Packit |
577717 |
"invalid parameters",
|
|
Packit |
577717 |
"pfmlib not initialized",
|
|
Packit |
577717 |
"event not found",
|
|
Packit |
577717 |
"invalid combination of model specific features",
|
|
Packit |
577717 |
"invalid or missing unit mask",
|
|
Packit |
577717 |
"out of memory",
|
|
Packit |
577717 |
"invalid event attribute",
|
|
Packit |
577717 |
"invalid event attribute value",
|
|
Packit |
577717 |
"attribute value already set",
|
|
Packit |
577717 |
"too many parameters",
|
|
Packit |
577717 |
"parameter is too small",
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
static int pfmlib_err_count = (int)sizeof(pfmlib_err_list)/sizeof(char *);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const char *
|
|
Packit |
577717 |
pfm_strerror(int code)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
code = -code;
|
|
Packit |
577717 |
if (code <0 || code >= pfmlib_err_count)
|
|
Packit |
577717 |
return "unknown error code";
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pfmlib_err_list[code];
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_version(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return LIBPFM_VERSION;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_next(int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
int pidx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pfmlib_idx2pidx(idx, &pidx);
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pidx = pmu->get_event_next(pmu, pidx);
|
|
Packit |
577717 |
return pidx == -1 ? -1 : pfmlib_pidx2idx(pmu, pidx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_os_event_encoding(const char *str, int dfl_plm, pfm_os_t uos, void *args)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_os_t *os;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!(args && str))
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (dfl_plm & ~(PFM_PLM_ALL))
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
os = pfmlib_find_os(uos);
|
|
Packit |
577717 |
if (!os)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return os->encode(os, str, dfl_plm, args);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* old API maintained for backward compatibility with existing apps
|
|
Packit |
577717 |
* prefer pfm_get_os_event_encoding()
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_encoding(const char *str, int dfl_plm, char **fstr, int *idx, uint64_t **codes, int *count)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_encode_arg_t arg;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!(str && codes && count))
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if ((*codes && !*count) || (!*codes && *count))
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&arg, 0, sizeof(arg));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
arg.fstr = fstr;
|
|
Packit |
577717 |
arg.codes = *codes;
|
|
Packit |
577717 |
arg.count = *count;
|
|
Packit |
577717 |
arg.size = sizeof(arg);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* request RAW PMU encoding
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = pfm_get_os_event_encoding(str, dfl_plm, PFM_OS_NONE, &arg;;
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* handle the case where the array was allocated */
|
|
Packit |
577717 |
*codes = arg.codes;
|
|
Packit |
577717 |
*count = arg.count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (idx)
|
|
Packit |
577717 |
*idx = arg.idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_check_event_pattrs(pfmlib_pmu_t *pmu, int pidx, pfm_os_t osid, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
int i, j, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
e.event = pidx;
|
|
Packit |
577717 |
e.osid = osid;
|
|
Packit |
577717 |
e.pmu = pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_build_event_pattrs(&e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
fprintf(fp, "invalid pattrs for event %d\n", pidx);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < e.npattrs; i++) {
|
|
Packit |
577717 |
for (j = i+1; j < e.npattrs; j++) {
|
|
Packit |
577717 |
if (!strcmp(e.pattrs[i].name, e.pattrs[j].name)) {
|
|
Packit |
577717 |
fprintf(fp, "event %d duplicate pattrs %s\n", pidx, e.pattrs[i].name);
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* release resources allocated for event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_validate_encoding(char *buf, int plm)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
uint64_t *codes = NULL;
|
|
Packit |
577717 |
int count = 0, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_get_event_encoding(buf, plm, NULL, NULL, &codes, &count);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
DPRINT("%s ", buf);
|
|
Packit |
577717 |
for(i=0; i < count; i++)
|
|
Packit |
577717 |
__pfm_dbprintf(" %#"PRIx64, codes[i]);
|
|
Packit |
577717 |
__pfm_dbprintf("\n");
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (codes)
|
|
Packit |
577717 |
free(codes);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_pmu_validate_encoding(pfmlib_pmu_t *pmu, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_event_info_t einfo;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t ainfo;
|
|
Packit |
577717 |
char *buf;
|
|
Packit |
577717 |
size_t maxlen = 0, len;
|
|
Packit |
577717 |
int i, u, n = 0, um;
|
|
Packit |
577717 |
int ret, retval = PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_pmu_event(pmu, i) {
|
|
Packit |
577717 |
ret = pmu->get_event_info(pmu, i, &einfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_check_event_pattrs(pmu, i, PFM_OS_NONE, fp);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
len = strlen(einfo.name);
|
|
Packit |
577717 |
if (len > maxlen)
|
|
Packit |
577717 |
maxlen = len;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for_each_pmu_event_attr(u, &einfo) {
|
|
Packit |
577717 |
ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ainfo.type != PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
len = strlen(einfo.name) + strlen(ainfo.name);
|
|
Packit |
577717 |
if (len > maxlen)
|
|
Packit |
577717 |
maxlen = len;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* 2 = ::, 1=:, 1=eol */
|
|
Packit |
577717 |
maxlen += strlen(pmu->name) + 2 + 1 + 1;
|
|
Packit |
577717 |
buf = malloc(maxlen);
|
|
Packit |
577717 |
if (!buf)
|
|
Packit |
577717 |
return PFM_ERR_NOMEM;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_pmu_event(pmu, i) {
|
|
Packit |
577717 |
ret = pmu->get_event_info(pmu, i, &einfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
retval = ret;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
um = 0;
|
|
Packit |
577717 |
for_each_pmu_event_attr(u, &einfo) {
|
|
Packit |
577717 |
ret = pmu->get_event_attr_info(pmu, i, u, &ainfo);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
retval = ret;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ainfo.type != PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: some events may require more than one umasks to encode
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
sprintf(buf, "%s::%s:%s", pmu->name, einfo.name, ainfo.name);
|
|
Packit |
577717 |
ret = pfmlib_validate_encoding(buf, PFM_PLM3|PFM_PLM0);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
if (pmu->can_auto_encode) {
|
|
Packit |
577717 |
if (!pmu->can_auto_encode(pmu, i, u))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* some PMU may not support raw encoding
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (ret != PFM_ERR_NOTSUPP) {
|
|
Packit |
577717 |
fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
|
|
Packit |
577717 |
retval = ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
um++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (um == 0) {
|
|
Packit |
577717 |
sprintf(buf, "%s::%s", pmu->name, einfo.name);
|
|
Packit |
577717 |
ret = pfmlib_validate_encoding(buf, PFM_PLM3|PFM_PLM0);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
if (pmu->can_auto_encode) {
|
|
Packit |
577717 |
if (!pmu->can_auto_encode(pmu, i, u))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (ret != PFM_ERR_NOTSUPP) {
|
|
Packit |
577717 |
fprintf(fp, "cannot encode event %s : %s\n", buf, pfm_strerror(ret));
|
|
Packit |
577717 |
retval = ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
n++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
free(buf);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return retval;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_pmu_validate(pfm_pmu_t pmu_id, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu, *pmx;
|
|
Packit |
577717 |
int nos = 0;
|
|
Packit |
577717 |
int i, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fp == NULL)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pmu2pmuidx(pmu_id);
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfmlib_pmu_initialized(pmu)) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: initialization failed\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->name) {
|
|
Packit |
577717 |
fprintf(fp, "pmu id: %d :: no name\n", pmu->pmu);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->desc) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: no description\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->pmu >= PFM_PMU_MAX) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: invalid PMU id\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->max_encoding >= PFMLIB_MAX_ENCODING) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: max encoding too high\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfmlib_pmu_active(pmu) && !pmu->pme_count) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: no events\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->pmu_detect) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: missing pmu_detect callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->get_event_first) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: missing get_event_first callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->get_event_next) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: missing get_event_next callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->get_event_info) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: missing get_event_info callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->get_event_attr_info) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: missing get_event_attr_info callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
for (i = PFM_OS_NONE; i < PFM_OS_MAX; i++) {
|
|
Packit |
577717 |
if (pmu->get_event_encoding[i])
|
|
Packit |
577717 |
nos++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!nos) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: no os event encoding callback\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!pmu->max_encoding) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: max_encoding is zero\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* look for duplicate names, id */
|
|
Packit |
577717 |
pfmlib_for_each_pmu(i) {
|
|
Packit |
577717 |
pmx = pfmlib_pmus[i];
|
|
Packit |
577717 |
if (!pfmlib_pmu_active(pmx))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (pmx == pmu)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (!strcasecmp(pmx->name, pmu->name)) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: duplicate name\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (pmx->pmu == pmu->pmu) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s :: duplicate id\n", pmu->name);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->validate_table) {
|
|
Packit |
577717 |
ret = pmu->validate_table(pmu, fp);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return pfmlib_pmu_validate_encoding(pmu, fp);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_info(int idx, pfm_os_t os, pfm_event_info_t *uinfo)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_event_info_t info;
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
size_t sz = sizeof(info);
|
|
Packit |
577717 |
int pidx, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!PFMLIB_INITIALIZED())
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (os >= PFM_OS_MAX)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pfmlib_idx2pidx(idx, &pidx);
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!uinfo)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_EVENT_INFO_ABI0, sz);
|
|
Packit |
577717 |
if (!sz)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&info, 0, sizeof(info));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info.size = sz;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* default data type is uint64 */
|
|
Packit |
577717 |
info.dtype = PFM_DTYPE_UINT64;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* reset flags */
|
|
Packit |
577717 |
info.is_precise = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pmu->get_event_info(pmu, pidx, &info;;
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info.pmu = pmu->pmu;
|
|
Packit |
577717 |
info.idx = idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
e.event = pidx;
|
|
Packit |
577717 |
e.osid = os;
|
|
Packit |
577717 |
e.pmu = pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_build_event_pattrs(&e);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS) {
|
|
Packit |
577717 |
info.nattrs = e.npattrs;
|
|
Packit |
577717 |
memcpy(uinfo, &info, sz);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_event_attr_info(int idx, int attr_idx, pfm_os_t os, pfm_event_attr_info_t *uinfo)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_attr_info_t info;
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
size_t sz = sizeof(info);
|
|
Packit |
577717 |
int pidx, ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!PFMLIB_INITIALIZED())
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (attr_idx < 0)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (os >= PFM_OS_MAX)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pfmlib_idx2pidx(idx, &pidx);
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!uinfo)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_ATTR_INFO_ABI0, sz);
|
|
Packit |
577717 |
if (!sz)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
e.event = pidx;
|
|
Packit |
577717 |
e.osid = os;
|
|
Packit |
577717 |
e.pmu = pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_build_event_pattrs(&e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (attr_idx >= e.npattrs)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* copy event_attr_info
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
info = e.pattrs[attr_idx];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* info.idx = private, namespace specific index,
|
|
Packit |
577717 |
* should not be visible externally, so override
|
|
Packit |
577717 |
* with public index
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* cannot memcpy() info into uinfo as they do not
|
|
Packit |
577717 |
* have the same size, cf. idx field (uint64 vs, uint32)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
uinfo->name = info.name;
|
|
Packit |
577717 |
uinfo->desc = info.desc;
|
|
Packit |
577717 |
uinfo->equiv = info.equiv;
|
|
Packit |
577717 |
uinfo->size = sz;
|
|
Packit |
577717 |
uinfo->code = info.code;
|
|
Packit |
577717 |
uinfo->type = info.type;
|
|
Packit |
577717 |
uinfo->idx = attr_idx;
|
|
Packit |
577717 |
uinfo->ctrl = info.ctrl;
|
|
Packit |
577717 |
uinfo->is_dfl= info.is_dfl;
|
|
Packit |
577717 |
uinfo->is_precise = info.is_precise;
|
|
Packit |
577717 |
uinfo->reserved_bits = 0;
|
|
Packit |
577717 |
uinfo->dfl_val64 = info.dfl_val64;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_pmu_info(pfm_pmu_t pmuid, pfm_pmu_info_t *uinfo)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_info_t info;
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
size_t sz = sizeof(info);
|
|
Packit |
577717 |
int pidx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!PFMLIB_INITIALIZED())
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmuid >= PFM_PMU_MAX)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!uinfo)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = pfmlib_check_struct(uinfo, uinfo->size, PFM_PMU_INFO_ABI0, sz);
|
|
Packit |
577717 |
if (!sz)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = pfmlib_pmus_map[pmuid];
|
|
Packit |
577717 |
if (!pmu)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info.name = pmu->name;
|
|
Packit |
577717 |
info.desc = pmu->desc;
|
|
Packit |
577717 |
info.pmu = pmuid;
|
|
Packit |
577717 |
info.size = sz;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info.max_encoding = pmu->max_encoding;
|
|
Packit |
577717 |
info.num_cntrs = pmu->num_cntrs;
|
|
Packit |
577717 |
info.num_fixed_cntrs = pmu->num_fixed_cntrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pidx = pmu->get_event_first(pmu);
|
|
Packit |
577717 |
if (pidx == -1)
|
|
Packit |
577717 |
info.first_event = -1;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
info.first_event = pfmlib_pidx2idx(pmu, pidx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* XXX: pme_count only valid when PMU is detected
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
info.is_present = pfmlib_pmu_active(pmu);
|
|
Packit |
577717 |
info.is_dfl = !!(pmu->flags & PFMLIB_PMU_FL_ARCH_DFL);
|
|
Packit |
577717 |
info.type = pmu->type;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->get_num_events)
|
|
Packit |
577717 |
info.nevents = pmu->get_num_events(pmu);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
info.nevents = pmu->pme_count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memcpy(uinfo, &info, sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_pmu_t *
|
|
Packit |
577717 |
pfmlib_get_pmu_by_type(pfm_pmu_type_t t)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_pmu(i) {
|
|
Packit |
577717 |
pmu = pfmlib_pmus[i];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pfmlib_pmu_active(pmu))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* first match */
|
|
Packit |
577717 |
if (pmu->type != t)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return pmu;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return NULL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_compare_attr_id(const void *a, const void *b)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const pfmlib_attr_t *t1 = a;
|
|
Packit |
577717 |
const pfmlib_attr_t *t2 = b;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (t1->id < t2->id)
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
return t1->id == t2->id ? 0 : 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
void
|
|
Packit |
577717 |
pfmlib_sort_attr(pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
qsort(e->attrs, e->nattrs, sizeof(pfmlib_attr_t), pfmlib_compare_attr_id);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_raw_pmu_encode(void *this, const char *str, int dfl_plm, void *data)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_encode_arg_t arg;
|
|
Packit |
577717 |
pfm_pmu_encode_arg_t *uarg = data;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
size_t sz = sizeof(arg);
|
|
Packit |
577717 |
int ret, i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = pfmlib_check_struct(uarg, uarg->size, PFM_RAW_ENCODE_ABI0, sz);
|
|
Packit |
577717 |
if (!sz)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&arg, 0, sizeof(arg));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* get input data
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
memcpy(&arg, uarg, sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e.osid = PFM_OS_NONE;
|
|
Packit |
577717 |
e.dfl_plm = dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_parse_event(str, &e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pmu = e.pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->get_event_encoding[PFM_OS_NONE]) {
|
|
Packit |
577717 |
DPRINT("PMU %s does not support PFM_OS_NONE\n", pmu->name);
|
|
Packit |
577717 |
ret = PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pmu->get_event_encoding[PFM_OS_NONE](pmu, &e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* return opaque event identifier
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
arg.idx = pfmlib_pidx2idx(e.pmu, e.event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (arg.codes == NULL) {
|
|
Packit |
577717 |
ret = PFM_ERR_NOMEM;
|
|
Packit |
577717 |
arg.codes = malloc(sizeof(uint64_t) * e.count);
|
|
Packit |
577717 |
if (!arg.codes)
|
|
Packit |
577717 |
goto error_fstr;
|
|
Packit |
577717 |
} else if (arg.count < e.count) {
|
|
Packit |
577717 |
ret = PFM_ERR_TOOSMALL;
|
|
Packit |
577717 |
goto error_fstr;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
arg.count = e.count;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < e.count; i++)
|
|
Packit |
577717 |
arg.codes[i] = e.codes[i];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (arg.fstr) {
|
|
Packit |
577717 |
ret = pfmlib_build_fstr(&e, arg.fstr);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto error;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* copy out results */
|
|
Packit |
577717 |
memcpy(uarg, &arg, sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
error_fstr:
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
free(arg.fstr);
|
|
Packit |
577717 |
error:
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* release resources allocated for event
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_raw_pmu_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static pfmlib_os_t pfmlib_os_none= {
|
|
Packit |
577717 |
.name = "No OS (raw PMU)",
|
|
Packit |
577717 |
.id = PFM_OS_NONE,
|
|
Packit |
577717 |
.flags = PFMLIB_OS_FL_ACTIVATED,
|
|
Packit |
577717 |
.encode = pfmlib_raw_pmu_encode,
|
|
Packit |
577717 |
.detect = pfmlib_raw_pmu_detect,
|
|
Packit |
577717 |
};
|