From aefc85d7b956c4df998afb4cfe5c413e5fd5b062 Mon Sep 17 00:00:00 2001 From: Sandipan Das 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 --- 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 #include +#include #include +#include #include #include #include @@ -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