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