Commit 352ea45a authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf callchain: Add mask into struct regs_dump

Adding mask info into struct regs_dump to make the registers information
compact.

The mask was always passed along, so logically the mask info fits more
into the struct regs_dump.
Signed-off-by: default avatarJiri Olsa <jolsa@redhat.com>
Acked-by: default avatarJean Pihet <jean.pihet@linaro.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1389098853-14466-9-git-send-email-jolsa@redhat.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 1cf0382a
...@@ -53,6 +53,7 @@ int test__arch_unwind_sample(struct perf_sample *sample, ...@@ -53,6 +53,7 @@ int test__arch_unwind_sample(struct perf_sample *sample,
perf_regs_load(buf); perf_regs_load(buf);
regs->abi = PERF_SAMPLE_REGS_ABI; regs->abi = PERF_SAMPLE_REGS_ABI;
regs->regs = buf; regs->regs = buf;
regs->mask = PERF_REGS_MASK;
return sample_ustack(sample, thread, buf); return sample_ustack(sample, thread, buf);
} }
...@@ -312,7 +312,6 @@ static int perf_inject__sched_stat(struct perf_tool *tool, ...@@ -312,7 +312,6 @@ static int perf_inject__sched_stat(struct perf_tool *tool,
sample_sw.period = sample->period; sample_sw.period = sample->period;
sample_sw.time = sample->time; sample_sw.time = sample->time;
perf_event__synthesize_sample(event_sw, evsel->attr.sample_type, perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
evsel->attr.sample_regs_user,
evsel->attr.read_format, &sample_sw, evsel->attr.read_format, &sample_sw,
false); false);
build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine); build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
......
...@@ -72,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine) ...@@ -72,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
} }
err = unwind__get_entries(unwind_entry, &cnt, machine, thread, err = unwind__get_entries(unwind_entry, &cnt, machine, thread,
PERF_REGS_MASK, &sample, MAX_STACK); &sample, MAX_STACK);
if (err) if (err)
pr_debug("unwind failed\n"); pr_debug("unwind failed\n");
else if (cnt != MAX_STACK) { else if (cnt != MAX_STACK) {
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
} while (0) } while (0)
static bool samples_same(const struct perf_sample *s1, static bool samples_same(const struct perf_sample *s1,
const struct perf_sample *s2, u64 type, u64 regs_user, const struct perf_sample *s2,
u64 read_format) u64 type, u64 read_format)
{ {
size_t i; size_t i;
...@@ -95,8 +95,9 @@ static bool samples_same(const struct perf_sample *s1, ...@@ -95,8 +95,9 @@ static bool samples_same(const struct perf_sample *s1,
} }
if (type & PERF_SAMPLE_REGS_USER) { if (type & PERF_SAMPLE_REGS_USER) {
size_t sz = hweight_long(regs_user) * sizeof(u64); size_t sz = hweight_long(s1->user_regs.mask) * sizeof(u64);
COMP(user_regs.mask);
COMP(user_regs.abi); COMP(user_regs.abi);
if (s1->user_regs.abi && if (s1->user_regs.abi &&
(!s1->user_regs.regs || !s2->user_regs.regs || (!s1->user_regs.regs || !s2->user_regs.regs ||
...@@ -174,6 +175,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) ...@@ -174,6 +175,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
.branch_stack = &branch_stack.branch_stack, .branch_stack = &branch_stack.branch_stack,
.user_regs = { .user_regs = {
.abi = PERF_SAMPLE_REGS_ABI_64, .abi = PERF_SAMPLE_REGS_ABI_64,
.mask = sample_regs_user,
.regs = user_regs, .regs = user_regs,
}, },
.user_stack = { .user_stack = {
...@@ -201,8 +203,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) ...@@ -201,8 +203,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
sample.read.one.id = 99; sample.read.one.id = 99;
} }
sz = perf_event__sample_event_size(&sample, sample_type, sz = perf_event__sample_event_size(&sample, sample_type, read_format);
sample_regs_user, read_format);
bufsz = sz + 4096; /* Add a bit for overrun checking */ bufsz = sz + 4096; /* Add a bit for overrun checking */
event = malloc(bufsz); event = malloc(bufsz);
if (!event) { if (!event) {
...@@ -215,8 +216,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) ...@@ -215,8 +216,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
event->header.misc = 0; event->header.misc = 0;
event->header.size = sz; event->header.size = sz;
err = perf_event__synthesize_sample(event, sample_type, err = perf_event__synthesize_sample(event, sample_type, read_format,
sample_regs_user, read_format,
&sample, false); &sample, false);
if (err) { if (err) {
pr_debug("%s failed for sample_type %#"PRIx64", error %d\n", pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
...@@ -244,8 +244,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) ...@@ -244,8 +244,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
goto out_free; goto out_free;
} }
if (!samples_same(&sample, &sample_out, sample_type, if (!samples_same(&sample, &sample_out, sample_type, read_format)) {
sample_regs_user, read_format)) {
pr_debug("parsing failed for sample_type %#"PRIx64"\n", pr_debug("parsing failed for sample_type %#"PRIx64"\n",
sample_type); sample_type);
goto out_free; goto out_free;
......
...@@ -85,6 +85,7 @@ struct sample_event { ...@@ -85,6 +85,7 @@ struct sample_event {
struct regs_dump { struct regs_dump {
u64 abi; u64 abi;
u64 mask;
u64 *regs; u64 *regs;
}; };
...@@ -259,9 +260,9 @@ int perf_event__preprocess_sample(const union perf_event *event, ...@@ -259,9 +260,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
const char *perf_event__name(unsigned int id); const char *perf_event__name(unsigned int id);
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 sample_regs_user, u64 read_format); u64 read_format);
int perf_event__synthesize_sample(union perf_event *event, u64 type, int perf_event__synthesize_sample(union perf_event *event, u64 type,
u64 sample_regs_user, u64 read_format, u64 read_format,
const struct perf_sample *sample, const struct perf_sample *sample,
bool swapped); bool swapped);
......
...@@ -1396,10 +1396,11 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, ...@@ -1396,10 +1396,11 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++; array++;
if (data->user_regs.abi) { if (data->user_regs.abi) {
u64 regs_user = evsel->attr.sample_regs_user; u64 mask = evsel->attr.sample_regs_user;
sz = hweight_long(regs_user) * sizeof(u64); sz = hweight_long(mask) * sizeof(u64);
OVERFLOW_CHECK(array, sz, max_size); OVERFLOW_CHECK(array, sz, max_size);
data->user_regs.mask = mask;
data->user_regs.regs = (u64 *)array; data->user_regs.regs = (u64 *)array;
array = (void *)array + sz; array = (void *)array + sz;
} }
...@@ -1451,7 +1452,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, ...@@ -1451,7 +1452,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
} }
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 sample_regs_user, u64 read_format) u64 read_format)
{ {
size_t sz, result = sizeof(struct sample_event); size_t sz, result = sizeof(struct sample_event);
...@@ -1517,7 +1518,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, ...@@ -1517,7 +1518,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
if (type & PERF_SAMPLE_REGS_USER) { if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) { if (sample->user_regs.abi) {
result += sizeof(u64); result += sizeof(u64);
sz = hweight_long(sample_regs_user) * sizeof(u64); sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
result += sz; result += sz;
} else { } else {
result += sizeof(u64); result += sizeof(u64);
...@@ -1546,7 +1547,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, ...@@ -1546,7 +1547,7 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
} }
int perf_event__synthesize_sample(union perf_event *event, u64 type, int perf_event__synthesize_sample(union perf_event *event, u64 type,
u64 sample_regs_user, u64 read_format, u64 read_format,
const struct perf_sample *sample, const struct perf_sample *sample,
bool swapped) bool swapped)
{ {
...@@ -1687,7 +1688,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, ...@@ -1687,7 +1688,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
if (type & PERF_SAMPLE_REGS_USER) { if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) { if (sample->user_regs.abi) {
*array++ = sample->user_regs.abi; *array++ = sample->user_regs.abi;
sz = hweight_long(sample_regs_user) * sizeof(u64); sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
memcpy(array, sample->user_regs.regs, sz); memcpy(array, sample->user_regs.regs, sz);
array = (void *)array + sz; array = (void *)array + sz;
} else { } else {
......
...@@ -1383,8 +1383,7 @@ int machine__resolve_callchain(struct machine *machine, ...@@ -1383,8 +1383,7 @@ int machine__resolve_callchain(struct machine *machine,
return 0; return 0;
return unwind__get_entries(unwind_entry, &callchain_cursor, machine, return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
thread, evsel->attr.sample_regs_user, thread, sample, max_stack);
sample, max_stack);
} }
......
...@@ -702,11 +702,12 @@ static void regs_dump__printf(u64 mask, u64 *regs) ...@@ -702,11 +702,12 @@ static void regs_dump__printf(u64 mask, u64 *regs)
} }
} }
static void regs_user__printf(struct perf_sample *sample, u64 mask) static void regs_user__printf(struct perf_sample *sample)
{ {
struct regs_dump *user_regs = &sample->user_regs; struct regs_dump *user_regs = &sample->user_regs;
if (user_regs->regs) { if (user_regs->regs) {
u64 mask = user_regs->mask;
printf("... user regs: mask 0x%" PRIx64 "\n", mask); printf("... user regs: mask 0x%" PRIx64 "\n", mask);
regs_dump__printf(mask, user_regs->regs); regs_dump__printf(mask, user_regs->regs);
} }
...@@ -806,7 +807,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, ...@@ -806,7 +807,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
branch_stack__printf(sample); branch_stack__printf(sample);
if (sample_type & PERF_SAMPLE_REGS_USER) if (sample_type & PERF_SAMPLE_REGS_USER)
regs_user__printf(sample, evsel->attr.sample_regs_user); regs_user__printf(sample);
if (sample_type & PERF_SAMPLE_STACK_USER) if (sample_type & PERF_SAMPLE_STACK_USER)
stack_user__printf(&sample->user_stack); stack_user__printf(&sample->user_stack);
......
...@@ -86,7 +86,6 @@ struct unwind_info { ...@@ -86,7 +86,6 @@ struct unwind_info {
struct perf_sample *sample; struct perf_sample *sample;
struct machine *machine; struct machine *machine;
struct thread *thread; struct thread *thread;
u64 sample_uregs;
}; };
#define dw_read(ptr, type, end) ({ \ #define dw_read(ptr, type, end) ({ \
...@@ -391,16 +390,16 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, ...@@ -391,16 +390,16 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
return !(size == sizeof(*data)); return !(size == sizeof(*data));
} }
static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id, static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id)
u64 sample_regs)
{ {
int i, idx = 0; int i, idx = 0;
u64 mask = regs->mask;
if (!(sample_regs & (1 << id))) if (!(mask & (1 << id)))
return -EINVAL; return -EINVAL;
for (i = 0; i < id; i++) { for (i = 0; i < id; i++) {
if (sample_regs & (1 << i)) if (mask & (1 << i))
idx++; idx++;
} }
...@@ -424,8 +423,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, ...@@ -424,8 +423,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
return 0; return 0;
} }
ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP, ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
ui->sample_uregs);
if (ret) if (ret)
return ret; return ret;
...@@ -475,7 +473,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as, ...@@ -475,7 +473,7 @@ static int access_reg(unw_addr_space_t __maybe_unused as,
if (id < 0) if (id < 0)
return -EINVAL; return -EINVAL;
ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs); ret = reg_value(valp, &ui->sample->user_regs, id);
if (ret) { if (ret) {
pr_err("unwind: can't read reg %d\n", regnum); pr_err("unwind: can't read reg %d\n", regnum);
return ret; return ret;
...@@ -572,13 +570,11 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, ...@@ -572,13 +570,11 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
int unwind__get_entries(unwind_entry_cb_t cb, void *arg, int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct machine *machine, struct thread *thread, struct machine *machine, struct thread *thread,
u64 sample_uregs, struct perf_sample *data, struct perf_sample *data, int max_stack)
int max_stack)
{ {
unw_word_t ip; unw_word_t ip;
struct unwind_info ui = { struct unwind_info ui = {
.sample = data, .sample = data,
.sample_uregs = sample_uregs,
.thread = thread, .thread = thread,
.machine = machine, .machine = machine,
}; };
...@@ -587,7 +583,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, ...@@ -587,7 +583,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
if (!data->user_regs.regs) if (!data->user_regs.regs)
return -EINVAL; return -EINVAL;
ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs); ret = reg_value(&ip, &data->user_regs, PERF_REG_IP);
if (ret) if (ret)
return ret; return ret;
......
...@@ -17,7 +17,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); ...@@ -17,7 +17,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
int unwind__get_entries(unwind_entry_cb_t cb, void *arg, int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct machine *machine, struct machine *machine,
struct thread *thread, struct thread *thread,
u64 sample_uregs,
struct perf_sample *data, int max_stack); struct perf_sample *data, int max_stack);
int unwind__arch_reg_id(int regnum); int unwind__arch_reg_id(int regnum);
#else #else
...@@ -26,7 +25,6 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, ...@@ -26,7 +25,6 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
void *arg __maybe_unused, void *arg __maybe_unused,
struct machine *machine __maybe_unused, struct machine *machine __maybe_unused,
struct thread *thread __maybe_unused, struct thread *thread __maybe_unused,
u64 sample_uregs __maybe_unused,
struct perf_sample *data __maybe_unused, struct perf_sample *data __maybe_unused,
int max_stack __maybe_unused) int max_stack __maybe_unused)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment