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

parse-branch-options.c (2282B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "util/debug.h"
      3#include "util/event.h"
      4#include <subcmd/parse-options.h>
      5#include "util/parse-branch-options.h"
      6#include <stdlib.h>
      7#include <string.h>
      8
      9#define BRANCH_OPT(n, m) \
     10	{ .name = n, .mode = (m) }
     11
     12#define BRANCH_END { .name = NULL }
     13
     14struct branch_mode {
     15	const char *name;
     16	int mode;
     17};
     18
     19static const struct branch_mode branch_modes[] = {
     20	BRANCH_OPT("u", PERF_SAMPLE_BRANCH_USER),
     21	BRANCH_OPT("k", PERF_SAMPLE_BRANCH_KERNEL),
     22	BRANCH_OPT("hv", PERF_SAMPLE_BRANCH_HV),
     23	BRANCH_OPT("any", PERF_SAMPLE_BRANCH_ANY),
     24	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
     25	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
     26	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
     27	BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
     28	BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
     29	BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
     30	BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND),
     31	BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP),
     32	BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL),
     33	BRANCH_OPT("save_type", PERF_SAMPLE_BRANCH_TYPE_SAVE),
     34	BRANCH_OPT("stack", PERF_SAMPLE_BRANCH_CALL_STACK),
     35	BRANCH_END
     36};
     37
     38int parse_branch_str(const char *str, __u64 *mode)
     39{
     40#define ONLY_PLM \
     41	(PERF_SAMPLE_BRANCH_USER	|\
     42	 PERF_SAMPLE_BRANCH_KERNEL	|\
     43	 PERF_SAMPLE_BRANCH_HV)
     44
     45	int ret = 0;
     46	char *p, *s;
     47	char *os = NULL;
     48	const struct branch_mode *br;
     49
     50	if (str == NULL) {
     51		*mode = PERF_SAMPLE_BRANCH_ANY;
     52		return 0;
     53	}
     54
     55	/* because str is read-only */
     56	s = os = strdup(str);
     57	if (!s)
     58		return -1;
     59
     60	for (;;) {
     61		p = strchr(s, ',');
     62		if (p)
     63			*p = '\0';
     64
     65		for (br = branch_modes; br->name; br++) {
     66			if (!strcasecmp(s, br->name))
     67				break;
     68		}
     69		if (!br->name) {
     70			ret = -1;
     71			pr_warning("unknown branch filter %s,"
     72				    " check man page\n", s);
     73			goto error;
     74		}
     75
     76		*mode |= br->mode;
     77
     78		if (!p)
     79			break;
     80
     81		s = p + 1;
     82	}
     83
     84	/* default to any branch */
     85	if ((*mode & ~ONLY_PLM) == 0) {
     86		*mode = PERF_SAMPLE_BRANCH_ANY;
     87	}
     88error:
     89	free(os);
     90	return ret;
     91}
     92
     93int
     94parse_branch_stack(const struct option *opt, const char *str, int unset)
     95{
     96	__u64 *mode = (__u64 *)opt->value;
     97
     98	if (unset)
     99		return 0;
    100
    101	/*
    102	 * cannot set it twice, -b + --branch-filter for instance
    103	 */
    104	if (*mode)
    105		return -1;
    106
    107	return parse_branch_str(str, mode);
    108}