^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 <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <stdint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "util/debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <subcmd/parse-options.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "util/perf_regs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "util/parse-regs-options.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) __parse_regs(const struct option *opt, const char *str, int unset, bool intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) uint64_t *mode = (uint64_t *)opt->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) const struct sample_reg *r = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) char *s, *os = NULL, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) uint64_t mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * cannot set it twice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (*mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (intr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) mask = arch__intr_reg_mask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mask = arch__user_reg_mask();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* str may be NULL in case no arg is passed to -I */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (str) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* because str is read-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) s = os = strdup(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) p = strchr(s, ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!strcmp(s, "?")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) fprintf(stderr, "available registers: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifdef HAVE_PERF_REGS_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) for (r = sample_reg_masks; r->name; r++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (r->mask & mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) fprintf(stderr, "%s ", r->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) fputc('\n', stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* just printing available regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #ifdef HAVE_PERF_REGS_SUPPORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) for (r = sample_reg_masks; r->name; r++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if ((r->mask & mask) && !strcasecmp(s, r->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!r || !r->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) s, intr ? "-I" : "--user-regs=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *mode |= r->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) s = p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* default to all possible regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (*mode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *mode = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) free(os);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) parse_user_regs(const struct option *opt, const char *str, int unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return __parse_regs(opt, str, unset, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) parse_intr_regs(const struct option *opt, const char *str, int unset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return __parse_regs(opt, str, unset, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }