Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
5752c20
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
accounting
arch
bootconfig
bpf
build
certs
cgroup
counter
debugging
edid
firewire
firmware
gpio
hv
iio
include
io_uring
kvm
laptop
leds
lib
memory-model
mm
net
objtool
pci
pcmcia
perf
Documentation
arch
bench
dlfilters
examples
include
jvmti
pmu-events
python
scripts
tests
trace
ui
util
arm-spe-decoder
bpf_skel
c++
cs-etm-decoder
hisi-ptt-decoder
include
intel-pt-decoder
libunwind
scripting-engines
Build
PERF-VERSION-GEN
addr_location.c
addr_location.h
affinity.c
affinity.h
amd-sample-raw.c
annotate.c
annotate.h
archinsn.h
arm-spe.c
arm-spe.h
arm64-frame-pointer-unwind-support.c
arm64-frame-pointer-unwind-support.h
auxtrace.c
auxtrace.h
block-info.c
block-info.h
block-range.c
block-range.h
bpf-event.c
bpf-event.h
bpf-filter.c
bpf-filter.h
bpf-filter.l
bpf-filter.y
bpf-loader.c
bpf-loader.h
bpf-prologue.c
bpf-prologue.h
bpf-utils.c
bpf-utils.h
bpf_counter.c
bpf_counter.h
bpf_counter_cgroup.c
bpf_ftrace.c
bpf_kwork.c
bpf_lock_contention.c
bpf_map.c
bpf_map.h
bpf_off_cpu.c
branch.c
branch.h
build-id.c
build-id.h
cache.h
cacheline.c
cacheline.h
call-path.c
call-path.h
callchain.c
callchain.h
cap.c
cap.h
cgroup.c
cgroup.h
clockid.c
clockid.h
cloexec.c
cloexec.h
color.c
color.h
color_config.c
comm.c
comm.h
compress.h
config.c
config.h
copyfile.c
copyfile.h
counts.c
counts.h
cpu-set-sched.h
cpumap.c
cpumap.h
cputopo.c
cputopo.h
cs-etm-base.c
cs-etm.c
cs-etm.h
data-convert-bt.c
data-convert-json.c
data-convert.h
data.c
data.h
db-export.c
db-export.h
debug.c
debug.h
demangle-cxx.cpp
demangle-cxx.h
demangle-java.c
demangle-java.h
demangle-ocaml.c
demangle-ocaml.h
demangle-rust.c
demangle-rust.h
dlfilter.c
dlfilter.h
dso.c
dso.h
dsos.c
dsos.h
dump-insn.c
dump-insn.h
dwarf-aux.c
dwarf-aux.h
dwarf-regs.c
env.c
env.h
event.c
event.h
events_stats.h
evlist.c
evlist.h
evsel.c
evsel.h
evsel_config.h
evsel_fprintf.c
evsel_fprintf.h
evswitch.c
evswitch.h
expr.c
expr.h
expr.l
expr.y
find-map.c
fncache.c
fncache.h
ftrace.h
genelf.c
genelf.h
genelf_debug.c
generate-cmdlist.sh
get_current_dir_name.c
get_current_dir_name.h
hashmap.c
hashmap.h
header.c
header.h
help-unknown-cmd.c
help-unknown-cmd.h
hisi-ptt.c
hisi-ptt.h
hist.c
hist.h
intel-bts.c
intel-bts.h
intel-pt.c
intel-pt.h
intlist.c
intlist.h
iostat.c
iostat.h
jit.h
jitdump.c
jitdump.h
kvm-stat.h
kwork.h
levenshtein.c
levenshtein.h
llvm-utils.c
llvm-utils.h
lock-contention.h
lzma.c
machine.c
machine.h
map.c
map.h
map_symbol.h
maps.c
maps.h
mem-events.c
mem-events.h
mem2node.c
mem2node.h
memswap.c
memswap.h
metricgroup.c
metricgroup.h
mmap.c
mmap.h
mutex.c
mutex.h
namespaces.c
namespaces.h
off_cpu.h
ordered-events.c
ordered-events.h
parse-branch-options.c
parse-branch-options.h
parse-events.c
parse-events.h
parse-events.l
parse-events.y
parse-regs-options.c
parse-regs-options.h
parse-sublevel-options.c
parse-sublevel-options.h
path.c
path.h
perf-hooks-list.h
perf-hooks.c
perf-hooks.h
perf_api_probe.c
perf_api_probe.h
perf_event_attr_fprintf.c
perf_regs.c
perf_regs.h
pfm.c
pfm.h
pmu.c
pmu.h
pmu.l
pmu.y
pmus.c
pmus.h
print-events.c
print-events.h
print_binary.c
print_binary.h
probe-event.c
probe-event.h
probe-file.c
probe-file.h
probe-finder.c
probe-finder.h
pstack.c
pstack.h
python-ext-sources
python.c
rb_resort.h
rblist.c
rblist.h
record.c
record.h
rlimit.c
rlimit.h
rwsem.c
rwsem.h
s390-cpumcf-kernel.h
s390-cpumsf-kernel.h
s390-cpumsf.c
s390-cpumsf.h
s390-sample-raw.c
sample-raw.c
sample-raw.h
sample.h
session.c
session.h
setns.c
setup.py
sideband_evlist.c
smt.c
smt.h
sort.c
sort.h
spark.c
spark.h
srccode.c
srccode.h
srcline.c
srcline.h
stat-display.c
stat-shadow.c
stat.c
stat.h
strbuf.c
strbuf.h
stream.c
stream.h
strfilter.c
strfilter.h
string.c
string2.h
strlist.c
strlist.h
svghelper.c
svghelper.h
symbol-elf.c
symbol-minimal.c
symbol.c
symbol.h
symbol_conf.h
symbol_fprintf.c
symsrc.h
synthetic-events.c
synthetic-events.h
syscalltbl.c
syscalltbl.h
target.c
target.h
term.c
term.h
thread-stack.c
thread-stack.h
thread.c
thread.h
thread_map.c
thread_map.h
time-utils.c
time-utils.h
tool.h
top.c
top.h
topdown.c
topdown.h
trace-event-info.c
trace-event-parse.c
trace-event-read.c
trace-event-scripting.c
trace-event.c
trace-event.h
tracepoint.c
tracepoint.h
trigger.h
tsc.c
tsc.h
units.c
units.h
unwind-libdw.c
unwind-libdw.h
unwind-libunwind-local.c
unwind-libunwind.c
unwind.h
usage.c
util.c
util.h
values.c
values.h
vdso.c
vdso.h
zlib.c
zstd.c
.gitignore
Build
CREDITS
MANIFEST
Makefile
Makefile.config
Makefile.perf
builtin-annotate.c
builtin-bench.c
builtin-buildid-cache.c
builtin-buildid-list.c
builtin-c2c.c
builtin-config.c
builtin-daemon.c
builtin-data.c
builtin-diff.c
builtin-evlist.c
builtin-ftrace.c
builtin-help.c
builtin-inject.c
builtin-kallsyms.c
builtin-kmem.c
builtin-kvm.c
builtin-kwork.c
builtin-list.c
builtin-lock.c
builtin-mem.c
builtin-probe.c
builtin-record.c
builtin-report.c
builtin-sched.c
builtin-script.c
builtin-stat.c
builtin-timechart.c
builtin-top.c
builtin-trace.c
builtin-version.c
builtin.h
check-headers.sh
command-list.txt
design.txt
perf-archive.sh
perf-completion.sh
perf-iostat.sh
perf-read-vdso.c
perf-sys.h
perf.c
perf.h
power
rcu
scripts
spi
testing
thermal
time
tracing
usb
verification
virtio
wmi
Makefile
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
perf
/
util
/
mem-events.c
Copy path
Blame
Blame
Latest commit
Ravi Bangoria
and
Arnaldo Carvalho de Melo
perf mem: Scan all PMUs instead of just core ones
Jun 16, 2023
5752c20
·
Jun 16, 2023
History
History
703 lines (585 loc) · 14.9 KB
Breadcrumbs
linux
/
tools
/
perf
/
util
/
mem-events.c
Top
File metadata and controls
Code
Blame
703 lines (585 loc) · 14.9 KB
Raw
// SPDX-License-Identifier: GPL-2.0 #include <stddef.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <api/fs/fs.h> #include <linux/kernel.h> #include "map_symbol.h" #include "mem-events.h" #include "debug.h" #include "symbol.h" #include "pmu.h" #include "pmus.h" unsigned int perf_mem_events__loads_ldlat = 30; #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s } static struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "cpu/events/mem-loads"), E("ldlat-stores", "cpu/mem-stores/P", "cpu/events/mem-stores"), E(NULL, NULL, NULL), }; #undef E static char mem_loads_name[100]; static bool mem_loads_name__init; struct perf_mem_event * __weak perf_mem_events__ptr(int i) { if (i >= PERF_MEM_EVENTS__MAX) return NULL; return &perf_mem_events[i]; } char * __weak perf_mem_events__name(int i, char *pmu_name __maybe_unused) { struct perf_mem_event *e = perf_mem_events__ptr(i); if (!e) return NULL; if (i == PERF_MEM_EVENTS__LOAD) { if (!mem_loads_name__init) { mem_loads_name__init = true; scnprintf(mem_loads_name, sizeof(mem_loads_name), e->name, perf_mem_events__loads_ldlat); } return mem_loads_name; } return (char *)e->name; } __weak bool is_mem_loads_aux_event(struct evsel *leader __maybe_unused) { return false; } int perf_mem_events__parse(const char *str) { char *tok, *saveptr = NULL; bool found = false; char *buf; int j; /* We need buffer that we know we can write to. */ buf = malloc(strlen(str) + 1); if (!buf) return -ENOMEM; strcpy(buf, str); tok = strtok_r((char *)buf, ",", &saveptr); while (tok) { for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { struct perf_mem_event *e = perf_mem_events__ptr(j); if (!e->tag) continue; if (strstr(e->tag, tok)) e->record = found = true; } tok = strtok_r(NULL, ",", &saveptr); } free(buf); if (found) return 0; pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str); return -1; } static bool perf_mem_event__supported(const char *mnt, char *sysfs_name) { char path[PATH_MAX]; struct stat st; scnprintf(path, PATH_MAX, "%s/devices/%s", mnt, sysfs_name); return !stat(path, &st); } int perf_mem_events__init(void) { const char *mnt = sysfs__mount(); bool found = false; int j; if (!mnt) return -ENOENT; for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { struct perf_mem_event *e = perf_mem_events__ptr(j); char sysfs_name[100]; struct perf_pmu *pmu = NULL; /* * If the event entry isn't valid, skip initialization * and "e->supported" will keep false. */ if (!e->tag) continue; /* * Scan all PMUs not just core ones, since perf mem/c2c on * platforms like AMD uses IBS OP PMU which is independent * of core PMU. */ while ((pmu = perf_pmus__scan(pmu)) != NULL) { scnprintf(sysfs_name, sizeof(sysfs_name), e->sysfs_name, pmu->name); e->supported |= perf_mem_event__supported(mnt, sysfs_name); } if (e->supported) found = true; } return found ? 0 : -ENOENT; } void perf_mem_events__list(void) { int j; for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { struct perf_mem_event *e = perf_mem_events__ptr(j); fprintf(stderr, "%-*s%-*s%s", e->tag ? 13 : 0, e->tag ? : "", e->tag && verbose > 0 ? 25 : 0, e->tag && verbose > 0 ? perf_mem_events__name(j, NULL) : "", e->supported ? ": available\n" : ""); } } static void perf_mem_events__print_unsupport_hybrid(struct perf_mem_event *e, int idx) { const char *mnt = sysfs__mount(); char sysfs_name[100]; struct perf_pmu *pmu = NULL; while ((pmu = perf_pmus__scan(pmu)) != NULL) { scnprintf(sysfs_name, sizeof(sysfs_name), e->sysfs_name, pmu->name); if (!perf_mem_event__supported(mnt, sysfs_name)) { pr_err("failed: event '%s' not supported\n", perf_mem_events__name(idx, pmu->name)); } } } int perf_mem_events__record_args(const char **rec_argv, int *argv_nr, char **rec_tmp, int *tmp_nr) { int i = *argv_nr, k = 0; struct perf_mem_event *e; struct perf_pmu *pmu; char *s; for (int j = 0; j < PERF_MEM_EVENTS__MAX; j++) { e = perf_mem_events__ptr(j); if (!e->record) continue; if (perf_pmus__num_mem_pmus() == 1) { if (!e->supported) { pr_err("failed: event '%s' not supported\n", perf_mem_events__name(j, NULL)); return -1; } rec_argv[i++] = "-e"; rec_argv[i++] = perf_mem_events__name(j, NULL); } else { if (!e->supported) { perf_mem_events__print_unsupport_hybrid(e, j); return -1; } while ((pmu = perf_pmus__scan(pmu)) != NULL) { rec_argv[i++] = "-e"; s = perf_mem_events__name(j, pmu->name); if (s) { s = strdup(s); if (!s) return -1; rec_argv[i++] = s; rec_tmp[k++] = s; } } } } *argv_nr = i; *tmp_nr = k; return 0; } static const char * const tlb_access[] = { "N/A", "HIT", "MISS", "L1", "L2", "Walker", "Fault", }; int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { size_t l = 0, i; u64 m = PERF_MEM_TLB_NA; u64 hit, miss; sz -= 1; /* -1 for null termination */ out[0] = '\0'; if (mem_info) m = mem_info->data_src.mem_dtlb; hit = m & PERF_MEM_TLB_HIT; miss = m & PERF_MEM_TLB_MISS; /* already taken care of */ m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS); for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) { if (!(m & 0x1)) continue; if (l) { strcat(out, " or "); l += 4; } l += scnprintf(out + l, sz - l, tlb_access[i]); } if (*out == '\0') l += scnprintf(out, sz - l, "N/A"); if (hit) l += scnprintf(out + l, sz - l, " hit"); if (miss) l += scnprintf(out + l, sz - l, " miss"); return l; } static const char * const mem_lvl[] = { "N/A", "HIT", "MISS", "L1", "LFB/MAB", "L2", "L3", "Local RAM", "Remote RAM (1 hop)", "Remote RAM (2 hops)", "Remote Cache (1 hop)", "Remote Cache (2 hops)", "I/O", "Uncached", }; static const char * const mem_lvlnum[] = { [PERF_MEM_LVLNUM_UNC] = "Uncached", [PERF_MEM_LVLNUM_CXL] = "CXL", [PERF_MEM_LVLNUM_IO] = "I/O", [PERF_MEM_LVLNUM_ANY_CACHE] = "Any cache", [PERF_MEM_LVLNUM_LFB] = "LFB/MAB", [PERF_MEM_LVLNUM_RAM] = "RAM", [PERF_MEM_LVLNUM_PMEM] = "PMEM", [PERF_MEM_LVLNUM_NA] = "N/A", }; static const char * const mem_hops[] = { "N/A", /* * While printing, 'Remote' will be added to represent * 'Remote core, same node' accesses as remote field need * to be set with mem_hops field. */ "core, same node", "node, same socket", "socket, same board", "board", }; static int perf_mem__op_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { u64 op = PERF_MEM_LOCK_NA; int l; if (mem_info) op = mem_info->data_src.mem_op; if (op & PERF_MEM_OP_NA) l = scnprintf(out, sz, "N/A"); else if (op & PERF_MEM_OP_LOAD) l = scnprintf(out, sz, "LOAD"); else if (op & PERF_MEM_OP_STORE) l = scnprintf(out, sz, "STORE"); else if (op & PERF_MEM_OP_PFETCH) l = scnprintf(out, sz, "PFETCH"); else if (op & PERF_MEM_OP_EXEC) l = scnprintf(out, sz, "EXEC"); else l = scnprintf(out, sz, "No"); return l; } int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { union perf_mem_data_src data_src; int printed = 0; size_t l = 0; size_t i; int lvl; char hit_miss[5] = {0}; sz -= 1; /* -1 for null termination */ out[0] = '\0'; if (!mem_info) goto na; data_src = mem_info->data_src; if (data_src.mem_lvl & PERF_MEM_LVL_HIT) memcpy(hit_miss, "hit", 3); else if (data_src.mem_lvl & PERF_MEM_LVL_MISS) memcpy(hit_miss, "miss", 4); lvl = data_src.mem_lvl_num; if (lvl && lvl != PERF_MEM_LVLNUM_NA) { if (data_src.mem_remote) { strcat(out, "Remote "); l += 7; } if (data_src.mem_hops) l += scnprintf(out + l, sz - l, "%s ", mem_hops[data_src.mem_hops]); if (mem_lvlnum[lvl]) l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]); else l += scnprintf(out + l, sz - l, "L%d", lvl); l += scnprintf(out + l, sz - l, " %s", hit_miss); return l; } lvl = data_src.mem_lvl; if (!lvl) goto na; lvl &= ~(PERF_MEM_LVL_NA | PERF_MEM_LVL_HIT | PERF_MEM_LVL_MISS); if (!lvl) goto na; for (i = 0; lvl && i < ARRAY_SIZE(mem_lvl); i++, lvl >>= 1) { if (!(lvl & 0x1)) continue; if (printed++) { strcat(out, " or "); l += 4; } l += scnprintf(out + l, sz - l, mem_lvl[i]); } if (printed) { l += scnprintf(out + l, sz - l, " %s", hit_miss); return l; } na: strcat(out, "N/A"); return 3; } static const char * const snoop_access[] = { "N/A", "None", "Hit", "Miss", "HitM", }; static const char * const snoopx_access[] = { "Fwd", "Peer", }; int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { size_t i, l = 0; u64 m = PERF_MEM_SNOOP_NA; sz -= 1; /* -1 for null termination */ out[0] = '\0'; if (mem_info) m = mem_info->data_src.mem_snoop; for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) { if (!(m & 0x1)) continue; if (l) { strcat(out, " or "); l += 4; } l += scnprintf(out + l, sz - l, snoop_access[i]); } m = 0; if (mem_info) m = mem_info->data_src.mem_snoopx; for (i = 0; m && i < ARRAY_SIZE(snoopx_access); i++, m >>= 1) { if (!(m & 0x1)) continue; if (l) { strcat(out, " or "); l += 4; } l += scnprintf(out + l, sz - l, snoopx_access[i]); } if (*out == '\0') l += scnprintf(out, sz - l, "N/A"); return l; } int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { u64 mask = PERF_MEM_LOCK_NA; int l; if (mem_info) mask = mem_info->data_src.mem_lock; if (mask & PERF_MEM_LOCK_NA) l = scnprintf(out, sz, "N/A"); else if (mask & PERF_MEM_LOCK_LOCKED) l = scnprintf(out, sz, "Yes"); else l = scnprintf(out, sz, "No"); return l; } int perf_mem__blk_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { size_t l = 0; u64 mask = PERF_MEM_BLK_NA; sz -= 1; /* -1 for null termination */ out[0] = '\0'; if (mem_info) mask = mem_info->data_src.mem_blk; if (!mask || (mask & PERF_MEM_BLK_NA)) { l += scnprintf(out + l, sz - l, " N/A"); return l; } if (mask & PERF_MEM_BLK_DATA) l += scnprintf(out + l, sz - l, " Data"); if (mask & PERF_MEM_BLK_ADDR) l += scnprintf(out + l, sz - l, " Addr"); return l; } int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info) { int i = 0; i += scnprintf(out, sz, "|OP "); i += perf_mem__op_scnprintf(out + i, sz - i, mem_info); i += scnprintf(out + i, sz - i, "|LVL "); i += perf_mem__lvl_scnprintf(out + i, sz, mem_info); i += scnprintf(out + i, sz - i, "|SNP "); i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info); i += scnprintf(out + i, sz - i, "|TLB "); i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info); i += scnprintf(out + i, sz - i, "|LCK "); i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info); i += scnprintf(out + i, sz - i, "|BLK "); i += perf_mem__blk_scnprintf(out + i, sz - i, mem_info); return i; } int c2c_decode_stats(struct c2c_stats *stats, struct mem_info *mi) { union perf_mem_data_src *data_src = &mi->data_src; u64 daddr = mi->daddr.addr; u64 op = data_src->mem_op; u64 lvl = data_src->mem_lvl; u64 snoop = data_src->mem_snoop; u64 snoopx = data_src->mem_snoopx; u64 lock = data_src->mem_lock; u64 blk = data_src->mem_blk; /* * Skylake might report unknown remote level via this * bit, consider it when evaluating remote HITMs. * * Incase of power, remote field can also be used to denote cache * accesses from the another core of same node. Hence, setting * mrem only when HOPS is zero along with set remote field. */ bool mrem = (data_src->mem_remote && !data_src->mem_hops); int err = 0; #define HITM_INC(__f) \ do { \ stats->__f++; \ stats->tot_hitm++; \ } while (0) #define PEER_INC(__f) \ do { \ stats->__f++; \ stats->tot_peer++; \ } while (0) #define P(a, b) PERF_MEM_##a##_##b stats->nr_entries++; if (lock & P(LOCK, LOCKED)) stats->locks++; if (blk & P(BLK, DATA)) stats->blk_data++; if (blk & P(BLK, ADDR)) stats->blk_addr++; if (op & P(OP, LOAD)) { /* load */ stats->load++; if (!daddr) { stats->ld_noadrs++; return -1; } if (lvl & P(LVL, HIT)) { if (lvl & P(LVL, UNC)) stats->ld_uncache++; if (lvl & P(LVL, IO)) stats->ld_io++; if (lvl & P(LVL, LFB)) stats->ld_fbhit++; if (lvl & P(LVL, L1 )) stats->ld_l1hit++; if (lvl & P(LVL, L2)) { stats->ld_l2hit++; if (snoopx & P(SNOOPX, PEER)) PEER_INC(lcl_peer); } if (lvl & P(LVL, L3 )) { if (snoop & P(SNOOP, HITM)) HITM_INC(lcl_hitm); else stats->ld_llchit++; if (snoopx & P(SNOOPX, PEER)) PEER_INC(lcl_peer); } if (lvl & P(LVL, LOC_RAM)) { stats->lcl_dram++; if (snoop & P(SNOOP, HIT)) stats->ld_shared++; else stats->ld_excl++; } if ((lvl & P(LVL, REM_RAM1)) || (lvl & P(LVL, REM_RAM2)) || mrem) { stats->rmt_dram++; if (snoop & P(SNOOP, HIT)) stats->ld_shared++; else stats->ld_excl++; } } if ((lvl & P(LVL, REM_CCE1)) || (lvl & P(LVL, REM_CCE2)) || mrem) { if (snoop & P(SNOOP, HIT)) { stats->rmt_hit++; } else if (snoop & P(SNOOP, HITM)) { HITM_INC(rmt_hitm); } else if (snoopx & P(SNOOPX, PEER)) { stats->rmt_hit++; PEER_INC(rmt_peer); } } if ((lvl & P(LVL, MISS))) stats->ld_miss++; } else if (op & P(OP, STORE)) { /* store */ stats->store++; if (!daddr) { stats->st_noadrs++; return -1; } if (lvl & P(LVL, HIT)) { if (lvl & P(LVL, UNC)) stats->st_uncache++; if (lvl & P(LVL, L1 )) stats->st_l1hit++; } if (lvl & P(LVL, MISS)) if (lvl & P(LVL, L1)) stats->st_l1miss++; if (lvl & P(LVL, NA)) stats->st_na++; } else { /* unparsable data_src? */ stats->noparse++; return -1; } if (!mi->daddr.ms.map || !mi->iaddr.ms.map) { stats->nomap++; return -1; } #undef P #undef HITM_INC return err; } void c2c_add_stats(struct c2c_stats *stats, struct c2c_stats *add) { stats->nr_entries += add->nr_entries; stats->locks += add->locks; stats->store += add->store; stats->st_uncache += add->st_uncache; stats->st_noadrs += add->st_noadrs; stats->st_l1hit += add->st_l1hit; stats->st_l1miss += add->st_l1miss; stats->st_na += add->st_na; stats->load += add->load; stats->ld_excl += add->ld_excl; stats->ld_shared += add->ld_shared; stats->ld_uncache += add->ld_uncache; stats->ld_io += add->ld_io; stats->ld_miss += add->ld_miss; stats->ld_noadrs += add->ld_noadrs; stats->ld_fbhit += add->ld_fbhit; stats->ld_l1hit += add->ld_l1hit; stats->ld_l2hit += add->ld_l2hit; stats->ld_llchit += add->ld_llchit; stats->lcl_hitm += add->lcl_hitm; stats->rmt_hitm += add->rmt_hitm; stats->tot_hitm += add->tot_hitm; stats->lcl_peer += add->lcl_peer; stats->rmt_peer += add->rmt_peer; stats->tot_peer += add->tot_peer; stats->rmt_hit += add->rmt_hit; stats->lcl_dram += add->lcl_dram; stats->rmt_dram += add->rmt_dram; stats->blk_data += add->blk_data; stats->blk_addr += add->blk_addr; stats->nomap += add->nomap; stats->noparse += add->noparse; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
You can’t perform that action at this time.