mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
gprofng: add hardware counters for Intel Ice Lake processor
gprofng/ChangeLog 2024-07-07 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>. * common/hwc_cpus.h: New constant for Intel Ice Lake processor. * common/hwcdrv.c: Add a new argument to hwcfuncs_get_x86_eventsel. Set config1 in perf_event_attr. Remove the use of memset. * common/core_pcbe.c (core_pcbe_get_eventnum): Return 0. * common/hwcentry.h: Add config1. * src/collctrl.cc (Coll_Ctrl::build_data_desc):Set config1. * common/hwcfuncs.c (process_data_descriptor): Set config1. * common/hwctable.c: Add the hwc table for Intel Ice Lake processor. * src/hwc_intel_icelake.h: New file.
This commit is contained in:
parent
604b972e61
commit
971ae1844e
@ -3017,8 +3017,7 @@ core_pcbe_get_eventnum (const char *eventname, uint_t pmc, eventsel_t *eventnum,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*eventnum = (eventsel_t) - 1;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hdrv_pcbe_api_t hdrv_pcbe_core_api = {
|
||||
|
@ -107,6 +107,7 @@ extern cpu_info_t *read_cpuinfo();
|
||||
#define CPC_INTEL_HASWELL 2060
|
||||
#define CPC_INTEL_BROADWELL 2070
|
||||
#define CPC_INTEL_SKYLAKE 2080
|
||||
#define CPC_INTEL_ICELAKE 2081
|
||||
#define CPC_INTEL_UNKNOWN 2499
|
||||
#define CPC_AMD_K8C 2500 /* Opteron, Athlon... */
|
||||
#define CPC_AMD_FAM_10H 2501 /* Barcelona, Shanghai... */
|
||||
|
@ -215,29 +215,29 @@ set_x86_attr_bits (eventsel_t *result_mask, eventsel_t evnt_valid_umask,
|
||||
}
|
||||
|
||||
static int
|
||||
hwcfuncs_get_x86_eventsel (unsigned int regno, const char *int_name,
|
||||
hwcfuncs_get_x86_eventsel (Hwcentry *h,
|
||||
eventsel_t *return_event, uint_t *return_pmc_sel)
|
||||
{
|
||||
hwcfuncs_attr_t attrs[HWCFUNCS_MAX_ATTRS + 1];
|
||||
unsigned nattrs = 0;
|
||||
char *nameOnly = NULL;
|
||||
eventsel_t evntsel = 0; // event number
|
||||
eventsel_t evntsel = h->config;
|
||||
eventsel_t evnt_valid_umask = 0;
|
||||
uint_t pmc_sel = 0;
|
||||
int rc = -1;
|
||||
*return_event = 0;
|
||||
*return_pmc_sel = 0;
|
||||
void *attr_mem = hwcfuncs_parse_attrs (int_name, attrs, HWCFUNCS_MAX_ATTRS,
|
||||
void *attr_mem = hwcfuncs_parse_attrs (h->int_name, attrs, HWCFUNCS_MAX_ATTRS,
|
||||
&nattrs, NULL);
|
||||
if (!attr_mem)
|
||||
{
|
||||
logerr (GTXT ("out of memory, could not parse attributes\n"));
|
||||
return -1;
|
||||
}
|
||||
hwcfuncs_parse_ctr (int_name, NULL, &nameOnly, NULL, NULL, NULL);
|
||||
hwcfuncs_parse_ctr (h->int_name, NULL, &nameOnly, NULL, NULL, NULL);
|
||||
|
||||
/* look up evntsel */
|
||||
if (myperfctr_get_x86_eventnum (nameOnly, regno,
|
||||
if (myperfctr_get_x86_eventnum (nameOnly, h->reg_num,
|
||||
&evntsel, &evnt_valid_umask, &pmc_sel))
|
||||
{
|
||||
logerr (GTXT ("counter `%s' is not valid\n"), nameOnly);
|
||||
@ -335,6 +335,7 @@ typedef struct
|
||||
hrtime_t min_time; // minimum time we're targeting between events
|
||||
char *name;
|
||||
} perf_event_def_t;
|
||||
static perf_event_def_t event_def_0;
|
||||
|
||||
typedef struct
|
||||
{ // runtime state of perf_event buffer
|
||||
@ -601,11 +602,17 @@ static void
|
||||
init_perf_event (struct perf_event_attr *hw, uint64_t event, uint64_t period,
|
||||
Hwcentry *hwce)
|
||||
{
|
||||
memset (hw, 0, sizeof (struct perf_event_attr));
|
||||
hw->size = sizeof (struct perf_event_attr);
|
||||
static struct perf_event_attr perf_event_attr_0 = {
|
||||
.size = sizeof (struct perf_event_attr),
|
||||
.disabled = 1, /* off by default */
|
||||
.exclude_hv = 1,
|
||||
.wakeup_events = 1 /* wakeup every n events */
|
||||
};
|
||||
*hw = perf_event_attr_0;
|
||||
if (hwce && hwce->use_perf_event_type)
|
||||
{
|
||||
hw->config = hwce->config;
|
||||
hw->config1 = hwce->config1;
|
||||
hw->type = hwce->type;
|
||||
}
|
||||
else
|
||||
@ -632,13 +639,10 @@ init_perf_event (struct perf_event_attr *hw, uint64_t event, uint64_t period,
|
||||
// PERF_FORMAT_ID |
|
||||
// PERF_FORMAT_GROUP |
|
||||
0;
|
||||
hw->disabled = 1; /* off by default */
|
||||
|
||||
// Note: the following override config.priv bits!
|
||||
hw->exclude_user = (event & (1 << 16)) == 0; /* don't count user */
|
||||
hw->exclude_kernel = (event & (1 << 17)) == 0; /* ditto kernel */
|
||||
hw->exclude_hv = 1; /* ditto hypervisor */
|
||||
hw->wakeup_events = 1; /* wakeup every n events */
|
||||
dump_perf_event_attr (hw);
|
||||
}
|
||||
|
||||
@ -773,8 +777,7 @@ hdrv_pcl_internal_open ()
|
||||
}
|
||||
|
||||
// determine if PCL is available
|
||||
perf_event_def_t tmp_event_def;
|
||||
memset (&tmp_event_def, 0, sizeof (tmp_event_def));
|
||||
perf_event_def_t tmp_event_def = event_def_0;
|
||||
struct perf_event_attr *pe_attr = &tmp_event_def.hw;
|
||||
init_perf_event (pe_attr, 0, 0, NULL);
|
||||
pe_attr->type = PERF_TYPE_HARDWARE; // specify abstracted HW event
|
||||
@ -1186,11 +1189,10 @@ hwcdrv_create_counters (unsigned hwcdef_cnt, Hwcentry *hwcdef)
|
||||
for (unsigned idx = 0; idx < hwcdef_cnt; idx++)
|
||||
{
|
||||
perf_event_def_t *glb_event_def = &global_perf_event_def[idx];
|
||||
memset (glb_event_def, 0, sizeof (perf_event_def_t));
|
||||
*glb_event_def = event_def_0;
|
||||
unsigned int pmc_sel;
|
||||
eventsel_t evntsel;
|
||||
if (hwcfuncs_get_x86_eventsel (hwcdef[idx].reg_num,
|
||||
hwcdef[idx].int_name, &evntsel, &pmc_sel))
|
||||
if (hwcfuncs_get_x86_eventsel (hwcdef + idx, &evntsel, &pmc_sel))
|
||||
{
|
||||
TprintfT (0, "hwcdrv: ERROR: hwcfuncs_get_x86_eventsel() failed\n");
|
||||
return HWCFUNCS_ERROR_HWCARGS;
|
||||
|
@ -118,6 +118,7 @@ extern "C"
|
||||
unsigned int use_perf_event_type : 16; /* Set 1 to use two fields below */
|
||||
unsigned int type : 16; /* Type of perf_event_attr */
|
||||
long long config; /* perf_event_type -specific configuration */
|
||||
long long config1; /* perf_event_type -specific configuration */
|
||||
int sort_order; /* "tag" to associate experiment record with HWC def */
|
||||
hrtime_t min_time; /* target minimum time between overflow events. 0 is off. See HWCTIME_* macros */
|
||||
hrtime_t min_time_default; /* if min_time==HWCTIME_AUTO, use this value instead. 0 is off. */
|
||||
|
@ -288,6 +288,12 @@ process_data_descriptor (const char *defstring)
|
||||
break;
|
||||
}
|
||||
hwcdef[idx].config = strtol (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
break;
|
||||
}
|
||||
hwcdef[idx].config1 = strtol (dsp, &dsp, 0);
|
||||
if (*dsp++ != ':')
|
||||
{
|
||||
err = HWCFUNCS_ERROR_HWCARGS;
|
||||
|
@ -1304,6 +1304,7 @@ static Hwcentry generic_list[] = {
|
||||
|
||||
#include "hwc_amd_zen3.h"
|
||||
#include "hwc_amd_zen4.h"
|
||||
#include "hwc_intel_icelake.h"
|
||||
|
||||
/* structure defining the counters for a CPU type */
|
||||
typedef struct
|
||||
@ -1343,6 +1344,7 @@ static cpu_list_t cputabs[] = {
|
||||
"insts,,cycles,,l3m,,dtlbm", 0}},
|
||||
{CPC_INTEL_SKYLAKE, intelSkylakeList, {"insts,,cycles,,+l2m_latency,,dtlbm_stall",
|
||||
"insts,,cycles,,l2m_stall,,dtlbm_stall", 0}},
|
||||
{CPC_INTEL_ICELAKE, intelIcelakeList, {"insts,,cycles,,dTLB-load-misses", 0}},
|
||||
{CPC_INTEL_UNKNOWN, intelLinuxUnknown, {"cycles,,insts,,llm",
|
||||
"user_time,,system_time,,cycles,,insts,,llm", 0}},
|
||||
{CPC_INTEL_ATOM, intelAtomList, {"insts", 0}},
|
||||
@ -1827,7 +1829,7 @@ setup_cpc_general (int skip_hwc_test)
|
||||
hwcdrv->hwcdrv_get_info (&cpcx_cpuver, &cpcx_cciname, &cpcx_npics,
|
||||
&cpcx_docref, &cpcx_support_bitmask);
|
||||
|
||||
/* Fix cpcx_cpuver for new Zen machines */
|
||||
/* Fix cpcx_cpuver for new Zen and Intel machines */
|
||||
cpu_info_t *cpu_p = read_cpuinfo ();
|
||||
if (strcmp (cpu_p->cpu_vendorstr, "AuthenticAMD") == 0)
|
||||
{
|
||||
@ -1846,6 +1848,14 @@ setup_cpc_general (int skip_hwc_test)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (strcmp (cpu_p->cpu_vendorstr, "GenuineIntel") == 0)
|
||||
{
|
||||
if (cpu_p->cpu_family == 6)
|
||||
{
|
||||
if (cpu_p->cpu_model == 106)
|
||||
cpcx_cpuver = CPC_INTEL_ICELAKE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DISALLOW_PENTIUM_PRO_MMX_7007575
|
||||
if (cpcx_cpuver == CPC_PENTIUM_PRO_MMX)
|
||||
|
@ -1688,8 +1688,9 @@ Coll_Ctrl::build_data_desc ()
|
||||
min_time = h->min_time_default;
|
||||
if (ii > 0)
|
||||
sb.append (',');
|
||||
sb.appendf ("%d:%d:%lld:%s:%s:%lld:%d:m%lld:%d:%d:0x%x",
|
||||
sb.appendf ("%d:%d:%lld:%lld:%s:%s:%lld:%d:m%lld:%d:%d:0x%x",
|
||||
h->use_perf_event_type, h->type, (long long) h->config,
|
||||
(long long) h->config1,
|
||||
strcmp (h->name, h->int_name) ? h->name : "",
|
||||
h->int_name, (long long) h->reg_num, h->val,
|
||||
(long long) min_time, ii, /*tag*/ h->timecvt, h->memop);
|
||||
|
1171
gprofng/src/hwc_intel_icelake.h
Normal file
1171
gprofng/src/hwc_intel_icelake.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user