Blame src/libpfm4/lib/pfmlib_common.c

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
};