|
Packit |
577717 |
/* pfmlib_intel_x86.c : common code for Intel X86 processors
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2009 Google, Inc
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@gmail.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 |
* This file implements the common code for all Intel X86 processors.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
#include <stdarg.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
#include "pfmlib_intel_x86_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const pfmlib_attr_desc_t intel_x86_mods[]={
|
|
Packit |
577717 |
PFM_ATTR_B("k", "monitor at priv level 0"), /* monitor priv level 0 */
|
|
Packit |
577717 |
PFM_ATTR_B("u", "monitor at priv level 1, 2, 3"), /* monitor priv level 1, 2, 3 */
|
|
Packit |
577717 |
PFM_ATTR_B("e", "edge level (may require counter-mask >= 1)"), /* edge */
|
|
Packit |
577717 |
PFM_ATTR_B("i", "invert"), /* invert */
|
|
Packit |
577717 |
PFM_ATTR_I("c", "counter-mask in range [0-255]"), /* counter-mask */
|
|
Packit |
577717 |
PFM_ATTR_B("t", "measure any thread"), /* monitor on both threads */
|
|
Packit |
577717 |
PFM_ATTR_I("ldlat", "load latency threshold (cycles, [3-65535])"), /* load latency threshold */
|
|
Packit |
577717 |
PFM_ATTR_B("intx", "monitor only inside transactional memory region"),
|
|
Packit |
577717 |
PFM_ATTR_B("intxcp", "do not count occurrences inside aborted transactional memory region"),
|
|
Packit |
577717 |
PFM_ATTR_I("fe_thres", "frontend bubble latency threshold in cycles ([1-4095]"),
|
|
Packit |
577717 |
PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_intel_x86_config_t pfm_intel_x86_cfg;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#define mdhw(m, u, at) (m & u & _INTEL_X86_##at)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* .byte 0x53 == push ebx. it's universal for 32 and 64 bit
|
|
Packit |
577717 |
* .byte 0x5b == pop ebx.
|
|
Packit |
577717 |
* Some gcc's (4.1.2 on Core2) object to pairing push/pop and ebx in 64 bit mode.
|
|
Packit |
577717 |
* Using the opcode directly avoids this problem.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static inline void
|
|
Packit |
577717 |
cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c, unsigned int *d)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\tmovl %%ebx, %%esi\n\t.byte 0x5b"
|
|
Packit |
577717 |
: "=a" (*a),
|
|
Packit |
577717 |
"=S" (*b),
|
|
Packit |
577717 |
"=c" (*c),
|
|
Packit |
577717 |
"=d" (*d)
|
|
Packit |
577717 |
: "a" (op));
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
pfm_intel_x86_display_reg(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfm_intel_x86_reg_t reg;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.val = e->codes[0];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* handle generic counters
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
__pfm_vbprintf("[0x%"PRIx64" event_sel=0x%x umask=0x%x os=%d usr=%d "
|
|
Packit |
577717 |
"en=%d int=%d inv=%d edge=%d cnt_mask=%d",
|
|
Packit |
577717 |
reg.val,
|
|
Packit |
577717 |
reg.sel_event_select,
|
|
Packit |
577717 |
reg.sel_unit_mask,
|
|
Packit |
577717 |
reg.sel_os,
|
|
Packit |
577717 |
reg.sel_usr,
|
|
Packit |
577717 |
reg.sel_en,
|
|
Packit |
577717 |
reg.sel_int,
|
|
Packit |
577717 |
reg.sel_inv,
|
|
Packit |
577717 |
reg.sel_edge,
|
|
Packit |
577717 |
reg.sel_cnt_mask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[e->event].modmsk & _INTEL_X86_ATTR_T)
|
|
Packit |
577717 |
__pfm_vbprintf(" any=%d", reg.sel_anythr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("]", e->fstr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 1 ; i < e->count; i++)
|
|
Packit |
577717 |
__pfm_vbprintf(" [0x%"PRIx64"]", e->codes[i]);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf(" %s\n", e->fstr);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* number of HW modifiers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
intel_x86_num_mods(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
unsigned int mask;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
mask = pe[idx].modmsk;
|
|
Packit |
577717 |
return pfmlib_popcnt(mask);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
intel_x86_attr2mod(void *this, int pidx, int attr_idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
size_t x;
|
|
Packit |
577717 |
int n, numasks;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
numasks = intel_x86_num_umasks(this, pidx);
|
|
Packit |
577717 |
n = attr_idx - numasks;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_for_each_bit(x, pe[pidx].modmsk) {
|
|
Packit |
577717 |
if (n == 0)
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
n--;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return x;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* detect processor model using cpuid()
|
|
Packit |
577717 |
* based on documentation
|
|
Packit |
577717 |
* http://www.intel.com/Assets/PDF/appnote/241618.pdf
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_detect(void)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int a, b, c, d;
|
|
Packit |
577717 |
char buffer[64];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family)
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuid(0, &a, &b, &c, &d);
|
|
Packit |
577717 |
strncpy(&buffer[0], (char *)(&b), 4);
|
|
Packit |
577717 |
strncpy(&buffer[4], (char *)(&d), 4);
|
|
Packit |
577717 |
strncpy(&buffer[8], (char *)(&c), 4);
|
|
Packit |
577717 |
buffer[12] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* must be Intel */
|
|
Packit |
577717 |
if (strcmp(buffer, "GenuineIntel"))
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuid(1, &a, &b, &c, &d);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_intel_x86_cfg.family = (a >> 8) & 0xf; // bits 11 - 8
|
|
Packit |
577717 |
pfm_intel_x86_cfg.model = (a >> 4) & 0xf; // Bits 7 - 4
|
|
Packit |
577717 |
pfm_intel_x86_cfg.stepping = a & 0xf; // Bits 0 - 3
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* extended family */
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family == 0xf)
|
|
Packit |
577717 |
pfm_intel_x86_cfg.family += (a >> 20) & 0xff;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* extended model */
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family >= 0x6)
|
|
Packit |
577717 |
pfm_intel_x86_cfg.model += ((a >> 16) & 0xf) << 4;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int pfm_intel_x86_model_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const int *p;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != pmu->cpu_family)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (p = pmu->cpu_models; *p; p++) {
|
|
Packit |
577717 |
if (*p == pfm_intel_x86_cfg.model)
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_add_defaults(void *this, pfmlib_event_desc_t *e,
|
|
Packit |
577717 |
unsigned int msk,
|
|
Packit |
577717 |
uint64_t *umask,
|
|
Packit |
577717 |
unsigned short max_grpid,
|
|
Packit |
577717 |
int excl_grp_but_0)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
const intel_x86_entry_t *ent;
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
unsigned short grpid;
|
|
Packit |
577717 |
int j, k, added, skip;
|
|
Packit |
577717 |
int idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
k = e->nattrs;
|
|
Packit |
577717 |
ent = pe+e->event;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; msk; msk >>=1, i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!(msk & 0x1))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
added = skip = 0;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* must scan list of possible attributes
|
|
Packit |
577717 |
* (not all possible attributes)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (j = 0; j < e->npattrs; j++) {
|
|
Packit |
577717 |
if (e->pattrs[j].ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (e->pattrs[j].type != PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
idx = e->pattrs[j].idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ent->umasks[idx].grpid != i)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (max_grpid != INTEL_X86_MAX_GRPID && i > max_grpid) {
|
|
Packit |
577717 |
skip = 1;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, idx, INTEL_X86_GRP_DFL_NONE)) {
|
|
Packit |
577717 |
skip = 1;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
grpid = ent->umasks[idx].grpid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (excl_grp_but_0 != -1 && grpid != 0 && excl_grp_but_0 != grpid) {
|
|
Packit |
577717 |
skip = 1;
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* umask is default for group */
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, idx, INTEL_X86_DFL)) {
|
|
Packit |
577717 |
DPRINT("added default %s for group %d j=%d idx=%d ucode=0x%"PRIx64"\n",
|
|
Packit |
577717 |
ent->umasks[idx].uname,
|
|
Packit |
577717 |
i,
|
|
Packit |
577717 |
j,
|
|
Packit |
577717 |
idx,
|
|
Packit |
577717 |
ent->umasks[idx].ucode);
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* default could be an alias, but
|
|
Packit |
577717 |
* ucode must reflect actual code
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
*umask |= ent->umasks[idx].ucode >> 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->attrs[k].id = j; /* pattrs index */
|
|
Packit |
577717 |
e->attrs[k].ival = 0;
|
|
Packit |
577717 |
k++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
added++;
|
|
Packit |
577717 |
if (intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL))
|
|
Packit |
577717 |
goto done;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, idx, INTEL_X86_EXCL_GRP_GT)) {
|
|
Packit |
577717 |
if (max_grpid != INTEL_X86_MAX_GRPID) {
|
|
Packit |
577717 |
DPRINT("two max_grpid, old=%d new=%d\n", max_grpid, ent->umasks[idx].grpid);
|
|
Packit |
577717 |
return PFM_ERR_UMASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
max_grpid = ent->umasks[idx].grpid;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!added && !skip) {
|
|
Packit |
577717 |
DPRINT("no default found for event %s unit mask group %d (max_grpid=%d)\n", ent->name, i, max_grpid);
|
|
Packit |
577717 |
return PFM_ERR_UMASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
DPRINT("max_grpid=%d nattrs=%d k=%d umask=0x%"PRIx64"\n", max_grpid, e->nattrs, k, *umask);
|
|
Packit |
577717 |
done:
|
|
Packit |
577717 |
e->nattrs = k;
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
intel_x86_check_pebs(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
int numasks = 0, pebs = 0;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if 1
|
|
Packit |
577717 |
if (1) // !intel_x86_requesting_pebs(e))
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if event has no umask and is PEBS, then we are okay
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!pe[e->event].numasks
|
|
Packit |
577717 |
&& intel_x86_eflag(this, e->event, INTEL_X86_PEBS))
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if the event sets PEBS, then it measn at least one umask
|
|
Packit |
577717 |
* supports PEBS, so we need to check
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = 0; i < e->nattrs; i++) {
|
|
Packit |
577717 |
a = attr(e, i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->type == PFM_ATTR_UMASK) {
|
|
Packit |
577717 |
/* count number of umasks */
|
|
Packit |
577717 |
numasks++;
|
|
Packit |
577717 |
/* and those that support PEBS */
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_PEBS))
|
|
Packit |
577717 |
pebs++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pass if user requested only PEBS umasks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
return pebs != numasks ? PFM_ERR_FEATCOMB : PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
intel_x86_check_max_grpid(void *this, pfmlib_event_desc_t *e, unsigned short max_grpid)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
unsigned short grpid;
|
|
Packit |
577717 |
int i;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
DPRINT("check: max_grpid=%d\n", max_grpid);
|
|
Packit |
577717 |
pe = this_pe(this);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i = 0; i < e->nattrs; i++) {
|
|
Packit |
577717 |
a = attr(e, i);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->type == PFM_ATTR_UMASK) {
|
|
Packit |
577717 |
grpid = pe[e->event].umasks[a->idx].grpid;
|
|
Packit |
577717 |
if (grpid > max_grpid)
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
pfm_intel_x86_encode_gen(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
const intel_x86_entry_t *pe;
|
|
Packit |
577717 |
pfm_intel_x86_reg_t reg, reg2;
|
|
Packit |
577717 |
unsigned int grpmsk, ugrpmsk = 0;
|
|
Packit |
577717 |
uint64_t umask1, umask2, ucode, last_ucode = ~0ULL;
|
|
Packit |
577717 |
unsigned int modhw = 0;
|
|
Packit |
577717 |
unsigned int plmmsk = 0;
|
|
Packit |
577717 |
int umodmsk = 0, modmsk_r = 0;
|
|
Packit |
577717 |
int k, ret, id;
|
|
Packit |
577717 |
unsigned short max_grpid = INTEL_X86_MAX_GRPID;
|
|
Packit |
577717 |
unsigned short last_grpid = INTEL_X86_MAX_GRPID;
|
|
Packit |
577717 |
unsigned short grpid;
|
|
Packit |
577717 |
int ldlat = 0, ldlat_um = 0;
|
|
Packit |
577717 |
int fe_thr= 0, fe_thr_um = 0;
|
|
Packit |
577717 |
int excl_grp_but_0 = -1;
|
|
Packit |
577717 |
int grpcounts[INTEL_X86_NUM_GRP];
|
|
Packit |
577717 |
int ncombo[INTEL_X86_NUM_GRP];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(grpcounts, 0, sizeof(grpcounts));
|
|
Packit |
577717 |
memset(ncombo, 0, sizeof(ncombo));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pe = this_pe(this);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->fstr[0] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* preset certain fields from event code
|
|
Packit |
577717 |
* including modifiers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
reg.val = pe[e->event].code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
grpmsk = (1 << pe[e->event].ngrp)-1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* take into account hardcoded umask */
|
|
Packit |
577717 |
umask1 = (reg.val >> 8) & 0xff;
|
|
Packit |
577717 |
umask2 = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
modmsk_r = pe[e->event].modmsk_req;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (k = 0; k < e->nattrs; k++) {
|
|
Packit |
577717 |
a = attr(e, k);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->type == PFM_ATTR_UMASK) {
|
|
Packit |
577717 |
grpid = pe[e->event].umasks[a->idx].grpid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* certain event groups are meant to be
|
|
Packit |
577717 |
* exclusive, i.e., only unit masks of one group
|
|
Packit |
577717 |
* can be used
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (last_grpid != INTEL_X86_MAX_GRPID && grpid != last_grpid
|
|
Packit |
577717 |
&& intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL)) {
|
|
Packit |
577717 |
DPRINT("exclusive unit mask group error\n");
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* selecting certain umasks in a group may exclude any umasks
|
|
Packit |
577717 |
* from any groups with a higher index
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* enforcement requires looking at the grpid of all the umasks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_EXCL_GRP_GT))
|
|
Packit |
577717 |
max_grpid = grpid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_EXCL_GRP_BUT_0))
|
|
Packit |
577717 |
excl_grp_but_0 = grpid;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* upper layer has removed duplicates
|
|
Packit |
577717 |
* so if we come here more than once, it is for two
|
|
Packit |
577717 |
* disinct umasks
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* NCOMBO=no combination of unit masks within the same
|
|
Packit |
577717 |
* umask group
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
++grpcounts[grpid];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* mark that we have a umask with NCOMBO in this group */
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_NCOMBO))
|
|
Packit |
577717 |
ncombo[grpid] = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_LDLAT))
|
|
Packit |
577717 |
ldlat_um = 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_FETHR))
|
|
Packit |
577717 |
fe_thr_um = 1;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* if more than one umask in this group but one is marked
|
|
Packit |
577717 |
* with ncombo, then fail. It is okay to combine umask within
|
|
Packit |
577717 |
* a group as long as none is tagged with NCOMBO
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (grpcounts[grpid] > 1 && ncombo[grpid]) {
|
|
Packit |
577717 |
DPRINT("umask %s does not support unit mask combination within group %d\n", pe[e->event].umasks[a->idx].uname, grpid);
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
last_grpid = grpid;
|
|
Packit |
577717 |
ucode = pe[e->event].umasks[a->idx].ucode;
|
|
Packit |
577717 |
modhw |= pe[e->event].umasks[a->idx].modhw;
|
|
Packit |
577717 |
umask2 |= ucode >> 8;
|
|
Packit |
577717 |
ugrpmsk |= 1 << pe[e->event].umasks[a->idx].grpid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
modmsk_r |= pe[e->event].umasks[a->idx].umodmsk_req;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_CODE_OVERRIDE)) {
|
|
Packit |
577717 |
if (last_ucode != ~0ULL && (ucode & 0xff) != last_ucode) {
|
|
Packit |
577717 |
DPRINT("cannot override event with two different codes for %s\n", pe[e->event].name);
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
last_ucode = ucode & 0xff;
|
|
Packit |
577717 |
reg.sel_event_select = last_ucode;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (a->type == PFM_ATTR_RAW_UMASK) {
|
|
Packit |
577717 |
int ofr_bits = 8;
|
|
Packit |
577717 |
uint64_t rmask;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* set limit on width of raw umask */
|
|
Packit |
577717 |
if (intel_x86_eflag(this, e->event, INTEL_X86_NHM_OFFCORE)) {
|
|
Packit |
577717 |
ofr_bits = 38;
|
|
Packit |
577717 |
if (e->pmu->pmu == PFM_PMU_INTEL_WSM || e->pmu->pmu == PFM_PMU_INTEL_WSM_DP)
|
|
Packit |
577717 |
ofr_bits = 16;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
rmask = (1ULL << ofr_bits) - 1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (a->idx & ~rmask) {
|
|
Packit |
577717 |
DPRINT("raw umask is too wide max %d bits\n", ofr_bits);
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* override umask */
|
|
Packit |
577717 |
umask2 = a->idx & rmask;
|
|
Packit |
577717 |
ugrpmsk = grpmsk;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
uint64_t ival = e->attrs[k].ival;
|
|
Packit |
577717 |
switch(a->idx) {
|
|
Packit |
577717 |
case INTEL_X86_ATTR_I: /* invert */
|
|
Packit |
577717 |
reg.sel_inv = !!ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_I;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_E: /* edge */
|
|
Packit |
577717 |
reg.sel_edge = !!ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_E;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_C: /* counter-mask */
|
|
Packit |
577717 |
if (ival > 255)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
reg.sel_cnt_mask = ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_C;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_U: /* USR */
|
|
Packit |
577717 |
reg.sel_usr = !!ival;
|
|
Packit |
577717 |
plmmsk |= _INTEL_X86_ATTR_U;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_U;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_K: /* OS */
|
|
Packit |
577717 |
reg.sel_os = !!ival;
|
|
Packit |
577717 |
plmmsk |= _INTEL_X86_ATTR_K;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_K;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_T: /* anythread (v3 and above) */
|
|
Packit |
577717 |
reg.sel_anythr = !!ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_T;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_LDLAT: /* load latency */
|
|
Packit |
577717 |
if (ival < 3 || ival > 65535)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
ldlat = ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_INTX: /* in_tx */
|
|
Packit |
577717 |
reg.sel_intx = !!ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_INTX;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_INTXCP: /* in_tx_cp */
|
|
Packit |
577717 |
reg.sel_intxcp = !!ival;
|
|
Packit |
577717 |
umodmsk |= _INTEL_X86_ATTR_INTXCP;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_FETHR: /* precise frontend latency threshold */
|
|
Packit |
577717 |
if (ival < 1 || ival > 4095)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
fe_thr = ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* we need to wait until all the attributes have been parsed to check
|
|
Packit |
577717 |
* for conflicts between hardcoded attributes and user-provided attributes.
|
|
Packit |
577717 |
* we do not want to depend on the order in which they are specified
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The test check for conflicts. It is okay to specify an attribute if
|
|
Packit |
577717 |
* it encodes to the same same value as the hardcoded value. That allows
|
|
Packit |
577717 |
* use to prase a FQESTR (fully-qualified event string) as returned by
|
|
Packit |
577717 |
* the library
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
reg2.val = (umask1 | umask2) << 8;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_I) && reg2.sel_inv != reg.sel_inv)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_E) && reg2.sel_edge != reg.sel_edge)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_C) && reg2.sel_cnt_mask != reg.sel_cnt_mask)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_U) && reg2.sel_usr != reg.sel_usr)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_K) && reg2.sel_os != reg.sel_os)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_T) && reg2.sel_anythr != reg.sel_anythr)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_INTX) && reg2.sel_intx != reg.sel_intx)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
if (mdhw(modhw, umodmsk, ATTR_INTXCP) && reg2.sel_intxcp != reg.sel_intxcp)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_SET;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* handle case where no priv level mask was passed.
|
|
Packit |
577717 |
* then we use the dfl_plm
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!(plmmsk & (_INTEL_X86_ATTR_K|_INTEL_X86_ATTR_U))) {
|
|
Packit |
577717 |
if ((e->dfl_plm & PFM_PLM0) && (pmu->supported_plm & PFM_PLM0))
|
|
Packit |
577717 |
reg.sel_os = 1;
|
|
Packit |
577717 |
if ((e->dfl_plm & PFM_PLM3) && (pmu->supported_plm & PFM_PLM3))
|
|
Packit |
577717 |
reg.sel_usr = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check that there is at least of unit mask in each unit
|
|
Packit |
577717 |
* mask group
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((ugrpmsk != grpmsk && !intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL)) || ugrpmsk == 0) {
|
|
Packit |
577717 |
ugrpmsk ^= grpmsk;
|
|
Packit |
577717 |
ret = pfm_intel_x86_add_defaults(this, e, ugrpmsk, &umask2, max_grpid, excl_grp_but_0);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* GRP_EXCL_BUT_0 groups require at least one bit set in grpid = 0 and one in theirs
|
|
Packit |
577717 |
* applies to OFFCORE_RESPONSE umasks on some processors (e.g., Goldmont)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
DPRINT("excl_grp_but_0=%d\n", excl_grp_but_0);
|
|
Packit |
577717 |
if (excl_grp_but_0 != -1) {
|
|
Packit |
577717 |
/* skip group 0, because it is authorized */
|
|
Packit |
577717 |
for (k = 1; k < INTEL_X86_NUM_GRP; k++) {
|
|
Packit |
577717 |
DPRINT("grpcounts[%d]=%d\n", k, grpcounts[k]);
|
|
Packit |
577717 |
if (grpcounts[k] && k != excl_grp_but_0) {
|
|
Packit |
577717 |
DPRINT("GRP_EXCL_BUT_0 but grpcounts[%d]=%d\n", k, grpcounts[k]);
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
ret = intel_x86_check_pebs(this, e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check no umask violates the max_grpid constraint
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (max_grpid != INTEL_X86_MAX_GRPID) {
|
|
Packit |
577717 |
ret = intel_x86_check_max_grpid(this, e, max_grpid);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS) {
|
|
Packit |
577717 |
DPRINT("event %s: umask from grp > %d\n", pe[e->event].name, max_grpid);
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (modmsk_r && (umodmsk ^ modmsk_r)) {
|
|
Packit |
577717 |
DPRINT("required modifiers missing: 0x%x\n", modmsk_r);
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* reorder all the attributes such that the fstr appears always
|
|
Packit |
577717 |
* the same regardless of how the attributes were submitted.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
evt_strcat(e->fstr, "%s", pe[e->event].name);
|
|
Packit |
577717 |
pfmlib_sort_attr(e);
|
|
Packit |
577717 |
for(k=0; k < e->nattrs; k++) {
|
|
Packit |
577717 |
a = attr(e, k);
|
|
Packit |
577717 |
if (a->ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (a->type == PFM_ATTR_UMASK)
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s", pe[e->event].umasks[a->idx].uname);
|
|
Packit |
577717 |
else if (a->type == PFM_ATTR_RAW_UMASK)
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":0x%x", a->idx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (fe_thr_um && !fe_thr) {
|
|
Packit |
577717 |
/* try extracting te latency threshold from the event umask first */
|
|
Packit |
577717 |
fe_thr = (umask2 >> 8) & 0x7;
|
|
Packit |
577717 |
/* if not in the umask ,then use default */
|
|
Packit |
577717 |
if (!fe_thr) {
|
|
Packit |
577717 |
DPRINT("missing fe_thres= for umask, forcing to default %d cycles\n", INTEL_X86_FETHR_DEFAULT);
|
|
Packit |
577717 |
fe_thr = INTEL_X86_FETHR_DEFAULT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* encode threshold in final position in extra register
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (fe_thr && fe_thr_um) {
|
|
Packit |
577717 |
umask2 |= fe_thr << 8;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* offcore_response or precise frontend require a separate register
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (intel_x86_eflag(this, e->event, INTEL_X86_NHM_OFFCORE)
|
|
Packit |
577717 |
|| intel_x86_eflag(this, e->event, INTEL_X86_FRONTEND)) {
|
|
Packit |
577717 |
e->codes[1] = umask2;
|
|
Packit |
577717 |
e->count = 2;
|
|
Packit |
577717 |
umask2 = 0;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
e->count = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ldlat && !ldlat_um) {
|
|
Packit |
577717 |
DPRINT("passed ldlat= but not using ldlat umask\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* force a default ldlat (will not appear in display_reg)
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (ldlat_um && !ldlat) {
|
|
Packit |
577717 |
DPRINT("missing ldlat= for umask, forcing to default %d cycles\n", INTEL_X86_LDLAT_DEFAULT);
|
|
Packit |
577717 |
ldlat = INTEL_X86_LDLAT_DEFAULT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (ldlat && ldlat_um) {
|
|
Packit |
577717 |
e->codes[1] = ldlat;
|
|
Packit |
577717 |
e->count = 2;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* take into account hardcoded modifiers, so use or on reg.val */
|
|
Packit |
577717 |
reg.val |= (umask1 | umask2) << 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.sel_en = 1; /* force enable bit to 1 */
|
|
Packit |
577717 |
reg.sel_int = 1; /* force APIC int to 1 */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->codes[0] = reg.val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* on recent processors (except Atom), edge requires cmask >=1
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if ((pmu->flags & INTEL_X86_PMU_FL_ECMASK)
|
|
Packit |
577717 |
&& reg.sel_edge && !reg.sel_cnt_mask) {
|
|
Packit |
577717 |
DPRINT("edge requires cmask >= 1\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* decode ALL modifiers
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (k = 0; k < e->npattrs; k++) {
|
|
Packit |
577717 |
if (e->pattrs[k].ctrl != PFM_ATTR_CTRL_PMU)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (e->pattrs[k].type == PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
id = e->pattrs[k].idx;
|
|
Packit |
577717 |
switch(id) {
|
|
Packit |
577717 |
case INTEL_X86_ATTR_U:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_usr);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_K:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_os);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_E:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_edge);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_I:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_inv);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_C:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_cnt_mask);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_T:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_anythr);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_LDLAT:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%d", intel_x86_mods[id].name, ldlat);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_INTX:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_intx);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_INTXCP:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, reg.sel_intxcp);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case INTEL_X86_ATTR_FETHR:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", intel_x86_mods[id].name, fe_thr);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_get_encoding(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_encode_gen(this, e);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfm_intel_x86_display_reg(this, e);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_get_event_first(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *p = this;
|
|
Packit |
577717 |
int idx = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* skip event for different models */
|
|
Packit |
577717 |
while (idx < p->pme_count && !is_model_event(this, idx)) idx++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return idx < p->pme_count ? idx : -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_get_event_next(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *p = this;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* pme_count is always >= 1*/
|
|
Packit |
577717 |
if (idx >= (p->pme_count-1))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
idx++;
|
|
Packit |
577717 |
/* skip event for different models */
|
|
Packit |
577717 |
while (idx < p->pme_count && !is_model_event(this, idx)) idx++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return idx < p->pme_count ? idx : -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_event_is_valid(void *this, int pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *p = this;
|
|
Packit |
577717 |
return pidx >= 0 && pidx < p->pme_count && is_model_event(this, pidx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_validate_table(void *this, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
int ndfl[INTEL_X86_NUM_GRP];
|
|
Packit |
577717 |
int i, j, error = 0;
|
|
Packit |
577717 |
unsigned int u, v;
|
|
Packit |
577717 |
int npebs;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->atdesc) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s missing attr_desc\n", pmu->name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pmu->supported_plm && pmu->type == PFM_PMU_TYPE_CORE) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s supported_plm not set\n", pmu->name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(i=0; i < pmu->pme_count; i++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!is_model_event(this, i))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pe[i].name) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: :: no name (prev event was %s)\n", pmu->name, i,
|
|
Packit |
577717 |
i > 1 ? pe[i-1].name : "??");
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pe[i].desc) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: no description\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pe[i].cntmsk) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: cntmsk=0\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks && pe[i].ngrp == 0) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: ngrp cannot be zero\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks && pe[i].umasks == NULL) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: numasks but no umasks\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks == 0 && pe[i].umasks) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: numasks=0 but umasks defined\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks == 0 && pe[i].ngrp) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: ngrp must be zero\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].ngrp >= INTEL_X86_NUM_GRP) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: ngrp too big (max=%d)\n", pmu->name, i, pe[i].name, INTEL_X86_NUM_GRP);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (pe[i].model >= PFM_PMU_MAX) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: model too big (max=%d)\n", pmu->name, i, pe[i].name, PFM_PMU_MAX);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (j=i+1; j < (int)pmu->pme_count; j++) {
|
|
Packit |
577717 |
if (pe[i].code == pe[j].code && !(pe[j].equiv || pe[i].equiv) && pe[j].cntmsk == pe[i].cntmsk) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s events %s and %s have the same code 0x%x\n", pmu->name, pe[i].name, pe[j].name, pe[i].code);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=0; j < INTEL_X86_NUM_GRP; j++)
|
|
Packit |
577717 |
ndfl[j] = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=0, npebs = 0; j < (int)pe[i].numasks; j++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pe[i].umasks[j].uname) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s umask%d :: no name\n", pmu->name, i, pe[i].name, j);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (pe[i].umasks[j].modhw && (pe[i].umasks[j].modhw | pe[i].modmsk) != pe[i].modmsk) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s umask%d: %s :: modhw not subset of modmsk\n", pmu->name, i, pe[i].name, j, pe[i].umasks[j].uname);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!pe[i].umasks[j].udesc) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: umask%d: %s :: no description\n", pmu->name, i, j, pe[i].umasks[j].uname);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].ngrp && pe[i].umasks[j].grpid >= pe[i].ngrp) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s umask%d: %s :: invalid grpid %d (must be < %d)\n", pmu->name, i, pe[i].name, j, pe[i].umasks[j].uname, pe[i].umasks[j].grpid, pe[i].ngrp);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (pe[i].umasks[j].umodel >= PFM_PMU_MAX) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s umask%d: %s :: model too big (max=%d)\n", pmu->name, i, pe[i].name, j, pe[i].umasks[j].uname, PFM_PMU_MAX);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (pe[i].umasks[j].uflags & INTEL_X86_DFL)
|
|
Packit |
577717 |
ndfl[pe[i].umasks[j].grpid]++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].umasks[j].uflags & INTEL_X86_PEBS)
|
|
Packit |
577717 |
npebs++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (npebs && !intel_x86_eflag(this, i, INTEL_X86_PEBS)) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s, pebs umasks but event pebs flag not set\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_eflag(this, i, INTEL_X86_PEBS) && pe[i].numasks && npebs == 0) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s, pebs event flag but not umask has pebs flag\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* if only one umask, then ought to be default */
|
|
Packit |
577717 |
if (pe[i].numasks == 1 && !(pe[i].umasks[0].uflags & INTEL_X86_DFL)) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s, only one umask but no default\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks) {
|
|
Packit |
577717 |
unsigned int *dfl_model = malloc(sizeof(*dfl_model) * pe[i].numasks);
|
|
Packit |
577717 |
if (!dfl_model)
|
|
Packit |
577717 |
goto skip_dfl;
|
|
Packit |
577717 |
for(u=0; u < pe[i].ngrp; u++) {
|
|
Packit |
577717 |
int l = 0, m;
|
|
Packit |
577717 |
for (v = 0; v < pe[i].numasks; v++) {
|
|
Packit |
577717 |
if (pe[i].umasks[v].grpid != u)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (pe[i].umasks[v].uflags & INTEL_X86_DFL) {
|
|
Packit |
577717 |
for (m = 0; m < l; m++) {
|
|
Packit |
577717 |
if (dfl_model[m] == pe[i].umasks[v].umodel || dfl_model[m] == 0) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s grpid %d has 2 default umasks\n", pmu->name, i, pe[i].name, u);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (m == l)
|
|
Packit |
577717 |
dfl_model[l++] = pe[i].umasks[v].umodel;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
free(dfl_model);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
skip_dfl:
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].flags & INTEL_X86_NCOMBO) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: NCOMBO is unit mask only flag\n", pmu->name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(u=0; u < pe[i].numasks; u++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].umasks[u].uequiv)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].umasks[u].uflags & INTEL_X86_NCOMBO)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(v=j+1; v < pe[i].numasks; v++) {
|
|
Packit |
577717 |
if (pe[i].umasks[v].uequiv)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (pe[i].umasks[v].uflags & INTEL_X86_NCOMBO)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (pe[i].umasks[v].grpid != pe[i].umasks[u].grpid)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if ((pe[i].umasks[u].ucode & pe[i].umasks[v].ucode) && pe[i].umasks[u].umodel == pe[i].umasks[v].umodel) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: umask %s and %s have overlapping code bits\n", pmu->name, i, pe[i].name, pe[i].umasks[u].uname, pe[i].umasks[v].uname);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return error ? PFM_ERR_INVAL : PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_get_event_attr_info(void *this, int pidx, int attr_idx, pfmlib_event_attr_info_t *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
const pfmlib_attr_desc_t *atdesc = this_atdesc(this);
|
|
Packit |
577717 |
int numasks, idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!is_model_event(this, pidx)) {
|
|
Packit |
577717 |
DPRINT("invalid event index %d\n", pidx);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
numasks = intel_x86_num_umasks(this, pidx);
|
|
Packit |
577717 |
if (attr_idx < numasks) {
|
|
Packit |
577717 |
idx = intel_x86_attr2umask(this, pidx, attr_idx);
|
|
Packit |
577717 |
info->name = pe[pidx].umasks[idx].uname;
|
|
Packit |
577717 |
info->desc = pe[pidx].umasks[idx].udesc;
|
|
Packit |
577717 |
info->equiv= pe[pidx].umasks[idx].uequiv;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->code = pe[pidx].umasks[idx].ucode;
|
|
Packit |
577717 |
if (!intel_x86_uflag(this, pidx, idx, INTEL_X86_CODE_OVERRIDE))
|
|
Packit |
577717 |
info->code >>= 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->type = PFM_ATTR_UMASK;
|
|
Packit |
577717 |
info->is_dfl = intel_x86_uflag(this, pidx, idx, INTEL_X86_DFL);
|
|
Packit |
577717 |
info->is_precise = intel_x86_uflag(this, pidx, idx, INTEL_X86_PEBS);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
idx = intel_x86_attr2mod(this, pidx, attr_idx);
|
|
Packit |
577717 |
info->name = atdesc[idx].name;
|
|
Packit |
577717 |
info->desc = atdesc[idx].desc;
|
|
Packit |
577717 |
info->type = atdesc[idx].type;
|
|
Packit |
577717 |
info->equiv= NULL;
|
|
Packit |
577717 |
info->code = idx;
|
|
Packit |
577717 |
info->is_dfl = 0;
|
|
Packit |
577717 |
info->is_precise = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->ctrl = PFM_ATTR_CTRL_PMU;
|
|
Packit |
577717 |
info->idx = idx; /* namespace specific index */
|
|
Packit |
577717 |
info->dfl_val64 = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_get_event_info(void *this, int idx, pfm_event_info_t *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (!is_model_event(this, idx)) {
|
|
Packit |
577717 |
DPRINT("invalid event index %d\n", idx);
|
|
Packit |
577717 |
return PFM_ERR_INVAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->name = pe[idx].name;
|
|
Packit |
577717 |
info->desc = pe[idx].desc;
|
|
Packit |
577717 |
info->code = pe[idx].code;
|
|
Packit |
577717 |
info->equiv = pe[idx].equiv;
|
|
Packit |
577717 |
info->idx = idx; /* private index */
|
|
Packit |
577717 |
info->pmu = pmu->pmu;
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* no umask: event supports PEBS
|
|
Packit |
577717 |
* with umasks: at least one umask supports PEBS
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
info->is_precise = intel_x86_eflag(this, idx, INTEL_X86_PEBS);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->nattrs = intel_x86_num_umasks(this, idx);
|
|
Packit |
577717 |
info->nattrs += intel_x86_num_mods(this, idx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_valid_pebs(pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
int i, npebs = 0, numasks = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* first check at the event level */
|
|
Packit |
577717 |
if (intel_x86_eflag(e->pmu, e->event, INTEL_X86_PEBS))
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* next check the umasks
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* we do not assume we are calling after
|
|
Packit |
577717 |
* pfm_intel_x86_ge_event_encoding(), therefore
|
|
Packit |
577717 |
* we check the unit masks again.
|
|
Packit |
577717 |
* They must all be PEBS-capable.
|
|
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_PMU || a->type != PFM_ATTR_UMASK)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
numasks++;
|
|
Packit |
577717 |
if (intel_x86_uflag(e->pmu, e->event, a->idx, INTEL_X86_PEBS))
|
|
Packit |
577717 |
npebs++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return npebs == numasks ? PFM_SUCCESS : PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
unsigned int
|
|
Packit |
577717 |
pfm_intel_x86_get_event_nattrs(void *this, int pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int nattrs;
|
|
Packit |
577717 |
nattrs = intel_x86_num_umasks(this, pidx);
|
|
Packit |
577717 |
nattrs += intel_x86_num_mods(this, pidx);
|
|
Packit |
577717 |
return nattrs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_x86_can_auto_encode(void *this, int pidx, int uidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int numasks;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (intel_x86_eflag(this, pidx, INTEL_X86_NO_AUTOENCODE))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
numasks = intel_x86_num_umasks(this, pidx);
|
|
Packit |
577717 |
if (uidx >= numasks)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return !intel_x86_uflag(this, pidx, uidx, INTEL_X86_NO_AUTOENCODE);
|
|
Packit |
577717 |
}
|