1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2215a0d30SArnaldo Carvalho de Melo #include <stdbool.h>
3215a0d30SArnaldo Carvalho de Melo #include <stdlib.h>
4215a0d30SArnaldo Carvalho de Melo #include <stdint.h>
5215a0d30SArnaldo Carvalho de Melo #include <string.h>
6215a0d30SArnaldo Carvalho de Melo #include <stdio.h>
7bcc84ec6SStephane Eranian #include "util/debug.h"
84b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
9215a0d30SArnaldo Carvalho de Melo #include "util/perf_regs.h"
10bcc84ec6SStephane Eranian #include "util/parse-regs-options.h"
11bcc84ec6SStephane Eranian
12aeea9062SKan Liang static int
__parse_regs(const struct option * opt,const char * str,int unset,bool intr)13aeea9062SKan Liang __parse_regs(const struct option *opt, const char *str, int unset, bool intr)
14bcc84ec6SStephane Eranian {
15bcc84ec6SStephane Eranian uint64_t *mode = (uint64_t *)opt->value;
1642466b9fSIan Rogers const struct sample_reg *r = NULL;
17bcc84ec6SStephane Eranian char *s, *os = NULL, *p;
18bcc84ec6SStephane Eranian int ret = -1;
19af785e75SKan Liang uint64_t mask;
20bcc84ec6SStephane Eranian
21bcc84ec6SStephane Eranian if (unset)
22bcc84ec6SStephane Eranian return 0;
23bcc84ec6SStephane Eranian
24bcc84ec6SStephane Eranian /*
25bcc84ec6SStephane Eranian * cannot set it twice
26bcc84ec6SStephane Eranian */
27bcc84ec6SStephane Eranian if (*mode)
28bcc84ec6SStephane Eranian return -1;
29bcc84ec6SStephane Eranian
30af785e75SKan Liang if (intr)
31af785e75SKan Liang mask = arch__intr_reg_mask();
32af785e75SKan Liang else
33af785e75SKan Liang mask = arch__user_reg_mask();
34af785e75SKan Liang
35bcc84ec6SStephane Eranian /* str may be NULL in case no arg is passed to -I */
36bcc84ec6SStephane Eranian if (str) {
37bcc84ec6SStephane Eranian /* because str is read-only */
38bcc84ec6SStephane Eranian s = os = strdup(str);
39bcc84ec6SStephane Eranian if (!s)
40bcc84ec6SStephane Eranian return -1;
41bcc84ec6SStephane Eranian
42bcc84ec6SStephane Eranian for (;;) {
43bcc84ec6SStephane Eranian p = strchr(s, ',');
44bcc84ec6SStephane Eranian if (p)
45bcc84ec6SStephane Eranian *p = '\0';
46bcc84ec6SStephane Eranian
47bcc84ec6SStephane Eranian if (!strcmp(s, "?")) {
48bcc84ec6SStephane Eranian fprintf(stderr, "available registers: ");
4942466b9fSIan Rogers #ifdef HAVE_PERF_REGS_SUPPORT
50bcc84ec6SStephane Eranian for (r = sample_reg_masks; r->name; r++) {
51af785e75SKan Liang if (r->mask & mask)
52bcc84ec6SStephane Eranian fprintf(stderr, "%s ", r->name);
53bcc84ec6SStephane Eranian }
5442466b9fSIan Rogers #endif
55bcc84ec6SStephane Eranian fputc('\n', stderr);
56bcc84ec6SStephane Eranian /* just printing available regs */
57*2eb5dd41SZheng Zengkai goto error;
58bcc84ec6SStephane Eranian }
5942466b9fSIan Rogers #ifdef HAVE_PERF_REGS_SUPPORT
60bcc84ec6SStephane Eranian for (r = sample_reg_masks; r->name; r++) {
61af785e75SKan Liang if ((r->mask & mask) && !strcasecmp(s, r->name))
62bcc84ec6SStephane Eranian break;
63bcc84ec6SStephane Eranian }
6442466b9fSIan Rogers #endif
6542466b9fSIan Rogers if (!r || !r->name) {
66aeea9062SKan Liang ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
67aeea9062SKan Liang s, intr ? "-I" : "--user-regs=");
68bcc84ec6SStephane Eranian goto error;
69bcc84ec6SStephane Eranian }
70bcc84ec6SStephane Eranian
71bcc84ec6SStephane Eranian *mode |= r->mask;
72bcc84ec6SStephane Eranian
73bcc84ec6SStephane Eranian if (!p)
74bcc84ec6SStephane Eranian break;
75bcc84ec6SStephane Eranian
76bcc84ec6SStephane Eranian s = p + 1;
77bcc84ec6SStephane Eranian }
78bcc84ec6SStephane Eranian }
79bcc84ec6SStephane Eranian ret = 0;
80bcc84ec6SStephane Eranian
81bcc84ec6SStephane Eranian /* default to all possible regs */
82bcc84ec6SStephane Eranian if (*mode == 0)
83af785e75SKan Liang *mode = mask;
84bcc84ec6SStephane Eranian error:
85bcc84ec6SStephane Eranian free(os);
86bcc84ec6SStephane Eranian return ret;
87bcc84ec6SStephane Eranian }
88aeea9062SKan Liang
89aeea9062SKan Liang int
parse_user_regs(const struct option * opt,const char * str,int unset)90aeea9062SKan Liang parse_user_regs(const struct option *opt, const char *str, int unset)
91aeea9062SKan Liang {
92aeea9062SKan Liang return __parse_regs(opt, str, unset, false);
93aeea9062SKan Liang }
94aeea9062SKan Liang
95aeea9062SKan Liang int
parse_intr_regs(const struct option * opt,const char * str,int unset)96aeea9062SKan Liang parse_intr_regs(const struct option *opt, const char *str, int unset)
97aeea9062SKan Liang {
98aeea9062SKan Liang return __parse_regs(opt, str, unset, true);
99aeea9062SKan Liang }
100