cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hists_common.c (5265B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <inttypes.h>
      3#include "util/debug.h"
      4#include "util/dso.h"
      5#include "util/event.h" // struct perf_sample
      6#include "util/map.h"
      7#include "util/symbol.h"
      8#include "util/sort.h"
      9#include "util/evsel.h"
     10#include "util/machine.h"
     11#include "util/thread.h"
     12#include "tests/hists_common.h"
     13#include <linux/kernel.h>
     14#include <linux/perf_event.h>
     15
     16static struct {
     17	u32 pid;
     18	const char *comm;
     19} fake_threads[] = {
     20	{ FAKE_PID_PERF1, "perf" },
     21	{ FAKE_PID_PERF2, "perf" },
     22	{ FAKE_PID_BASH,  "bash" },
     23};
     24
     25static struct {
     26	u32 pid;
     27	u64 start;
     28	const char *filename;
     29} fake_mmap_info[] = {
     30	{ FAKE_PID_PERF1, FAKE_MAP_PERF,   "perf" },
     31	{ FAKE_PID_PERF1, FAKE_MAP_LIBC,   "libc" },
     32	{ FAKE_PID_PERF1, FAKE_MAP_KERNEL, "[kernel]" },
     33	{ FAKE_PID_PERF2, FAKE_MAP_PERF,   "perf" },
     34	{ FAKE_PID_PERF2, FAKE_MAP_LIBC,   "libc" },
     35	{ FAKE_PID_PERF2, FAKE_MAP_KERNEL, "[kernel]" },
     36	{ FAKE_PID_BASH,  FAKE_MAP_BASH,   "bash" },
     37	{ FAKE_PID_BASH,  FAKE_MAP_LIBC,   "libc" },
     38	{ FAKE_PID_BASH,  FAKE_MAP_KERNEL, "[kernel]" },
     39};
     40
     41struct fake_sym {
     42	u64 start;
     43	u64 length;
     44	const char *name;
     45};
     46
     47static struct fake_sym perf_syms[] = {
     48	{ FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "main" },
     49	{ FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "run_command" },
     50	{ FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "cmd_record" },
     51};
     52
     53static struct fake_sym bash_syms[] = {
     54	{ FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "main" },
     55	{ FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "xmalloc" },
     56	{ FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "xfree" },
     57};
     58
     59static struct fake_sym libc_syms[] = {
     60	{ 700, 100, "malloc" },
     61	{ 800, 100, "free" },
     62	{ 900, 100, "realloc" },
     63	{ FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "malloc" },
     64	{ FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "free" },
     65	{ FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "realloc" },
     66};
     67
     68static struct fake_sym kernel_syms[] = {
     69	{ FAKE_SYM_OFFSET1, FAKE_SYM_LENGTH, "schedule" },
     70	{ FAKE_SYM_OFFSET2, FAKE_SYM_LENGTH, "page_fault" },
     71	{ FAKE_SYM_OFFSET3, FAKE_SYM_LENGTH, "sys_perf_event_open" },
     72};
     73
     74static struct {
     75	const char *dso_name;
     76	struct fake_sym *syms;
     77	size_t nr_syms;
     78} fake_symbols[] = {
     79	{ "perf", perf_syms, ARRAY_SIZE(perf_syms) },
     80	{ "bash", bash_syms, ARRAY_SIZE(bash_syms) },
     81	{ "libc", libc_syms, ARRAY_SIZE(libc_syms) },
     82	{ "[kernel]", kernel_syms, ARRAY_SIZE(kernel_syms) },
     83};
     84
     85struct machine *setup_fake_machine(struct machines *machines)
     86{
     87	struct machine *machine = machines__find(machines, HOST_KERNEL_ID);
     88	size_t i;
     89
     90	if (machine == NULL) {
     91		pr_debug("Not enough memory for machine setup\n");
     92		return NULL;
     93	}
     94
     95	for (i = 0; i < ARRAY_SIZE(fake_threads); i++) {
     96		struct thread *thread;
     97
     98		thread = machine__findnew_thread(machine, fake_threads[i].pid,
     99						 fake_threads[i].pid);
    100		if (thread == NULL)
    101			goto out;
    102
    103		thread__set_comm(thread, fake_threads[i].comm, 0);
    104		thread__put(thread);
    105	}
    106
    107	for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
    108		struct perf_sample sample = {
    109			.cpumode = PERF_RECORD_MISC_USER,
    110		};
    111		union perf_event fake_mmap_event = {
    112			.mmap = {
    113				.pid = fake_mmap_info[i].pid,
    114				.tid = fake_mmap_info[i].pid,
    115				.start = fake_mmap_info[i].start,
    116				.len = FAKE_MAP_LENGTH,
    117				.pgoff = 0ULL,
    118			},
    119		};
    120
    121		strcpy(fake_mmap_event.mmap.filename,
    122		       fake_mmap_info[i].filename);
    123
    124		machine__process_mmap_event(machine, &fake_mmap_event, &sample);
    125	}
    126
    127	for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
    128		size_t k;
    129		struct dso *dso;
    130
    131		dso = machine__findnew_dso(machine, fake_symbols[i].dso_name);
    132		if (dso == NULL)
    133			goto out;
    134
    135		/* emulate dso__load() */
    136		dso__set_loaded(dso);
    137
    138		for (k = 0; k < fake_symbols[i].nr_syms; k++) {
    139			struct symbol *sym;
    140			struct fake_sym *fsym = &fake_symbols[i].syms[k];
    141
    142			sym = symbol__new(fsym->start, fsym->length,
    143					  STB_GLOBAL, STT_FUNC, fsym->name);
    144			if (sym == NULL) {
    145				dso__put(dso);
    146				goto out;
    147			}
    148
    149			symbols__insert(&dso->symbols, sym);
    150		}
    151
    152		dso__put(dso);
    153	}
    154
    155	return machine;
    156
    157out:
    158	pr_debug("Not enough memory for machine setup\n");
    159	machine__delete_threads(machine);
    160	return NULL;
    161}
    162
    163void print_hists_in(struct hists *hists)
    164{
    165	int i = 0;
    166	struct rb_root_cached *root;
    167	struct rb_node *node;
    168
    169	if (hists__has(hists, need_collapse))
    170		root = &hists->entries_collapsed;
    171	else
    172		root = hists->entries_in;
    173
    174	pr_info("----- %s --------\n", __func__);
    175	node = rb_first_cached(root);
    176	while (node) {
    177		struct hist_entry *he;
    178
    179		he = rb_entry(node, struct hist_entry, rb_node_in);
    180
    181		if (!he->filtered) {
    182			pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
    183				i, thread__comm_str(he->thread),
    184				he->ms.map->dso->short_name,
    185				he->ms.sym->name, he->stat.period);
    186		}
    187
    188		i++;
    189		node = rb_next(node);
    190	}
    191}
    192
    193void print_hists_out(struct hists *hists)
    194{
    195	int i = 0;
    196	struct rb_root_cached *root;
    197	struct rb_node *node;
    198
    199	root = &hists->entries;
    200
    201	pr_info("----- %s --------\n", __func__);
    202	node = rb_first_cached(root);
    203	while (node) {
    204		struct hist_entry *he;
    205
    206		he = rb_entry(node, struct hist_entry, rb_node);
    207
    208		if (!he->filtered) {
    209			pr_info("%2d: entry: %8s:%5d [%-8s] %20s: period = %"PRIu64"/%"PRIu64"\n",
    210				i, thread__comm_str(he->thread), he->thread->tid,
    211				he->ms.map->dso->short_name,
    212				he->ms.sym->name, he->stat.period,
    213				he->stat_acc ? he->stat_acc->period : 0);
    214		}
    215
    216		i++;
    217		node = rb_next(node);
    218	}
    219}