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

values.c (7922B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <inttypes.h>
      3#include <stdio.h>
      4#include <stdlib.h>
      5#include <string.h>
      6#include <errno.h>
      7#include <linux/zalloc.h>
      8
      9#include "values.h"
     10#include "debug.h"
     11
     12int perf_read_values_init(struct perf_read_values *values)
     13{
     14	values->threads_max = 16;
     15	values->pid = malloc(values->threads_max * sizeof(*values->pid));
     16	values->tid = malloc(values->threads_max * sizeof(*values->tid));
     17	values->value = zalloc(values->threads_max * sizeof(*values->value));
     18	if (!values->pid || !values->tid || !values->value) {
     19		pr_debug("failed to allocate read_values threads arrays");
     20		goto out_free_pid;
     21	}
     22	values->threads = 0;
     23
     24	values->counters_max = 16;
     25	values->counterrawid = malloc(values->counters_max
     26				      * sizeof(*values->counterrawid));
     27	values->countername = malloc(values->counters_max
     28				     * sizeof(*values->countername));
     29	if (!values->counterrawid || !values->countername) {
     30		pr_debug("failed to allocate read_values counters arrays");
     31		goto out_free_counter;
     32	}
     33	values->counters = 0;
     34
     35	return 0;
     36
     37out_free_counter:
     38	zfree(&values->counterrawid);
     39	zfree(&values->countername);
     40out_free_pid:
     41	zfree(&values->pid);
     42	zfree(&values->tid);
     43	zfree(&values->value);
     44	return -ENOMEM;
     45}
     46
     47void perf_read_values_destroy(struct perf_read_values *values)
     48{
     49	int i;
     50
     51	if (!values->threads_max || !values->counters_max)
     52		return;
     53
     54	for (i = 0; i < values->threads; i++)
     55		zfree(&values->value[i]);
     56	zfree(&values->value);
     57	zfree(&values->pid);
     58	zfree(&values->tid);
     59	zfree(&values->counterrawid);
     60	for (i = 0; i < values->counters; i++)
     61		zfree(&values->countername[i]);
     62	zfree(&values->countername);
     63}
     64
     65static int perf_read_values__enlarge_threads(struct perf_read_values *values)
     66{
     67	int nthreads_max = values->threads_max * 2;
     68	void *npid = realloc(values->pid, nthreads_max * sizeof(*values->pid)),
     69	     *ntid = realloc(values->tid, nthreads_max * sizeof(*values->tid)),
     70	     *nvalue = realloc(values->value, nthreads_max * sizeof(*values->value));
     71
     72	if (!npid || !ntid || !nvalue)
     73		goto out_err;
     74
     75	values->threads_max = nthreads_max;
     76	values->pid = npid;
     77	values->tid = ntid;
     78	values->value = nvalue;
     79	return 0;
     80out_err:
     81	free(npid);
     82	free(ntid);
     83	free(nvalue);
     84	pr_debug("failed to enlarge read_values threads arrays");
     85	return -ENOMEM;
     86}
     87
     88static int perf_read_values__findnew_thread(struct perf_read_values *values,
     89					    u32 pid, u32 tid)
     90{
     91	int i;
     92
     93	for (i = 0; i < values->threads; i++)
     94		if (values->pid[i] == pid && values->tid[i] == tid)
     95			return i;
     96
     97	if (values->threads == values->threads_max) {
     98		i = perf_read_values__enlarge_threads(values);
     99		if (i < 0)
    100			return i;
    101	}
    102
    103	i = values->threads;
    104
    105	values->value[i] = zalloc(values->counters_max * sizeof(**values->value));
    106	if (!values->value[i]) {
    107		pr_debug("failed to allocate read_values counters array");
    108		return -ENOMEM;
    109	}
    110	values->pid[i] = pid;
    111	values->tid[i] = tid;
    112	values->threads = i + 1;
    113
    114	return i;
    115}
    116
    117static int perf_read_values__enlarge_counters(struct perf_read_values *values)
    118{
    119	char **countername;
    120	int i, counters_max = values->counters_max * 2;
    121	u64 *counterrawid = realloc(values->counterrawid, counters_max * sizeof(*values->counterrawid));
    122
    123	if (!counterrawid) {
    124		pr_debug("failed to enlarge read_values rawid array");
    125		goto out_enomem;
    126	}
    127
    128	countername = realloc(values->countername, counters_max * sizeof(*values->countername));
    129	if (!countername) {
    130		pr_debug("failed to enlarge read_values rawid array");
    131		goto out_free_rawid;
    132	}
    133
    134	for (i = 0; i < values->threads; i++) {
    135		u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
    136		int j;
    137
    138		if (!value) {
    139			pr_debug("failed to enlarge read_values ->values array");
    140			goto out_free_name;
    141		}
    142
    143		for (j = values->counters_max; j < counters_max; j++)
    144			value[j] = 0;
    145
    146		values->value[i] = value;
    147	}
    148
    149	values->counters_max = counters_max;
    150	values->counterrawid = counterrawid;
    151	values->countername  = countername;
    152
    153	return 0;
    154out_free_name:
    155	free(countername);
    156out_free_rawid:
    157	free(counterrawid);
    158out_enomem:
    159	return -ENOMEM;
    160}
    161
    162static int perf_read_values__findnew_counter(struct perf_read_values *values,
    163					     u64 rawid, const char *name)
    164{
    165	int i;
    166
    167	for (i = 0; i < values->counters; i++)
    168		if (values->counterrawid[i] == rawid)
    169			return i;
    170
    171	if (values->counters == values->counters_max) {
    172		i = perf_read_values__enlarge_counters(values);
    173		if (i)
    174			return i;
    175	}
    176
    177	i = values->counters++;
    178	values->counterrawid[i] = rawid;
    179	values->countername[i] = strdup(name);
    180
    181	return i;
    182}
    183
    184int perf_read_values_add_value(struct perf_read_values *values,
    185				u32 pid, u32 tid,
    186				u64 rawid, const char *name, u64 value)
    187{
    188	int tindex, cindex;
    189
    190	tindex = perf_read_values__findnew_thread(values, pid, tid);
    191	if (tindex < 0)
    192		return tindex;
    193	cindex = perf_read_values__findnew_counter(values, rawid, name);
    194	if (cindex < 0)
    195		return cindex;
    196
    197	values->value[tindex][cindex] += value;
    198	return 0;
    199}
    200
    201static void perf_read_values__display_pretty(FILE *fp,
    202					     struct perf_read_values *values)
    203{
    204	int i, j;
    205	int pidwidth, tidwidth;
    206	int *counterwidth;
    207
    208	counterwidth = malloc(values->counters * sizeof(*counterwidth));
    209	if (!counterwidth) {
    210		fprintf(fp, "INTERNAL ERROR: Failed to allocate counterwidth array\n");
    211		return;
    212	}
    213	tidwidth = 3;
    214	pidwidth = 3;
    215	for (j = 0; j < values->counters; j++)
    216		counterwidth[j] = strlen(values->countername[j]);
    217	for (i = 0; i < values->threads; i++) {
    218		int width;
    219
    220		width = snprintf(NULL, 0, "%d", values->pid[i]);
    221		if (width > pidwidth)
    222			pidwidth = width;
    223		width = snprintf(NULL, 0, "%d", values->tid[i]);
    224		if (width > tidwidth)
    225			tidwidth = width;
    226		for (j = 0; j < values->counters; j++) {
    227			width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
    228			if (width > counterwidth[j])
    229				counterwidth[j] = width;
    230		}
    231	}
    232
    233	fprintf(fp, "# %*s  %*s", pidwidth, "PID", tidwidth, "TID");
    234	for (j = 0; j < values->counters; j++)
    235		fprintf(fp, "  %*s", counterwidth[j], values->countername[j]);
    236	fprintf(fp, "\n");
    237
    238	for (i = 0; i < values->threads; i++) {
    239		fprintf(fp, "  %*d  %*d", pidwidth, values->pid[i],
    240			tidwidth, values->tid[i]);
    241		for (j = 0; j < values->counters; j++)
    242			fprintf(fp, "  %*" PRIu64,
    243				counterwidth[j], values->value[i][j]);
    244		fprintf(fp, "\n");
    245	}
    246	free(counterwidth);
    247}
    248
    249static void perf_read_values__display_raw(FILE *fp,
    250					  struct perf_read_values *values)
    251{
    252	int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
    253	int i, j;
    254
    255	tidwidth = 3; /* TID */
    256	pidwidth = 3; /* PID */
    257	namewidth = 4; /* "Name" */
    258	rawwidth = 3; /* "Raw" */
    259	countwidth = 5; /* "Count" */
    260
    261	for (i = 0; i < values->threads; i++) {
    262		width = snprintf(NULL, 0, "%d", values->pid[i]);
    263		if (width > pidwidth)
    264			pidwidth = width;
    265		width = snprintf(NULL, 0, "%d", values->tid[i]);
    266		if (width > tidwidth)
    267			tidwidth = width;
    268	}
    269	for (j = 0; j < values->counters; j++) {
    270		width = strlen(values->countername[j]);
    271		if (width > namewidth)
    272			namewidth = width;
    273		width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
    274		if (width > rawwidth)
    275			rawwidth = width;
    276	}
    277	for (i = 0; i < values->threads; i++) {
    278		for (j = 0; j < values->counters; j++) {
    279			width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
    280			if (width > countwidth)
    281				countwidth = width;
    282		}
    283	}
    284
    285	fprintf(fp, "# %*s  %*s  %*s  %*s  %*s\n",
    286		pidwidth, "PID", tidwidth, "TID",
    287		namewidth, "Name", rawwidth, "Raw",
    288		countwidth, "Count");
    289	for (i = 0; i < values->threads; i++)
    290		for (j = 0; j < values->counters; j++)
    291			fprintf(fp, "  %*d  %*d  %*s  %*" PRIx64 "  %*" PRIu64,
    292				pidwidth, values->pid[i],
    293				tidwidth, values->tid[i],
    294				namewidth, values->countername[j],
    295				rawwidth, values->counterrawid[j],
    296				countwidth, values->value[i][j]);
    297}
    298
    299void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
    300{
    301	if (raw)
    302		perf_read_values__display_raw(fp, values);
    303	else
    304		perf_read_values__display_pretty(fp, values);
    305}