|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_intel_snbep_unc.c : Intel SandyBridge-EP uncore PMU common code
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2012 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 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <ctype.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
#include <stdio.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h"
|
|
Packit |
577717 |
#include "pfmlib_intel_x86_priv.h"
|
|
Packit |
577717 |
#include "pfmlib_intel_snbep_unc_priv.h"
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const pfmlib_attr_desc_t snbep_unc_mods[]={
|
|
Packit |
577717 |
PFM_ATTR_B("e", "edge detect"), /* edge */
|
|
Packit |
577717 |
PFM_ATTR_B("i", "invert"), /* invert */
|
|
Packit |
577717 |
PFM_ATTR_I("t", "threshold in range [0-255]"), /* threshold */
|
|
Packit |
577717 |
PFM_ATTR_I("t", "threshold in range [0-31]"), /* threshold */
|
|
Packit |
577717 |
PFM_ATTR_I("tf", "thread id filter [0-1]"), /* thread id */
|
|
Packit |
577717 |
PFM_ATTR_I("cf", "core id filter, includes non-thread data in bit 4 [0-15]"), /* core id (ivbep) */
|
|
Packit |
577717 |
PFM_ATTR_I("nf", "node id bitmask filter [0-255]"),/* nodeid mask filter0 */
|
|
Packit |
577717 |
PFM_ATTR_I("ff", "frequency >= 100Mhz * [0-255]"),/* freq filter */
|
|
Packit |
577717 |
PFM_ATTR_I("addr", "physical address matcher [40 bits]"),/* address matcher */
|
|
Packit |
577717 |
PFM_ATTR_I("nf", "node id bitmask filter [0-255]"),/* nodeid mask filter1 */
|
|
Packit |
577717 |
PFM_ATTR_B("isoc", "match isochronous requests"), /* isochronous */
|
|
Packit |
577717 |
PFM_ATTR_B("nc", "match non-coherent requests"), /* non-coherent */
|
|
Packit |
577717 |
PFM_ATTR_I("cf", "core id filter, includes non-thread data in bit 5 [0-63]"), /* core id (hswep) */
|
|
Packit |
577717 |
PFM_ATTR_NULL
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_snbep_unc_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != 6)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(pfm_intel_x86_cfg.model) {
|
|
Packit |
577717 |
case 45: /* SandyBridge-EP */
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_ivbep_unc_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != 6)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(pfm_intel_x86_cfg.model) {
|
|
Packit |
577717 |
case 62: /* SandyBridge-EP */
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_hswep_unc_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != 6)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(pfm_intel_x86_cfg.model) {
|
|
Packit |
577717 |
case 63: /* Haswell-EP */
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_knl_unc_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != 6)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(pfm_intel_x86_cfg.model) {
|
|
Packit |
577717 |
case 87: /* Knights Landing */
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_bdx_unc_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_intel_x86_detect();
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_intel_x86_cfg.family != 6)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(pfm_intel_x86_cfg.model) {
|
|
Packit |
577717 |
case 79: /* Broadwell X */
|
|
Packit |
577717 |
case 86: /* Broadwell X */
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
display_com(void *this, pfmlib_event_desc_t *e, void *val)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfm_snbep_unc_reg_t *reg = val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
__pfm_vbprintf("[UNC=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
|
|
Packit |
577717 |
"inv=%d edge=%d thres=%d] %s\n",
|
|
Packit |
577717 |
reg->val,
|
|
Packit |
577717 |
reg->com.unc_event,
|
|
Packit |
577717 |
reg->com.unc_umask,
|
|
Packit |
577717 |
reg->com.unc_en,
|
|
Packit |
577717 |
reg->com.unc_inv,
|
|
Packit |
577717 |
reg->com.unc_edge,
|
|
Packit |
577717 |
reg->com.unc_thres,
|
|
Packit |
577717 |
pe[e->event].name);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
display_reg(void *this, pfmlib_event_desc_t *e, pfm_snbep_unc_reg_t reg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
if (pmu->display_reg)
|
|
Packit |
577717 |
pmu->display_reg(this, e, ®);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
display_com(this, e, ®);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
is_occ_event(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return (pmu->flags & INTEL_PMU_FL_UNC_OCC) && (pe[idx].code & 0x80);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
get_pcu_filt_band(void *this, pfm_snbep_unc_reg_t reg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
#define PCU_FREQ_BAND0_CODE 0xb /* event code for UNC_P_FREQ_BAND0_CYCLES */
|
|
Packit |
577717 |
return reg.pcu.unc_event - PCU_FREQ_BAND0_CODE;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
snbep_unc_add_defaults(void *this, pfmlib_event_desc_t *e,
|
|
Packit |
577717 |
unsigned int msk,
|
|
Packit |
577717 |
uint64_t *umask,
|
|
Packit |
577717 |
pfm_snbep_unc_reg_t *filters,
|
|
Packit |
577717 |
unsigned short max_grpid)
|
|
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 |
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 |
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 |
|
|
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 |
filters[0].val |= pe[e->event].umasks[idx].ufilters[0];
|
|
Packit |
577717 |
filters[1].val |= pe[e->event].umasks[idx].ufilters[1];
|
|
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, i=%d)\n", ent->name, i, max_grpid, i);
|
|
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 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* common encoding routine
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_snbep_unc_get_encoding(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const intel_x86_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
unsigned int grpmsk, ugrpmsk = 0;
|
|
Packit |
577717 |
unsigned short max_grpid = INTEL_X86_MAX_GRPID;
|
|
Packit |
577717 |
unsigned short last_grpid = INTEL_X86_MAX_GRPID;
|
|
Packit |
577717 |
int umodmsk = 0, modmsk_r = 0;
|
|
Packit |
577717 |
int pcu_filt_band = -1;
|
|
Packit |
577717 |
pfm_snbep_unc_reg_t reg;
|
|
Packit |
577717 |
pfm_snbep_unc_reg_t filters[INTEL_X86_MAX_FILTERS];
|
|
Packit |
577717 |
pfm_snbep_unc_reg_t addr;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
uint64_t val, umask1, umask2;
|
|
Packit |
577717 |
int k, ret;
|
|
Packit |
577717 |
int has_cbo_tid = 0;
|
|
Packit |
577717 |
unsigned short grpid;
|
|
Packit |
577717 |
int grpcounts[INTEL_X86_NUM_GRP];
|
|
Packit |
577717 |
int ncombo[INTEL_X86_NUM_GRP];
|
|
Packit |
577717 |
char umask_str[PFMLIB_EVT_MAX_NAME_LEN];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(grpcounts, 0, sizeof(grpcounts));
|
|
Packit |
577717 |
memset(ncombo, 0, sizeof(ncombo));
|
|
Packit |
577717 |
memset(filters, 0, sizeof(filters));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
addr.val = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pe = this_pe(this);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask_str[0] = e->fstr[0] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.val = val = pe[e->event].code;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* take into account hardcoded umask */
|
|
Packit |
577717 |
umask1 = (val >> 8) & 0xff;
|
|
Packit |
577717 |
umask2 = umask1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
grpmsk = (1 << pe[e->event].ngrp)-1;
|
|
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 |
uint64_t um;
|
|
Packit |
577717 |
|
|
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 |
/*
|
|
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 |
/*
|
|
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 |
* 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 |
/*
|
|
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 |
|
|
Packit |
577717 |
um = pe[e->event].umasks[a->idx].ucode;
|
|
Packit |
577717 |
filters[0].val |= pe[e->event].umasks[a->idx].ufilters[0];
|
|
Packit |
577717 |
filters[1].val |= pe[e->event].umasks[a->idx].ufilters[1];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
um >>= 8;
|
|
Packit |
577717 |
umask2 |= um;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ugrpmsk |= 1 << pe[e->event].umasks[a->idx].grpid;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* PCU occ event */
|
|
Packit |
577717 |
if (is_occ_event(this, e->event)) {
|
|
Packit |
577717 |
reg.pcu.unc_occ = umask2 >> 6;
|
|
Packit |
577717 |
umask2 = 0;
|
|
Packit |
577717 |
} else
|
|
Packit |
577717 |
reg.val |= umask2 << 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
evt_strcat(umask_str, ":%s", pe[e->event].umasks[a->idx].uname);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
modmsk_r |= pe[e->event].umasks[a->idx].umodmsk_req;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
} else if (a->type == PFM_ATTR_RAW_UMASK) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* there can only be one RAW_UMASK per event */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* sanity check */
|
|
Packit |
577717 |
if (a->idx & ~0xff) {
|
|
Packit |
577717 |
DPRINT("raw umask is 8-bit wide\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* override umask */
|
|
Packit |
577717 |
umask2 = a->idx & 0xff;
|
|
Packit |
577717 |
ugrpmsk = grpmsk;
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
uint64_t ival = e->attrs[k].ival;
|
|
Packit |
577717 |
switch(a->idx) {
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_I: /* invert */
|
|
Packit |
577717 |
if (is_occ_event(this, e->event))
|
|
Packit |
577717 |
reg.pcu.unc_occ_inv = !!ival;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
reg.com.unc_inv = !!ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_I;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_E: /* edge */
|
|
Packit |
577717 |
if (is_occ_event(this, e->event))
|
|
Packit |
577717 |
reg.pcu.unc_occ_edge = !!ival;
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
reg.com.unc_edge = !!ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_E;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_T8: /* counter-mask */
|
|
Packit |
577717 |
/* already forced, cannot overwrite */
|
|
Packit |
577717 |
if (ival > 255)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
reg.com.unc_thres = ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_T8;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_T5: /* pcu counter-mask */
|
|
Packit |
577717 |
/* already forced, cannot overwrite */
|
|
Packit |
577717 |
if (ival > 31)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
reg.pcu.unc_thres = ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_T5;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_TF: /* thread id */
|
|
Packit |
577717 |
if (ival > 1) {
|
|
Packit |
577717 |
DPRINT("invalid thread id, must be < 1");
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
reg.cbo.unc_tid = 1;
|
|
Packit |
577717 |
has_cbo_tid = 1;
|
|
Packit |
577717 |
filters[0].cbo_filt.tid = ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_TF;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_CF: /* core id */
|
|
Packit |
577717 |
if (ival > 15)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
reg.cbo.unc_tid = 1;
|
|
Packit |
577717 |
filters[0].cbo_filt.cid = ival;
|
|
Packit |
577717 |
has_cbo_tid = 1;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_CF;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_CF1: /* core id */
|
|
Packit |
577717 |
if (ival > 63)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
reg.cbo.unc_tid = 1;
|
|
Packit |
577717 |
filters[0].hswep_cbo_filt0.cid = ival; /* includes non-thread data */
|
|
Packit |
577717 |
has_cbo_tid = 1;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_CF1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NF: /* node id filter0 */
|
|
Packit |
577717 |
if (ival > 255 || ival == 0) {
|
|
Packit |
577717 |
DPRINT("invalid nf, 0 < nf < 256\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
filters[0].cbo_filt.nid = ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_NF;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NF1: /* node id filter1 */
|
|
Packit |
577717 |
if (ival > 255 || ival == 0) {
|
|
Packit |
577717 |
DPRINT("invalid nf, 0 < nf < 256\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
filters[1].ivbep_cbo_filt1.nid = ival;
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_NF1;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_FF: /* freq band filter */
|
|
Packit |
577717 |
if (ival > 255)
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
pcu_filt_band = get_pcu_filt_band(this, reg);
|
|
Packit |
577717 |
filters[0].val = ival << (pcu_filt_band * 8);
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_FF;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_A: /* addr filter */
|
|
Packit |
577717 |
if (ival & ~((1ULL << 40)-1)) {
|
|
Packit |
577717 |
DPRINT("address filter 40bits max\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR_VAL;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
addr.ha_addr.lo_addr = ival; /* LSB 26 bits */
|
|
Packit |
577717 |
addr.ha_addr.hi_addr = (ival >> 26) & ((1ULL << 14)-1);
|
|
Packit |
577717 |
umodmsk |= _SNBEP_UNC_ATTR_A;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_ISOC: /* isoc filter */
|
|
Packit |
577717 |
filters[1].ivbep_cbo_filt1.isoc = !!ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NC: /* nc filter */
|
|
Packit |
577717 |
filters[1].ivbep_cbo_filt1.nc = !!ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* check that there is at least of unit mask in each unit mask group
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (pe[e->event].numasks && (ugrpmsk != grpmsk || ugrpmsk == 0)) {
|
|
Packit |
577717 |
uint64_t um = 0;
|
|
Packit |
577717 |
ugrpmsk ^= grpmsk;
|
|
Packit |
577717 |
ret = snbep_unc_add_defaults(this, e, ugrpmsk, &um, filters, max_grpid);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
umask2 |= um;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* nf= is only required on some events in CBO
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!(modmsk_r & _SNBEP_UNC_ATTR_NF) && (umodmsk & _SNBEP_UNC_ATTR_NF)) {
|
|
Packit |
577717 |
DPRINT("using nf= on an umask which does not require it\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (!(modmsk_r & _SNBEP_UNC_ATTR_NF1) && (umodmsk & _SNBEP_UNC_ATTR_NF1)) {
|
|
Packit |
577717 |
DPRINT("using nf= on an umask which does not require it\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
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 |
evt_strcat(e->fstr, "%s", pe[e->event].name);
|
|
Packit |
577717 |
pfmlib_sort_attr(e);
|
|
Packit |
577717 |
|
|
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 |
DPRINT("umask2=0x%"PRIx64" umask1=0x%"PRIx64"\n", umask2, umask1);
|
|
Packit |
577717 |
e->count = 0;
|
|
Packit |
577717 |
reg.val |= (umask1 | umask2) << 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->codes[e->count++] = reg.val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* handles C-box filter
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (filters[0].val || filters[1].val || has_cbo_tid)
|
|
Packit |
577717 |
e->codes[e->count++] = filters[0].val;
|
|
Packit |
577717 |
if (filters[1].val)
|
|
Packit |
577717 |
e->codes[e->count++] = filters[1].val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* HA address matcher */
|
|
Packit |
577717 |
if (addr.val)
|
|
Packit |
577717 |
e->codes[e->count++] = addr.val;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (k = 0; k < e->npattrs; k++) {
|
|
Packit |
577717 |
int idx;
|
|
Packit |
577717 |
|
|
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 |
idx = e->pattrs[k].idx;
|
|
Packit |
577717 |
switch(idx) {
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_E:
|
|
Packit |
577717 |
if (is_occ_event(this, e->event))
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_occ_edge);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_edge);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_I:
|
|
Packit |
577717 |
if (is_occ_event(this, e->event))
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_occ_inv);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_inv);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_T8:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_thres);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_T5:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_thres);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_TF:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.cbo.unc_tid);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_CF:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[0].cbo_filt.cid);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_CF1:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[0].hswep_cbo_filt0.cid);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_FF:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, (filters[0].val >> (pcu_filt_band*8)) & 0xff);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_ISOC:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.isoc);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NC:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.nc);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NF:
|
|
Packit |
577717 |
if (modmsk_r & _SNBEP_UNC_ATTR_NF)
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[0].cbo_filt.nid);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_NF1:
|
|
Packit |
577717 |
if (modmsk_r & _SNBEP_UNC_ATTR_NF1)
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.nid);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case SNBEP_UNC_ATTR_A:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=0x%lx", snbep_unc_mods[idx].name,
|
|
Packit |
577717 |
addr.ha_addr.hi_addr << 26 | addr.ha_addr.lo_addr);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
display_reg(this, e, reg);
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_snbep_unc_can_auto_encode(void *this, int pidx, int uidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
if (intel_x86_eflag(this, pidx, INTEL_X86_NO_AUTOENCODE))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return !intel_x86_uflag(this, pidx, uidx, INTEL_X86_NO_AUTOENCODE);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_intel_snbep_unc_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 |
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 |
|
|
Packit |
577717 |
if (!intel_x86_uflag(this, pidx, idx, INTEL_X86_CODE_OVERRIDE))
|
|
Packit |
577717 |
info->code >>= 8;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (info->code == 0)
|
|
Packit |
577717 |
info->code = pe[pidx].umasks[idx].ufilters[0];
|
|
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 |
}
|