18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <stdbool.h> 38c2ecf20Sopenharmony_ci#include <stdlib.h> 48c2ecf20Sopenharmony_ci#include <stdint.h> 58c2ecf20Sopenharmony_ci#include <string.h> 68c2ecf20Sopenharmony_ci#include <stdio.h> 78c2ecf20Sopenharmony_ci#include "util/debug.h" 88c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h> 98c2ecf20Sopenharmony_ci#include "util/perf_regs.h" 108c2ecf20Sopenharmony_ci#include "util/parse-regs-options.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int 138c2ecf20Sopenharmony_ci__parse_regs(const struct option *opt, const char *str, int unset, bool intr) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci uint64_t *mode = (uint64_t *)opt->value; 168c2ecf20Sopenharmony_ci const struct sample_reg *r = NULL; 178c2ecf20Sopenharmony_ci char *s, *os = NULL, *p; 188c2ecf20Sopenharmony_ci int ret = -1; 198c2ecf20Sopenharmony_ci uint64_t mask; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (unset) 228c2ecf20Sopenharmony_ci return 0; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci /* 258c2ecf20Sopenharmony_ci * cannot set it twice 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci if (*mode) 288c2ecf20Sopenharmony_ci return -1; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci if (intr) 318c2ecf20Sopenharmony_ci mask = arch__intr_reg_mask(); 328c2ecf20Sopenharmony_ci else 338c2ecf20Sopenharmony_ci mask = arch__user_reg_mask(); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* str may be NULL in case no arg is passed to -I */ 368c2ecf20Sopenharmony_ci if (str) { 378c2ecf20Sopenharmony_ci /* because str is read-only */ 388c2ecf20Sopenharmony_ci s = os = strdup(str); 398c2ecf20Sopenharmony_ci if (!s) 408c2ecf20Sopenharmony_ci return -1; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci for (;;) { 438c2ecf20Sopenharmony_ci p = strchr(s, ','); 448c2ecf20Sopenharmony_ci if (p) 458c2ecf20Sopenharmony_ci *p = '\0'; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (!strcmp(s, "?")) { 488c2ecf20Sopenharmony_ci fprintf(stderr, "available registers: "); 498c2ecf20Sopenharmony_ci#ifdef HAVE_PERF_REGS_SUPPORT 508c2ecf20Sopenharmony_ci for (r = sample_reg_masks; r->name; r++) { 518c2ecf20Sopenharmony_ci if (r->mask & mask) 528c2ecf20Sopenharmony_ci fprintf(stderr, "%s ", r->name); 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci fputc('\n', stderr); 568c2ecf20Sopenharmony_ci /* just printing available regs */ 578c2ecf20Sopenharmony_ci goto error; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci#ifdef HAVE_PERF_REGS_SUPPORT 608c2ecf20Sopenharmony_ci for (r = sample_reg_masks; r->name; r++) { 618c2ecf20Sopenharmony_ci if ((r->mask & mask) && !strcasecmp(s, r->name)) 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci#endif 658c2ecf20Sopenharmony_ci if (!r || !r->name) { 668c2ecf20Sopenharmony_ci ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n", 678c2ecf20Sopenharmony_ci s, intr ? "-I" : "--user-regs="); 688c2ecf20Sopenharmony_ci goto error; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci *mode |= r->mask; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (!p) 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci s = p + 1; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci ret = 0; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* default to all possible regs */ 828c2ecf20Sopenharmony_ci if (*mode == 0) 838c2ecf20Sopenharmony_ci *mode = mask; 848c2ecf20Sopenharmony_cierror: 858c2ecf20Sopenharmony_ci free(os); 868c2ecf20Sopenharmony_ci return ret; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ciint 908c2ecf20Sopenharmony_ciparse_user_regs(const struct option *opt, const char *str, int unset) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci return __parse_regs(opt, str, unset, false); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciint 968c2ecf20Sopenharmony_ciparse_intr_regs(const struct option *opt, const char *str, int unset) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci return __parse_regs(opt, str, unset, true); 998c2ecf20Sopenharmony_ci} 100