numatop/0008-x86-zen-Add-support-fo...

157 lines
4.5 KiB
Diff

From aefc85d7b956c4df998afb4cfe5c413e5fd5b062 Mon Sep 17 00:00:00 2001
From: Sandipan Das <sandipan.das@amd.com>
Date: Thu, 10 Mar 2022 10:32:51 +0530
Subject: [PATCH 08/15] x86/zen: Add support for memory access stats
Add support for capturing memory access statistics on Zen
processors using Instruction Based Sampling (IBS).
IBS, by design, cannot tag specific types of ops and hence
cannot provide samples for only those ops that cause memory
access. Hence, additional post-processing is required for
filtering out irrelevant samples. To get an appropriate
volume of samples, the sampling frequency also needs to be
high.
Signed-off-by: Sandipan Das <sandipan.das@amd.com>
---
common/os/pfwrapper.c | 20 +++++++++++++++++---
x86/zen.c | 35 ++++++++++++++++++++++++++++++++++-
2 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/common/os/pfwrapper.c b/common/os/pfwrapper.c
index e08ce07..d6102be 100644
--- a/common/os/pfwrapper.c
+++ b/common/os/pfwrapper.c
@@ -434,7 +434,8 @@ pf_ll_setup(struct _perf_cpu *cpu, pf_conf_t *conf)
attr.precise_ip = 1;
attr.exclude_guest = conf->exclude_guest;
attr.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | PERF_SAMPLE_CPU |
- PERF_SAMPLE_WEIGHT | PERF_SAMPLE_CALLCHAIN;
+ PERF_SAMPLE_WEIGHT | PERF_SAMPLE_CALLCHAIN |
+ PERF_SAMPLE_DATA_SRC;
attr.disabled = 1;
if ((fds[0] = pf_event_open(&attr, -1, cpu->cpuid, -1, 0)) < 0) {
@@ -481,6 +482,7 @@ ll_sample_read(struct perf_event_mmap_page *mhdr, int size,
pf_ll_rec_t *rec)
{
struct { uint32_t pid, tid; } id;
+ union perf_mem_data_src data_src;
uint64_t i, addr, cpu, weight, nr, value, *ips;
int j, ret = -1;
@@ -492,6 +494,7 @@ ll_sample_read(struct perf_event_mmap_page *mhdr, int size,
* [ u64 nr; }
* { u64 ips[nr]; }
* { u64 weight; }
+ * { u64 data_src; }
* };
*/
if (mmap_buffer_read(mhdr, &id, sizeof (id)) == -1) {
@@ -551,7 +554,18 @@ ll_sample_read(struct perf_event_mmap_page *mhdr, int size,
}
size -= sizeof (weight);
-
+
+ if (mmap_buffer_read(mhdr, &data_src, sizeof (data_src)) == -1) {
+ debug_print(NULL, 2, "ll_sample_read: read data_src failed.\n");
+ goto L_EXIT;
+ }
+
+ size -= sizeof (data_src);
+
+ if (data_src.mem_op == PERF_MEM_OP_NA ||
+ data_src.mem_op == PERF_MEM_OP_EXEC)
+ addr = 0;
+
rec->ip_num = j;
rec->pid = id.pid;
rec->tid = id.tid;
@@ -575,7 +589,7 @@ ll_recbuf_update(pf_ll_rec_t *rec_arr, int *nrec, pf_ll_rec_t *rec)
{
int i;
- if ((rec->pid == 0) || (rec->tid == 0)) {
+ if ((rec->pid == 0) || (rec->tid == 0) || (rec->addr == 0)) {
/* Just consider the user-land process/thread. */
return;
}
diff --git a/x86/zen.c b/x86/zen.c
index 2f851a2..67a425b 100644
--- a/x86/zen.c
+++ b/x86/zen.c
@@ -30,7 +30,9 @@
#include <inttypes.h>
#include <stdlib.h>
+#include <sys/stat.h>
#include <sys/types.h>
+#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
@@ -39,6 +41,9 @@
#include "../common/include/os/plat.h"
#include "include/zen.h"
+#define IBS_OP_PMU_TYPE_PATH \
+ "/sys/bus/event_source/devices/ibs_op/type"
+
static plat_event_config_t s_zen_config[PERF_COUNT_NUM] = {
{ PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES, 0, 0, 0, 0, "LsNotHaltedCyc" },
{ PERF_TYPE_RAW, 0x0000000000004043, 0, 0, 0, 0, "LsDmndFillsFromSys.DRAM_IO_Far" },
@@ -47,8 +52,13 @@ static plat_event_config_t s_zen_config[PERF_COUNT_NUM] = {
{ PERF_TYPE_RAW, 0x0000000000000843, 0, 0, 0, 0, "LsDmndFillsFromSys.DRAM_IO_Near" },
};
+/*
+ * Owing to the nature of IBS uop tagging, a higher sampling period is
+ * required to capture meaningful samples. All samples may not originate
+ * from a memory access instruction and require additional filtering.
+ */
static plat_event_config_t s_zen_ll = {
- PERF_TYPE_RAW, 0, 0, 0, 0, 0, "Unsupported"
+ 0, 0x0000000000000000, 0, 0, LL_THRESH * 10, 0, "IbsOpCntCycles"
};
void
@@ -57,10 +67,33 @@ zen_profiling_config(perf_count_id_t perf_count_id, plat_event_config_t *cfg)
plat_config_get(perf_count_id, cfg, s_zen_config);
}
+static int
+zen_ibs_op_pmu_type(void)
+{
+ int fd, type, i;
+ char buf[32];
+
+ if ((fd = open(IBS_OP_PMU_TYPE_PATH, O_RDONLY)) < 0)
+ return (-1);
+
+ if ((i = read(fd, buf, sizeof (buf) - 1)) <= 0) {
+ close(fd);
+ return (-1);
+ }
+
+ close(fd);
+ buf[i] = 0;
+ if ((type = atoi(buf)) == 0)
+ return (-1);
+
+ return (type);
+}
+
void
zen_ll_config(plat_event_config_t *cfg)
{
memcpy(cfg, &s_zen_ll, sizeof (plat_event_config_t));
+ cfg->type = zen_ibs_op_pmu_type();
}
int
--
2.31.1