gprofng: 31123 improvements to hardware event implementation

Our hardware counter profiling is based on perf_event_open().
Our HWC tables are absent for new machines.
I have added HWC tables for the following events: PERF_TYPE_HARDWARE,
PERF_TYPE_SOFTWARE, PERF_TYPE_HW_CACHE. Other events require additional fixes.

Did a little cleaning: marked the symbols as static, used Stringbuilder,
created a function to read /proc/cpuinfo.

gprofng/ChangeLog
2024-01-08  Vladimir Mezentsev  <vladimir.mezentsev@oracle.com>

	PR gprofng/31123
	* common/core_pcbe.c: Mark the symbols as static. Add events_generic[].
	* common/hwc_cpus.h: Declare a new function read_cpuinfo.
	* common/hwcdrv.c: Add a new parameter in init_perf_event().
	* common/hwcentry.h: Add use_perf_event_type in Hwcentry.
	* common/hwcfuncs.c (process_data_descriptor): Read use_perf_event_type,
	type, config.
	* common/hwctable.c: Add a new HWC table generic_list[].
	* common/opteron_pcbe.c (opt_pcbe_init): Accept AMD machines.
	* src/collctrl.cc: Use StringBuilder in Coll_Ctrl::build_data_desc().
	Add a new function read_cpuinfo.
This commit is contained in:
Vladimir Mezentsev
2024-01-08 22:00:24 -08:00
parent e1cab50d2d
commit 8fe04eeb2c
8 changed files with 293 additions and 247 deletions

View File

@@ -675,26 +675,21 @@ dump_perf_event_attr (struct perf_event_attr *at)
}
static void
init_perf_event (struct perf_event_attr *hw, uint64_t event, uint64_t period)
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); // fwd/bwd compat
#if defined(__i386__) || defined(__x86_64)
//note: Nehalem/Westmere OFFCORE_RESPONSE in upper 32 bits
hw->config = event;
hw->type = PERF_TYPE_RAW; // hw/sw/trace/raw...
#elif defined(__aarch64__)
hw->type = (event >> 24) & 7;
hw->config = event & 0xff;
#elif defined(sparc)
//SPARC needs to be shifted up 16 bits
hw->config = (event & 0xFFFF) << 16; // uint64_t event
uint64_t regs = (event >> 20) & 0xf; // see sparc_pcbe.c
hw->config |= regs << 4; // for M8, supported PICs need to be placed at bits [7:4]
hw->type = PERF_TYPE_RAW; // hw/sw/trace/raw...
#endif
hw->size = sizeof (struct perf_event_attr);
if (hwce && hwce->use_perf_event_type)
{
hw->config = hwce->config;
hw->type = hwce->type;
}
else
{ // backward compatibility. The old interface had no 'hwce' argument.
hw->config = event;
hw->type = PERF_TYPE_RAW; // hw/sw/trace/raw...
}
hw->sample_period = period;
hw->sample_type = PERF_SAMPLE_IP |
// PERF_SAMPLE_TID |
@@ -858,7 +853,7 @@ hdrv_pcl_internal_open ()
perf_event_def_t tmp_event_def;
memset (&tmp_event_def, 0, sizeof (tmp_event_def));
struct perf_event_attr *pe_attr = &tmp_event_def.hw;
init_perf_event (pe_attr, 0, 0);
init_perf_event (pe_attr, 0, 0, NULL);
pe_attr->type = PERF_TYPE_HARDWARE; // specify abstracted HW event
pe_attr->config = PERF_COUNT_HW_INSTRUCTIONS; // specify abstracted insts
int hwc_fd = perf_event_open (pe_attr,
@@ -1283,7 +1278,7 @@ hwcdrv_create_counters (unsigned hwcdef_cnt, Hwcentry *hwcdef)
glb_event_def->min_time = hwcdef[idx].min_time;
glb_event_def->name = strdup (hwcdef[idx].name); // memory leak??? very minor
init_perf_event (&glb_event_def->hw, glb_event_def->eventsel,
glb_event_def->counter_preload);
glb_event_def->counter_preload, hwcdef + idx);
TprintfT (DBG_LT1, "hwcdrv: create_counters: pic=%u name='%s' interval=%lld"
"(min_time=%lld): reg_num=0x%x eventsel=0x%llx ireset=%lld usr=%lld sys=%lld\n",
idx, hwcdef[idx].int_name, (long long) glb_event_def->counter_preload,