|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_perf_events.c: encode events for perf_event API
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2009 Google, Inc
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@google.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 <unistd.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <limits.h>
|
|
Packit |
577717 |
#include <perfmon/pfmlib_perf_event.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
#include "pfmlib_perf_event_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define PERF_PROC_FILE "/proc/sys/kernel/perf_event_paranoid"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef min
|
|
Packit |
577717 |
#undef min
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#define min(a, b) ((a) < (b) ? (a) : (b))
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* contains ONLY attributes related to PMU features
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static const pfmlib_attr_desc_t perf_event_mods[]={
|
|
Packit |
577717 |
PFM_ATTR_B("u", "monitor at user level"), /* monitor user level */
|
|
Packit |
577717 |
PFM_ATTR_B("k", "monitor at kernel level"), /* monitor kernel level */
|
|
Packit |
577717 |
PFM_ATTR_B("h", "monitor at hypervisor level"), /* monitor hypervisor level */
|
|
Packit |
577717 |
PFM_ATTR_SKIP,
|
|
Packit |
577717 |
PFM_ATTR_SKIP,
|
|
Packit |
577717 |
PFM_ATTR_SKIP,
|
|
Packit |
577717 |
PFM_ATTR_SKIP,
|
|
Packit |
577717 |
PFM_ATTR_B("mg", "monitor guest execution"), /* monitor guest level */
|
|
Packit |
577717 |
PFM_ATTR_B("mh", "monitor host execution"), /* monitor host level */
|
|
Packit |
577717 |
PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* contains all attributes controlled by perf_events. That includes PMU attributes
|
|
Packit |
577717 |
* and pure software attributes such as sampling periods
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static const pfmlib_attr_desc_t perf_event_ext_mods[]={
|
|
Packit |
577717 |
PFM_ATTR_B("u", "monitor at user level"), /* monitor user level */
|
|
Packit |
577717 |
PFM_ATTR_B("k", "monitor at kernel level"), /* monitor kernel level */
|
|
Packit |
577717 |
PFM_ATTR_B("h", "monitor at hypervisor level"), /* monitor hypervisor level */
|
|
Packit |
577717 |
PFM_ATTR_I("period", "sampling period"), /* sampling period */
|
|
Packit |
577717 |
PFM_ATTR_I("freq", "sampling frequency (Hz)"), /* sampling frequency */
|
|
Packit |
577717 |
PFM_ATTR_I("precise", "precise ip"), /* anti-skid mechanism */
|
|
Packit |
577717 |
PFM_ATTR_B("excl", "exclusive access"), /* exclusive PMU access */
|
|
Packit |
577717 |
PFM_ATTR_B("mg", "monitor guest execution"), /* monitor guest level */
|
|
Packit |
577717 |
PFM_ATTR_B("mh", "monitor host execution"), /* monitor host level */
|
|
Packit |
577717 |
PFM_ATTR_I("cpu", "CPU to program"), /* CPU to program */
|
|
Packit |
577717 |
PFM_ATTR_B("pinned", "pin event to counters"), /* pin event to PMU */
|
|
Packit |
577717 |
PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfmlib_perf_event_encode(void *this, const char *str, int dfl_plm, void *data)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_perf_encode_arg_t arg;
|
|
Packit |
577717 |
pfm_perf_encode_arg_t *uarg = data;
|
|
Packit |
577717 |
pfmlib_os_t *os = this;
|
|
Packit |
577717 |
struct perf_event_attr my_attr, *attr;
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu;
|
|
Packit |
577717 |
pfmlib_event_desc_t e;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
size_t orig_sz, asz, sz = sizeof(arg);
|
|
Packit |
577717 |
uint64_t ival;
|
|
Packit |
577717 |
int has_plm = 0, has_vmx_plm = 0;
|
|
Packit |
577717 |
int i, plm = 0, ret, vmx_plm = 0;
|
|
Packit |
577717 |
int cpu = -1, pinned = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
sz = pfmlib_check_struct(uarg, uarg->size, PFM_PERF_ENCODE_ABI0, sz);
|
|
Packit |
577717 |
if (!sz)
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* copy input */
|
|
Packit |
577717 |
memcpy(&arg, uarg, sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* pointer to our internal attr struct */
|
|
Packit |
577717 |
memset(&my_attr, 0, sizeof(my_attr));
|
|
Packit |
577717 |
attr = &my_attr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* copy user attr to our internal version
|
|
Packit |
577717 |
* size == 0 is interpreted minimal possible
|
|
Packit |
577717 |
* size (ABI_VER0)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* size of attr struct passed by user */
|
|
Packit |
577717 |
orig_sz = uarg->attr->size;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (orig_sz == 0)
|
|
Packit |
577717 |
asz = PERF_ATTR_SIZE_VER0;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
asz = min(sizeof(*attr), orig_sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we copy the user struct to preserve whatever may
|
|
Packit |
577717 |
* have been initialized but that we do not use
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
memcpy(attr, uarg->attr, asz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* restore internal size (just in case we need it) */
|
|
Packit |
577717 |
attr->size = sizeof(my_attr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* useful for debugging */
|
|
Packit |
577717 |
if (asz != sizeof(*attr))
|
|
Packit |
577717 |
__pfm_vbprintf("warning: mismatch attr struct size "
|
|
Packit |
577717 |
"user=%d libpfm=%zu\n", asz, sizeof(*attr));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(&e, 0, sizeof(e));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e.osid = os->id;
|
|
Packit |
577717 |
e.os_data = attr;
|
|
Packit |
577717 |
e.dfl_plm = dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* after this call, need to call pfmlib_release_event() */
|
|
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 |
ret = PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
if (!pmu->get_event_encoding[e.osid]) {
|
|
Packit |
577717 |
DPRINT("PMU %s does not support PFM_OS_NONE\n", pmu->name);
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pmu->get_event_encoding[e.osid](pmu, &e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* process perf_event attributes
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = 0; i < e.nattrs; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
a = attr(&e, i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->ctrl != PFM_ATTR_CTRL_PERF_EVENT)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ival = e.attrs[i].ival;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(a->idx) {
|
|
Packit |
577717 |
case PERF_ATTR_U:
|
|
Packit |
577717 |
if (ival)
|
|
Packit |
577717 |
plm |= PFM_PLM3;
|
|
Packit |
577717 |
has_plm = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_K:
|
|
Packit |
577717 |
if (ival)
|
|
Packit |
577717 |
plm |= PFM_PLM0;
|
|
Packit |
577717 |
has_plm = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_H:
|
|
Packit |
577717 |
if (ival)
|
|
Packit |
577717 |
plm |= PFM_PLMH;
|
|
Packit |
577717 |
has_plm = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_PE:
|
|
Packit |
577717 |
if (!ival || attr->freq) {
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
attr->sample_period = ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_FR:
|
|
Packit |
577717 |
if (!ival || attr->sample_period) {
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
attr->sample_freq = ival;
|
|
Packit |
577717 |
attr->freq = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_PR:
|
|
Packit |
577717 |
if (ival > 3) {
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
attr->precise_ip = ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_EX:
|
|
Packit |
577717 |
if (ival && !attr->exclusive)
|
|
Packit |
577717 |
attr->exclusive = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_MG:
|
|
Packit |
577717 |
vmx_plm |= PFM_PLM3;
|
|
Packit |
577717 |
has_vmx_plm = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_MH:
|
|
Packit |
577717 |
vmx_plm |= PFM_PLM0;
|
|
Packit |
577717 |
has_vmx_plm = 1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_CPU:
|
|
Packit |
577717 |
if (ival >= INT_MAX) {
|
|
Packit |
577717 |
ret = PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
cpu = (int)ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_PIN:
|
|
Packit |
577717 |
pinned = (int)!!ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if no priv level mask was provided
|
|
Packit |
577717 |
* with the event, then use dfl_plm
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!has_plm)
|
|
Packit |
577717 |
plm = dfl_plm;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* exclude_guest by default */
|
|
Packit |
577717 |
if (!has_vmx_plm)
|
|
Packit |
577717 |
vmx_plm = PFM_PLM0;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* perf_event plm work by exclusion, so use logical or
|
|
Packit |
577717 |
* goal here is to set to zero any exclude_* not supported
|
|
Packit |
577717 |
* by underlying PMU
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
plm |= (~pmu->supported_plm) & PFM_PLM_ALL;
|
|
Packit |
577717 |
vmx_plm |= (~pmu->supported_plm) & PFM_PLM_ALL;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
attr->exclude_user = !(plm & PFM_PLM3);
|
|
Packit |
577717 |
attr->exclude_kernel = !(plm & PFM_PLM0);
|
|
Packit |
577717 |
attr->exclude_hv = !(plm & PFM_PLMH);
|
|
Packit |
577717 |
attr->exclude_guest = !(vmx_plm & PFM_PLM3);
|
|
Packit |
577717 |
attr->exclude_host = !(vmx_plm & PFM_PLM0);
|
|
Packit |
577717 |
attr->pinned = pinned;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("PERF[type=%x config=0x%"PRIx64" config1=0x%"PRIx64
|
|
Packit |
577717 |
" excl=%d e_u=%d e_k=%d e_hv=%d e_host=%d e_gu=%d period=%"PRIu64" freq=%d"
|
|
Packit |
577717 |
" precise=%d pinned=%d] %s\n",
|
|
Packit |
577717 |
attr->type,
|
|
Packit |
577717 |
attr->config,
|
|
Packit |
577717 |
attr->config1,
|
|
Packit |
577717 |
attr->exclusive,
|
|
Packit |
577717 |
attr->exclude_user,
|
|
Packit |
577717 |
attr->exclude_kernel,
|
|
Packit |
577717 |
attr->exclude_hv,
|
|
Packit |
577717 |
attr->exclude_host,
|
|
Packit |
577717 |
attr->exclude_guest,
|
|
Packit |
577717 |
attr->sample_period,
|
|
Packit |
577717 |
attr->freq,
|
|
Packit |
577717 |
attr->precise_ip,
|
|
Packit |
577717 |
attr->pinned,
|
|
Packit |
577717 |
str);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* propagate event index if necessary
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
arg.idx = pfmlib_pidx2idx(e.pmu, e.event);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* propagate cpu */
|
|
Packit |
577717 |
arg.cpu = cpu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* propagate our changes, that overwrites attr->size */
|
|
Packit |
577717 |
memcpy(uarg->attr, attr, asz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* restore user size */
|
|
Packit |
577717 |
uarg->attr->size = orig_sz;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* fstr not requested, stop here
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
ret = PFM_SUCCESS;
|
|
Packit |
577717 |
if (!arg.fstr) {
|
|
Packit |
577717 |
memcpy(uarg, &arg, sz);
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0; i < e.npattrs; i++) {
|
|
Packit |
577717 |
int idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (e.pattrs[i].ctrl != PFM_ATTR_CTRL_PERF_EVENT)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
idx = e.pattrs[i].idx;
|
|
Packit |
577717 |
switch (idx) {
|
|
Packit |
577717 |
case PERF_ATTR_K:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, !!(plm & PFM_PLM0));
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_U:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, !!(plm & PFM_PLM3));
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_H:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, !!(plm & PFM_PLMH));
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_PR:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%d", perf_event_ext_mods[idx].name, attr->precise_ip);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_PE:
|
|
Packit |
577717 |
case PERF_ATTR_FR:
|
|
Packit |
577717 |
if (attr->freq && attr->sample_period)
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%"PRIu64, perf_event_ext_mods[idx].name, attr->sample_period);
|
|
Packit |
577717 |
else if (attr->sample_period)
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%"PRIu64, perf_event_ext_mods[idx].name, attr->sample_period);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_MG:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, !attr->exclude_guest);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_MH:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, !attr->exclude_host);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case PERF_ATTR_EX:
|
|
Packit |
577717 |
evt_strcat(e.fstr, ":%s=%lu", perf_event_ext_mods[idx].name, attr->exclusive);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfmlib_build_fstr(&e, arg.fstr);
|
|
Packit |
577717 |
if (ret == PFM_SUCCESS)
|
|
Packit |
577717 |
memcpy(uarg, &arg, sz);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
pfmlib_release_event(&e);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* get OS-specific event attributes
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
perf_get_os_nattrs(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_os_t *os = this;
|
|
Packit |
577717 |
int i, n = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; os->atdesc[i].name; i++)
|
|
Packit |
577717 |
if (!is_empty_attr(os->atdesc+i))
|
|
Packit |
577717 |
n++;
|
|
Packit |
577717 |
return n;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
perf_get_os_attr_info(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_os_t *os = this;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *info;
|
|
Packit |
577717 |
int i, k, j = e->npattrs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = k = 0; os->atdesc[i].name; i++) {
|
|
Packit |
577717 |
/* skip padding entries */
|
|
Packit |
577717 |
if (is_empty_attr(os->atdesc+i))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info = e->pattrs + j + k;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->name = os->atdesc[i].name;
|
|
Packit |
577717 |
info->desc = os->atdesc[i].desc;
|
|
Packit |
577717 |
info->equiv= NULL;
|
|
Packit |
577717 |
info->code = i;
|
|
Packit |
577717 |
info->idx = i; /* namespace-specific index */
|
|
Packit |
577717 |
info->type = os->atdesc[i].type;
|
|
Packit |
577717 |
info->is_dfl = 0;
|
|
Packit |
577717 |
info->ctrl = PFM_ATTR_CTRL_PERF_EVENT;
|
|
Packit |
577717 |
k++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
e->npattrs += k;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* old interface, maintained for backward compatibility with earlier versions of the library
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_get_perf_event_encoding(const char *str, int dfl_plm, struct perf_event_attr *attr, char **fstr, int *idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_perf_encode_arg_t arg;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (PFMLIB_INITIALIZED() == 0)
|
|
Packit |
577717 |
return PFM_ERR_NOINIT;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* idx and fstr can be NULL */
|
|
Packit |
577717 |
if (!(attr && 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 |
memset(&arg, 0, sizeof(arg));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* do not clear attr, some fields may be initialized by caller already, e.g., size */
|
|
Packit |
577717 |
arg.attr = attr;
|
|
Packit |
577717 |
arg.fstr = fstr;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_get_os_event_encoding(str, dfl_plm, PFM_OS_PERF_EVENT_EXT, &arg;;
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
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 |
pfm_perf_event_os_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret = access(PERF_PROC_FILE, F_OK);
|
|
Packit |
577717 |
return ret ? PFM_ERR_NOTSUPP : PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_os_t pfmlib_os_perf={
|
|
Packit |
577717 |
.name = "perf_event",
|
|
Packit |
577717 |
.id = PFM_OS_PERF_EVENT,
|
|
Packit |
577717 |
.atdesc = perf_event_mods,
|
|
Packit |
577717 |
.detect = pfm_perf_event_os_detect,
|
|
Packit |
577717 |
.get_os_attr_info = perf_get_os_attr_info,
|
|
Packit |
577717 |
.get_os_nattrs = perf_get_os_nattrs,
|
|
Packit |
577717 |
.encode = pfmlib_perf_event_encode,
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_os_t pfmlib_os_perf_ext={
|
|
Packit |
577717 |
.name = "perf_event extended",
|
|
Packit |
577717 |
.id = PFM_OS_PERF_EVENT_EXT,
|
|
Packit |
577717 |
.atdesc = perf_event_ext_mods,
|
|
Packit |
577717 |
.detect = pfm_perf_event_os_detect,
|
|
Packit |
577717 |
.get_os_attr_info = perf_get_os_attr_info,
|
|
Packit |
577717 |
.get_os_nattrs = perf_get_os_nattrs,
|
|
Packit |
577717 |
.encode = pfmlib_perf_event_encode,
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
|