^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <api/fs/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "map_symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "mem-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "symbol.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) unsigned int perf_mem_events__loads_ldlat = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #undef E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #undef E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static char mem_loads_name[100];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static bool mem_loads_name__init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) char * __weak perf_mem_events__name(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (i == PERF_MEM_EVENTS__LOAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!mem_loads_name__init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) mem_loads_name__init = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) scnprintf(mem_loads_name, sizeof(mem_loads_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) perf_mem_events[i].name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) perf_mem_events__loads_ldlat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return mem_loads_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return (char *)perf_mem_events[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int perf_mem_events__parse(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) char *tok, *saveptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* We need buffer that we know we can write to. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) buf = malloc(strlen(str) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) strcpy(buf, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) tok = strtok_r((char *)buf, ",", &saveptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) while (tok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct perf_mem_event *e = &perf_mem_events[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (strstr(e->tag, tok))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) e->record = found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) tok = strtok_r(NULL, ",", &saveptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) free(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int perf_mem_events__init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) const char *mnt = sysfs__mount();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!mnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) char path[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct perf_mem_event *e = &perf_mem_events[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mnt, e->sysfs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (!stat(path, &st))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) e->supported = found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return found ? 0 : -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void perf_mem_events__list(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct perf_mem_event *e = &perf_mem_events[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) fprintf(stderr, "%-13s%-*s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) e->tag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) verbose > 0 ? 25 : 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) verbose > 0 ? perf_mem_events__name(j) : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) e->supported ? ": available" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static const char * const tlb_access[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "N/A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) "HIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) "MISS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "L1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "L2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "Walker",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) "Fault",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) size_t l = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) u64 m = PERF_MEM_TLB_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u64 hit, miss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) sz -= 1; /* -1 for null termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) out[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) m = mem_info->data_src.mem_dtlb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) hit = m & PERF_MEM_TLB_HIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) miss = m & PERF_MEM_TLB_MISS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* already taken care of */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!(m & 0x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) strcat(out, " or ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) l += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) l += scnprintf(out + l, sz - l, tlb_access[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (*out == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) l += scnprintf(out, sz - l, "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (hit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) l += scnprintf(out + l, sz - l, " hit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (miss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) l += scnprintf(out + l, sz - l, " miss");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static const char * const mem_lvl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) "N/A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) "HIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "MISS",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) "L1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) "LFB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "L2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "L3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) "Local RAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) "Remote RAM (1 hop)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) "Remote RAM (2 hops)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) "Remote Cache (1 hop)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) "Remote Cache (2 hops)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) "I/O",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) "Uncached",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static const char * const mem_lvlnum[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) [PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) [PERF_MEM_LVLNUM_LFB] = "LFB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) [PERF_MEM_LVLNUM_RAM] = "RAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) [PERF_MEM_LVLNUM_PMEM] = "PMEM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) [PERF_MEM_LVLNUM_NA] = "N/A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) size_t i, l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u64 m = PERF_MEM_LVL_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u64 hit, miss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int printed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) m = mem_info->data_src.mem_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) sz -= 1; /* -1 for null termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) out[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) hit = m & PERF_MEM_LVL_HIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) miss = m & PERF_MEM_LVL_MISS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* already taken care of */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (mem_info && mem_info->data_src.mem_remote) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) strcat(out, "Remote ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) l += 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) printed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!(m & 0x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (printed++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) strcat(out, " or ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) l += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) l += scnprintf(out + l, sz - l, mem_lvl[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (mem_info && mem_info->data_src.mem_lvl_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int lvl = mem_info->data_src.mem_lvl_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (printed++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) strcat(out, " or ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) l += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (mem_lvlnum[lvl])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) l += scnprintf(out + l, sz - l, "L%d", lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (l == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) l += scnprintf(out + l, sz - l, "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (hit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) l += scnprintf(out + l, sz - l, " hit");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (miss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) l += scnprintf(out + l, sz - l, " miss");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static const char * const snoop_access[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) "N/A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) "None",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) "Hit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) "Miss",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) "HitM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) size_t i, l = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) u64 m = PERF_MEM_SNOOP_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) sz -= 1; /* -1 for null termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) out[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) m = mem_info->data_src.mem_snoop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!(m & 0x1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) strcat(out, " or ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) l += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) l += scnprintf(out + l, sz - l, snoop_access[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (mem_info &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) (mem_info->data_src.mem_snoopx & PERF_MEM_SNOOPX_FWD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (l) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) strcat(out, " or ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) l += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) l += scnprintf(out + l, sz - l, "Fwd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (*out == '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) l += scnprintf(out, sz - l, "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) u64 mask = PERF_MEM_LOCK_NA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mask = mem_info->data_src.mem_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (mask & PERF_MEM_LOCK_NA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) l = scnprintf(out, sz, "N/A");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) else if (mask & PERF_MEM_LOCK_LOCKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) l = scnprintf(out, sz, "Yes");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) l = scnprintf(out, sz, "No");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) i += perf_mem__lvl_scnprintf(out, sz, mem_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) i += scnprintf(out + i, sz - i, "|SNP ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) i += scnprintf(out + i, sz - i, "|TLB ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) i += scnprintf(out + i, sz - i, "|LCK ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) union perf_mem_data_src *data_src = &mi->data_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) u64 daddr = mi->daddr.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u64 op = data_src->mem_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u64 lvl = data_src->mem_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) u64 snoop = data_src->mem_snoop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u64 lock = data_src->mem_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Skylake might report unknown remote level via this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * bit, consider it when evaluating remote HITMs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) bool mrem = data_src->mem_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #define HITM_INC(__f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) stats->__f++; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) stats->tot_hitm++; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #define P(a, b) PERF_MEM_##a##_##b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) stats->nr_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (lock & P(LOCK, LOCKED)) stats->locks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (op & P(OP, LOAD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* load */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) stats->load++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!daddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) stats->ld_noadrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (lvl & P(LVL, HIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (lvl & P(LVL, UNC)) stats->ld_uncache++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (lvl & P(LVL, IO)) stats->ld_io++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (lvl & P(LVL, LFB)) stats->ld_fbhit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (lvl & P(LVL, L1 )) stats->ld_l1hit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (lvl & P(LVL, L2 )) stats->ld_l2hit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (lvl & P(LVL, L3 )) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (snoop & P(SNOOP, HITM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) HITM_INC(lcl_hitm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) stats->ld_llchit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (lvl & P(LVL, LOC_RAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) stats->lcl_dram++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (snoop & P(SNOOP, HIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) stats->ld_shared++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) stats->ld_excl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if ((lvl & P(LVL, REM_RAM1)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) (lvl & P(LVL, REM_RAM2)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) mrem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) stats->rmt_dram++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (snoop & P(SNOOP, HIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) stats->ld_shared++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) stats->ld_excl++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if ((lvl & P(LVL, REM_CCE1)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) (lvl & P(LVL, REM_CCE2)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mrem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (snoop & P(SNOOP, HIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) stats->rmt_hit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) else if (snoop & P(SNOOP, HITM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) HITM_INC(rmt_hitm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if ((lvl & P(LVL, MISS)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) stats->ld_miss++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) } else if (op & P(OP, STORE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* store */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) stats->store++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (!daddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) stats->st_noadrs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (lvl & P(LVL, HIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (lvl & P(LVL, UNC)) stats->st_uncache++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (lvl & P(LVL, L1 )) stats->st_l1hit++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (lvl & P(LVL, MISS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (lvl & P(LVL, L1)) stats->st_l1miss++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* unparsable data_src? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) stats->noparse++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (!mi->daddr.ms.map || !mi->iaddr.ms.map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) stats->nomap++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #undef P
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) #undef HITM_INC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) stats->nr_entries += add->nr_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) stats->locks += add->locks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) stats->store += add->store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) stats->st_uncache += add->st_uncache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) stats->st_noadrs += add->st_noadrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) stats->st_l1hit += add->st_l1hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) stats->st_l1miss += add->st_l1miss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) stats->load += add->load;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) stats->ld_excl += add->ld_excl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) stats->ld_shared += add->ld_shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) stats->ld_uncache += add->ld_uncache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) stats->ld_io += add->ld_io;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) stats->ld_miss += add->ld_miss;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) stats->ld_noadrs += add->ld_noadrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) stats->ld_fbhit += add->ld_fbhit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) stats->ld_l1hit += add->ld_l1hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) stats->ld_l2hit += add->ld_l2hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) stats->ld_llchit += add->ld_llchit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) stats->lcl_hitm += add->lcl_hitm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) stats->rmt_hitm += add->rmt_hitm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) stats->tot_hitm += add->tot_hitm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) stats->rmt_hit += add->rmt_hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) stats->lcl_dram += add->lcl_dram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) stats->rmt_dram += add->rmt_dram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) stats->nomap += add->nomap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) stats->noparse += add->noparse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }