mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 09:56:46 +00:00
9a4e47ef98
Every architecture can provide a register list for sampling. If an architecture doesn't support register sampling, it won't define the data structure 'sample_reg_masks'. Consequently, any code using this structure must be protected by the macro 'HAVE_PERF_REGS_SUPPORT'. This patch defines a weak function, arch__sample_reg_masks(), which will be replaced by an architecture-defined function for returning the architecture's register list. With this refactoring, the function always exists, the condition checking for 'HAVE_PERF_REGS_SUPPORT' is not needed anymore, so remove it. Signed-off-by: Leo Yan <leo.yan@linux.dev> Reviewed-by: Ian Rogers <irogers@google.com> Cc: James Clark <james.clark@arm.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Guo Ren <guoren@kernel.org> Cc: Will Deacon <will@kernel.org> Cc: Mike Leach <mike.leach@linaro.org> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Ming Wang <wangming01@loongson.cn> Cc: John Garry <john.g.garry@oracle.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: linux-csky@vger.kernel.org Cc: linux-riscv@lists.infradead.org Signed-off-by: Namhyung Kim <namhyung@kernel.org> Link: https://lore.kernel.org/r/20240214113947.240957-4-leo.yan@linux.dev
96 lines
1.8 KiB
C
96 lines
1.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "util/debug.h"
|
|
#include <subcmd/parse-options.h>
|
|
#include "util/perf_regs.h"
|
|
#include "util/parse-regs-options.h"
|
|
|
|
static int
|
|
__parse_regs(const struct option *opt, const char *str, int unset, bool intr)
|
|
{
|
|
uint64_t *mode = (uint64_t *)opt->value;
|
|
const struct sample_reg *r = NULL;
|
|
char *s, *os = NULL, *p;
|
|
int ret = -1;
|
|
uint64_t mask;
|
|
|
|
if (unset)
|
|
return 0;
|
|
|
|
/*
|
|
* cannot set it twice
|
|
*/
|
|
if (*mode)
|
|
return -1;
|
|
|
|
if (intr)
|
|
mask = arch__intr_reg_mask();
|
|
else
|
|
mask = arch__user_reg_mask();
|
|
|
|
/* str may be NULL in case no arg is passed to -I */
|
|
if (str) {
|
|
/* because str is read-only */
|
|
s = os = strdup(str);
|
|
if (!s)
|
|
return -1;
|
|
|
|
for (;;) {
|
|
p = strchr(s, ',');
|
|
if (p)
|
|
*p = '\0';
|
|
|
|
if (!strcmp(s, "?")) {
|
|
fprintf(stderr, "available registers: ");
|
|
for (r = arch__sample_reg_masks(); r->name; r++) {
|
|
if (r->mask & mask)
|
|
fprintf(stderr, "%s ", r->name);
|
|
}
|
|
fputc('\n', stderr);
|
|
/* just printing available regs */
|
|
goto error;
|
|
}
|
|
for (r = arch__sample_reg_masks(); r->name; r++) {
|
|
if ((r->mask & mask) && !strcasecmp(s, r->name))
|
|
break;
|
|
}
|
|
if (!r || !r->name) {
|
|
ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
|
|
s, intr ? "-I" : "--user-regs=");
|
|
goto error;
|
|
}
|
|
|
|
*mode |= r->mask;
|
|
|
|
if (!p)
|
|
break;
|
|
|
|
s = p + 1;
|
|
}
|
|
}
|
|
ret = 0;
|
|
|
|
/* default to all possible regs */
|
|
if (*mode == 0)
|
|
*mode = mask;
|
|
error:
|
|
free(os);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
parse_user_regs(const struct option *opt, const char *str, int unset)
|
|
{
|
|
return __parse_regs(opt, str, unset, false);
|
|
}
|
|
|
|
int
|
|
parse_intr_regs(const struct option *opt, const char *str, int unset)
|
|
{
|
|
return __parse_regs(opt, str, unset, true);
|
|
}
|