|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* pfmlib_amd64.c : support for the AMD64 architected PMU
|
|
Packit |
577717 |
* (for both 64 and 32 bit modes)
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (c) 2009 Google, Inc
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@gmail.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Based on:
|
|
Packit |
577717 |
* Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
|
|
Packit |
577717 |
* Contributed by Stephane Eranian <eranian@hpl.hp.com>
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
577717 |
* of this software and associated documentation files (the "Software"), to deal
|
|
Packit |
577717 |
* in the Software without restriction, including without limitation the rights
|
|
Packit |
577717 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
Packit |
577717 |
* of the Software, and to permit persons to whom the Software is furnished to do so,
|
|
Packit |
577717 |
* subject to the following conditions:
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* The above copyright notice and this permission notice shall be included in all
|
|
Packit |
577717 |
* copies or substantial portions of the Software.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
Packit |
577717 |
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
Packit |
577717 |
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
Packit |
577717 |
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
Packit |
577717 |
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
Packit |
577717 |
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#include <sys/types.h>
|
|
Packit |
577717 |
#include <string.h>
|
|
Packit |
577717 |
#include <stdlib.h>
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* private headers */
|
|
Packit |
577717 |
#include "pfmlib_priv.h" /* library private */
|
|
Packit |
577717 |
#include "pfmlib_amd64_priv.h" /* architecture private */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
const pfmlib_attr_desc_t amd64_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"), /* 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("h", "monitor in hypervisor"), /* monitor in hypervisor*/
|
|
Packit |
577717 |
PFM_ATTR_B("g", "measure in guest"), /* monitor in guest */
|
|
Packit |
577717 |
PFM_ATTR_NULL /* end-marker to avoid exporting number of entries */
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
pfmlib_pmu_t amd64_support;
|
|
Packit |
577717 |
pfm_amd64_config_t pfm_amd64_cfg;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
amd64_num_mods(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_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 |
static inline int
|
|
Packit |
577717 |
amd64_eflag(void *this, int idx, int flag)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
return !!(pe[idx].flags & flag);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_uflag(void *this, int idx, int attr, int flag)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
return !!(pe[idx].umasks[attr].uflags & flag);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_event_ibsfetch(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return amd64_eflag(this, idx, AMD64_FL_IBSFE);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_event_ibsop(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return amd64_eflag(this, idx, AMD64_FL_IBSOP);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_from_rev(unsigned int flags)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return ((flags) >> 8) & 0xff;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_till_rev(unsigned int flags)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
int till = (((flags)>>16) & 0xff);
|
|
Packit |
577717 |
if (!till)
|
|
Packit |
577717 |
return 0xff;
|
|
Packit |
577717 |
return till;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static void
|
|
Packit |
577717 |
amd64_get_revision(pfm_amd64_config_t *cfg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfm_pmu_t rev = PFM_PMU_NONE;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cfg->family == 6) {
|
|
Packit |
577717 |
cfg->revision = PFM_PMU_AMD64_K7;
|
|
Packit |
577717 |
return;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (cfg->family == 15) {
|
|
Packit |
577717 |
switch (cfg->model >> 4) {
|
|
Packit |
577717 |
case 0:
|
|
Packit |
577717 |
if (cfg->model == 5 && cfg->stepping < 2) {
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVB;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
if (cfg->model == 4 && cfg->stepping == 0) {
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVB;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVC;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 1:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVD;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 2:
|
|
Packit |
577717 |
case 3:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVE;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
case 0xc:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVF;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
case 7:
|
|
Packit |
577717 |
case 8:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVG;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_K8_REVB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (cfg->family == 16) { /* family 10h */
|
|
Packit |
577717 |
switch (cfg->model) {
|
|
Packit |
577717 |
case 4:
|
|
Packit |
577717 |
case 5:
|
|
Packit |
577717 |
case 6:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM10H_SHANGHAI;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case 8:
|
|
Packit |
577717 |
case 9:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM10H_ISTANBUL;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM10H_BARCELONA;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (cfg->family == 17) { /* family 11h */
|
|
Packit |
577717 |
switch (cfg->model) {
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM11H_TURION;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (cfg->family == 18) { /* family 12h */
|
|
Packit |
577717 |
switch (cfg->model) {
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM12H_LLANO;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (cfg->family == 20) { /* family 14h */
|
|
Packit |
577717 |
switch (cfg->model) {
|
|
Packit |
577717 |
default:
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM14H_BOBCAT;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
} else if (cfg->family == 21) { /* family 15h */
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM15H_INTERLAGOS;
|
|
Packit |
577717 |
} else if (cfg->family == 23) { /* family 17h */
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM17H;
|
|
Packit |
577717 |
} else if (cfg->family == 22) { /* family 16h */
|
|
Packit |
577717 |
rev = PFM_PMU_AMD64_FAM16H;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cfg->revision = rev;
|
|
Packit |
577717 |
}
|
|
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 int
|
|
Packit |
577717 |
amd64_event_valid(void *this, int i)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
int flags;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
flags = pe[i].flags;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->pmu_rev < amd64_from_rev(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->pmu_rev > amd64_till_rev(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* no restrictions or matches restrictions */
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
amd64_umask_valid(void *this, int i, int attr)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
int flags;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
flags = pe[i].umasks[attr].uflags;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->pmu_rev < amd64_from_rev(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pmu->pmu_rev > amd64_till_rev(flags))
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* no restrictions or matches restrictions */
|
|
Packit |
577717 |
return 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static unsigned int
|
|
Packit |
577717 |
amd64_num_umasks(void *this, int pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
unsigned int i, n = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* unit masks + modifiers */
|
|
Packit |
577717 |
for (i = 0; i < pe[pidx].numasks; i++)
|
|
Packit |
577717 |
if (amd64_umask_valid(this, pidx, i))
|
|
Packit |
577717 |
n++;
|
|
Packit |
577717 |
return n;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
amd64_get_umask(void *this, int pidx, int attr_idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
int n;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for (i=0, n = 0; i < pe[pidx].numasks; i++) {
|
|
Packit |
577717 |
if (!amd64_umask_valid(this, pidx, i))
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if (n++ == attr_idx)
|
|
Packit |
577717 |
return i;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int
|
|
Packit |
577717 |
amd64_attr2mod(void *this, int pidx, int attr_idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
size_t x;
|
|
Packit |
577717 |
int n;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
n = attr_idx - amd64_num_umasks(this, pidx);
|
|
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 |
void amd64_display_reg(void *this, pfmlib_event_desc_t *e, pfm_amd64_reg_t reg)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (IS_FAMILY_10H(pmu) || IS_FAMILY_15H(pmu))
|
|
Packit |
577717 |
__pfm_vbprintf("[0x%"PRIx64" event_sel=0x%x umask=0x%x os=%d usr=%d en=%d int=%d inv=%d edge=%d cnt_mask=%d guest=%d host=%d] %s\n",
|
|
Packit |
577717 |
reg.val,
|
|
Packit |
577717 |
reg.sel_event_mask | (reg.sel_event_mask2 << 8),
|
|
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 |
reg.sel_guest,
|
|
Packit |
577717 |
reg.sel_host,
|
|
Packit |
577717 |
e->fstr);
|
|
Packit |
577717 |
else
|
|
Packit |
577717 |
__pfm_vbprintf("[0x%"PRIx64" event_sel=0x%x umask=0x%x os=%d usr=%d en=%d int=%d inv=%d edge=%d cnt_mask=%d] %s\n",
|
|
Packit |
577717 |
reg.val,
|
|
Packit |
577717 |
reg.sel_event_mask,
|
|
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 |
e->fstr);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int a, b, c, d;
|
|
Packit |
577717 |
char buffer[128];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_amd64_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 |
if (strcmp(buffer, "AuthenticAMD"))
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
cpuid(1, &a, &b, &c, &d);
|
|
Packit |
577717 |
pfm_amd64_cfg.family = (a >> 8) & 0x0000000f; // bits 11 - 8
|
|
Packit |
577717 |
pfm_amd64_cfg.model = (a >> 4) & 0x0000000f; // Bits 7 - 4
|
|
Packit |
577717 |
if (pfm_amd64_cfg.family == 0xf) {
|
|
Packit |
577717 |
pfm_amd64_cfg.family += (a >> 20) & 0x000000ff; // Extended family
|
|
Packit |
577717 |
pfm_amd64_cfg.model |= (a >> 12) & 0x000000f0; // Extended model
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
pfm_amd64_cfg.stepping= a & 0x0000000f; // bits 3 - 0
|
|
Packit |
577717 |
|
|
Packit |
577717 |
amd64_get_revision(&pfm_amd64_cfg);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pfm_amd64_cfg.revision == PFM_PMU_NONE)
|
|
Packit |
577717 |
return PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_family_detect(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
struct pfmlib_pmu *pmu = this;
|
|
Packit |
577717 |
int ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_amd64_detect(this);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
ret = pfm_amd64_cfg.revision;
|
|
Packit |
577717 |
return ret == pmu->cpu_family ? PFM_SUCCESS : PFM_ERR_NOTSUPP;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static int
|
|
Packit |
577717 |
amd64_add_defaults(void *this, pfmlib_event_desc_t *e, unsigned int msk, uint64_t *umask)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *ent, *pe = this_pe(this);
|
|
Packit |
577717 |
unsigned int i;
|
|
Packit |
577717 |
int j, k, added, omit, numasks_grp;
|
|
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 = omit = numasks_grp = 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 |
/* number of umasks in this group */
|
|
Packit |
577717 |
numasks_grp++;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (amd64_uflag(this, e->event, idx, AMD64_FL_DFL)) {
|
|
Packit |
577717 |
DPRINT("added default for %s j=%d idx=%d\n", ent->umasks[idx].uname, j, idx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
*umask |= ent->umasks[idx].ucode;
|
|
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 |
}
|
|
Packit |
577717 |
if (amd64_uflag(this, e->event, idx, AMD64_FL_OMIT))
|
|
Packit |
577717 |
omit++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* fail if no default was found AND at least one umasks cannot be omitted
|
|
Packit |
577717 |
* in the group
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (!added && omit != numasks_grp) {
|
|
Packit |
577717 |
DPRINT("no default found for event %s unit mask group %d\n", ent->name, i);
|
|
Packit |
577717 |
return PFM_ERR_UMASK;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
e->nattrs = k;
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_get_encoding(void *this, pfmlib_event_desc_t *e)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
pfm_amd64_reg_t reg;
|
|
Packit |
577717 |
pfmlib_event_attr_info_t *a;
|
|
Packit |
577717 |
uint64_t umask = 0;
|
|
Packit |
577717 |
unsigned int plmmsk = 0;
|
|
Packit |
577717 |
int k, ret, grpid;
|
|
Packit |
577717 |
unsigned int grpmsk, ugrpmsk = 0;
|
|
Packit |
577717 |
int grpcounts[AMD64_MAX_GRP];
|
|
Packit |
577717 |
int ncombo[AMD64_MAX_GRP];
|
|
Packit |
577717 |
|
|
Packit |
577717 |
memset(grpcounts, 0, sizeof(grpcounts));
|
|
Packit |
577717 |
memset(ncombo, 0, sizeof(ncombo));
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->fstr[0] = '\0';
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.val = 0; /* assume reserved bits are zerooed */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
grpmsk = (1 << pe[e->event].ngrp)-1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (amd64_event_ibsfetch(this, e->event))
|
|
Packit |
577717 |
reg.ibsfetch.en = 1;
|
|
Packit |
577717 |
else if (amd64_event_ibsop(this, e->event))
|
|
Packit |
577717 |
reg.ibsop.en = 1;
|
|
Packit |
577717 |
else {
|
|
Packit |
577717 |
reg.sel_event_mask = pe[e->event].code;
|
|
Packit |
577717 |
reg.sel_event_mask2 = pe[e->event].code >> 8;
|
|
Packit |
577717 |
reg.sel_en = 1; /* force enable */
|
|
Packit |
577717 |
reg.sel_int = 1; /* force APIC */
|
|
Packit |
577717 |
}
|
|
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 |
++grpcounts[grpid];
|
|
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 |
* diinct umasks
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
if (amd64_uflag(this, e->event, a->idx, AMD64_FL_NCOMBO))
|
|
Packit |
577717 |
ncombo[grpid] = 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("event does not support unit mask combination within a group\n");
|
|
Packit |
577717 |
return PFM_ERR_FEATCOMB;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
umask |= pe[e->event].umasks[a->idx].ucode;
|
|
Packit |
577717 |
ugrpmsk |= 1 << pe[e->event].umasks[a->idx].grpid;
|
|
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 checks */
|
|
Packit |
577717 |
if (a->idx & ~0xff) {
|
|
Packit |
577717 |
DPRINT("raw umask is invalid\n");
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
/* override umask */
|
|
Packit |
577717 |
umask = a->idx & 0xff;
|
|
Packit |
577717 |
ugrpmsk = grpmsk;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
} else { /* modifiers */
|
|
Packit |
577717 |
uint64_t ival = e->attrs[k].ival;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
switch(a->idx) { //amd64_attr2mod(this, e->osid, e->event, a->idx)) {
|
|
Packit |
577717 |
case AMD64_ATTR_I: /* invert */
|
|
Packit |
577717 |
reg.sel_inv = !!ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_E: /* edge */
|
|
Packit |
577717 |
reg.sel_edge = !!ival;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_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 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_U: /* USR */
|
|
Packit |
577717 |
reg.sel_usr = !!ival;
|
|
Packit |
577717 |
plmmsk |= _AMD64_ATTR_U;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_K: /* OS */
|
|
Packit |
577717 |
reg.sel_os = !!ival;
|
|
Packit |
577717 |
plmmsk |= _AMD64_ATTR_K;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_G: /* GUEST */
|
|
Packit |
577717 |
reg.sel_guest = !!ival;
|
|
Packit |
577717 |
plmmsk |= _AMD64_ATTR_G;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_H: /* HOST */
|
|
Packit |
577717 |
reg.sel_host = !!ival;
|
|
Packit |
577717 |
plmmsk |= _AMD64_ATTR_H;
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
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 & (_AMD64_ATTR_K|_AMD64_ATTR_U|_AMD64_ATTR_H))) {
|
|
Packit |
577717 |
if (e->dfl_plm & PFM_PLM0)
|
|
Packit |
577717 |
reg.sel_os = 1;
|
|
Packit |
577717 |
if (e->dfl_plm & PFM_PLM3)
|
|
Packit |
577717 |
reg.sel_usr = 1;
|
|
Packit |
577717 |
if ((IS_FAMILY_10H(this) || IS_FAMILY_15H(this))
|
|
Packit |
577717 |
&& e->dfl_plm & PFM_PLMH)
|
|
Packit |
577717 |
reg.sel_host = 1;
|
|
Packit |
577717 |
}
|
|
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) {
|
|
Packit |
577717 |
ugrpmsk ^= grpmsk;
|
|
Packit |
577717 |
ret = amd64_add_defaults(this, e, ugrpmsk, &umask);
|
|
Packit |
577717 |
if (ret != PFM_SUCCESS)
|
|
Packit |
577717 |
return ret;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
reg.sel_unit_mask = umask;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
e->codes[0] = reg.val;
|
|
Packit |
577717 |
e->count = 1;
|
|
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 |
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 AMD64_ATTR_K:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_os);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_U:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_usr);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_E:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_edge);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_I:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_inv);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_C:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_cnt_mask);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_H:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_host);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
case AMD64_ATTR_G:
|
|
Packit |
577717 |
evt_strcat(e->fstr, ":%s=%lu", amd64_mods[idx].name, reg.sel_guest);
|
|
Packit |
577717 |
break;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
amd64_display_reg(this, e, reg);
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_get_event_first(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
int idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(idx=0; idx < pmu->pme_count; idx++)
|
|
Packit |
577717 |
if (amd64_event_valid(this, idx))
|
|
Packit |
577717 |
return idx;
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_get_event_next(void *this, int idx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* basic validity checks on idx down by caller */
|
|
Packit |
577717 |
if (idx >= (pmu->pme_count-1))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* validate event fo this host PMU */
|
|
Packit |
577717 |
if (!amd64_event_valid(this, idx))
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(++idx; idx < pmu->pme_count; idx++) {
|
|
Packit |
577717 |
if (amd64_event_valid(this, idx))
|
|
Packit |
577717 |
return idx;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
return -1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_event_is_valid(void *this, int pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pidx < 0 || pidx >= pmu->pme_count)
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* valid revision */
|
|
Packit |
577717 |
return amd64_event_valid(this, pidx);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_get_event_attr_info(void *this, int pidx, int attr_idx, pfmlib_event_attr_info_t *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
int numasks, idx;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
numasks = amd64_num_umasks(this, pidx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (attr_idx < numasks) {
|
|
Packit |
577717 |
idx = amd64_get_umask(this, pidx, attr_idx);
|
|
Packit |
577717 |
if (idx == -1)
|
|
Packit |
577717 |
return PFM_ERR_ATTR;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->name = pe[pidx].umasks[idx].uname;
|
|
Packit |
577717 |
info->desc = pe[pidx].umasks[idx].udesc;
|
|
Packit |
577717 |
info->code = pe[pidx].umasks[idx].ucode;
|
|
Packit |
577717 |
info->type = PFM_ATTR_UMASK;
|
|
Packit |
577717 |
info->is_dfl = amd64_uflag(this, pidx, idx, AMD64_FL_DFL);
|
|
Packit |
577717 |
} else {
|
|
Packit |
577717 |
idx = amd64_attr2mod(this, pidx, attr_idx);
|
|
Packit |
577717 |
info->name = amd64_mods[idx].name;
|
|
Packit |
577717 |
info->desc = amd64_mods[idx].desc;
|
|
Packit |
577717 |
info->type = amd64_mods[idx].type;
|
|
Packit |
577717 |
info->code = idx;
|
|
Packit |
577717 |
info->is_dfl = 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
info->is_precise = 0;
|
|
Packit |
577717 |
info->equiv = NULL;
|
|
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_amd64_get_event_info(void *this, int idx, pfm_event_info_t *info)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->name = pe[idx].name;
|
|
Packit |
577717 |
info->desc = pe[idx].desc;
|
|
Packit |
577717 |
info->equiv = NULL;
|
|
Packit |
577717 |
info->code = pe[idx].code;
|
|
Packit |
577717 |
info->idx = idx;
|
|
Packit |
577717 |
info->pmu = pmu->pmu;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
info->is_precise = 0;
|
|
Packit |
577717 |
info->nattrs = amd64_num_umasks(this, idx);
|
|
Packit |
577717 |
info->nattrs += amd64_num_mods(this, idx);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
return PFM_SUCCESS;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int
|
|
Packit |
577717 |
pfm_amd64_validate_table(void *this, FILE *fp)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
const amd64_entry_t *pe = this_pe(this);
|
|
Packit |
577717 |
const char *name = pmu->name;
|
|
Packit |
577717 |
unsigned int j, k;
|
|
Packit |
577717 |
int i, ndfl;
|
|
Packit |
577717 |
int error = 0;
|
|
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 (!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", 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 && pe[i].ngrp == 0) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: ngrp cannot be zero\n", 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", name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].ngrp >= AMD64_MAX_GRP) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: ngrp too big (max=%d)\n", name, i, pe[i].name, AMD64_MAX_GRP);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(ndfl = 0, j= 0; j < 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 |
|
|
Packit |
577717 |
if (!pe[i].umasks[j].udesc) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d:%s umask%d: %s :: no description\n", name, i, pe[i].name, 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", 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 |
|
|
Packit |
577717 |
if (pe[i].umasks[j].uflags & AMD64_FL_DFL) {
|
|
Packit |
577717 |
for(k=0; k < j; k++)
|
|
Packit |
577717 |
if ((pe[i].umasks[k].uflags == pe[i].umasks[j].uflags)
|
|
Packit |
577717 |
&& (pe[i].umasks[k].grpid == pe[i].umasks[j].grpid))
|
|
Packit |
577717 |
ndfl++;
|
|
Packit |
577717 |
if (pe[i].numasks == 1)
|
|
Packit |
577717 |
ndfl = 1;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].numasks > 1 && ndfl) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: more than one default unit mask with same code\n", 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 && ndfl != 1) {
|
|
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].flags & AMD64_FL_NCOMBO) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: NCOMBO is unit mask only flag\n", name, i, pe[i].name);
|
|
Packit |
577717 |
error++;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(j=0; j < pe[i].numasks; j++) {
|
|
Packit |
577717 |
|
|
Packit |
577717 |
if (pe[i].umasks[j].uflags & AMD64_FL_NCOMBO)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
for(k=j+1; k < pe[i].numasks; k++) {
|
|
Packit |
577717 |
if (pe[i].umasks[k].uflags & AMD64_FL_NCOMBO)
|
|
Packit |
577717 |
continue;
|
|
Packit |
577717 |
if ((pe[i].umasks[j].ucode & pe[i].umasks[k].ucode)) {
|
|
Packit |
577717 |
fprintf(fp, "pmu: %s event%d: %s :: umask %s and %s have overlapping code bits\n", name, i, pe[i].name, pe[i].umasks[j].uname, pe[i].umasks[k].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 |
unsigned int
|
|
Packit |
577717 |
pfm_amd64_get_event_nattrs(void *this, int pidx)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
unsigned int nattrs;
|
|
Packit |
577717 |
nattrs = amd64_num_umasks(this, pidx);
|
|
Packit |
577717 |
nattrs += amd64_num_mods(this, pidx);
|
|
Packit |
577717 |
return nattrs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
int pfm_amd64_get_num_events(void *this)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
pfmlib_pmu_t *pmu = this;
|
|
Packit |
577717 |
int i, num = 0;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* count actual number of events for specific PMU.
|
|
Packit |
577717 |
* Table may contain more events for the family than
|
|
Packit |
577717 |
* what a specific model actually supports.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
for (i = 0; i < pmu->pme_count; i++)
|
|
Packit |
577717 |
if (amd64_event_valid(this, i))
|
|
Packit |
577717 |
num++;
|
|
Packit |
577717 |
return num;
|
|
Packit |
577717 |
}
|