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