aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-05-16 02:59:03 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-05-22 11:48:24 -0400
commite108c66e2c458f89931189a63a67ad16880d7f51 (patch)
tree35feb6a64b0ca216765a4f952041da9de792a922 /tools
parent2e49a948be1e282d2c1477c5a3b5ed23f5987723 (diff)
perf tools: Carry perf_event_attr bitfield throught different endians
When the perf data file is read cross architectures, the perf_event__attr_swap function takes care about endianness of all the struct fields except the bitfield flags. The bitfield flags need to be transformed as well, since the bitfield binary storage differs for both endians. ABI says: Bit-fields are allocated from right to left (least to most significant) on little-endian implementations and from left to right (most to least significant) on big-endian implementations. The above seems to be byte specific, so we need to reverse each byte of the bitfield. 'Internet' also says this might be implementation specific and we probably need proper fix and carry perf_event_attr bitfield flags in separate data file FEAT_ section. Thought this seems to work for now. Note, running following to test perf endianity handling: test 1) - origin system: # perf record -a -- sleep 10 (any perf record will do) # perf report > report.origin # perf archive perf.data - copy the perf.data, report.origin and perf.data.tar.bz2 to a target system and run: # tar xjvf perf.data.tar.bz2 -C ~/.debug # perf report > report.target # diff -u report.origin report.target - the diff should produce no output (besides some white space stuff and possibly different date/TZ output) test 2) - origin system: # perf record -ag -fo /tmp/perf.data -- sleep 1 - mount origin system root to the target system on /mnt/origin - target system: # perf script --symfs /mnt/origin -I -i /mnt/origin/tmp/perf.data \ --kallsyms /mnt/origin/proc/kallsyms - complete perf.data header is displayed Signed-off-by: Jiri Olsa <jolsa@redhat.com> Reviewed-by: David Ahern <dsahern@gmail.com> Tested-by: David Ahern <dsahern@gmail.com> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1337151548-2396-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/session.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4dcc8f3190cf..17c9ace445c4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -481,6 +481,38 @@ static void perf_event__read_swap(union perf_event *event)
481 event->read.id = bswap_64(event->read.id); 481 event->read.id = bswap_64(event->read.id);
482} 482}
483 483
484static u8 revbyte(u8 b)
485{
486 int rev = (b >> 4) | ((b & 0xf) << 4);
487 rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);
488 rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);
489 return (u8) rev;
490}
491
492/*
493 * XXX this is hack in attempt to carry flags bitfield
494 * throught endian village. ABI says:
495 *
496 * Bit-fields are allocated from right to left (least to most significant)
497 * on little-endian implementations and from left to right (most to least
498 * significant) on big-endian implementations.
499 *
500 * The above seems to be byte specific, so we need to reverse each
501 * byte of the bitfield. 'Internet' also says this might be implementation
502 * specific and we probably need proper fix and carry perf_event_attr
503 * bitfield flags in separate data file FEAT_ section. Thought this seems
504 * to work for now.
505 */
506static void swap_bitfield(u8 *p, unsigned len)
507{
508 unsigned i;
509
510 for (i = 0; i < len; i++) {
511 *p = revbyte(*p);
512 p++;
513 }
514}
515
484/* exported for swapping attributes in file header */ 516/* exported for swapping attributes in file header */
485void perf_event__attr_swap(struct perf_event_attr *attr) 517void perf_event__attr_swap(struct perf_event_attr *attr)
486{ 518{
@@ -494,6 +526,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
494 attr->bp_type = bswap_32(attr->bp_type); 526 attr->bp_type = bswap_32(attr->bp_type);
495 attr->bp_addr = bswap_64(attr->bp_addr); 527 attr->bp_addr = bswap_64(attr->bp_addr);
496 attr->bp_len = bswap_64(attr->bp_len); 528 attr->bp_len = bswap_64(attr->bp_len);
529
530 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
497} 531}
498 532
499static void perf_event__hdr_attr_swap(union perf_event *event) 533static void perf_event__hdr_attr_swap(union perf_event *event)