diff options
author | David Ahern <dsahern@gmail.com> | 2012-06-08 10:47:51 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-06-11 10:20:01 -0400 |
commit | 80c0120a3cca30166c0ab8b24e44be67e97b79af (patch) | |
tree | e7328b01e584d810f30e044f0286254a7b12bead | |
parent | 9ee6ddc9dada9cc4b2201631bc74fbf203183a10 (diff) |
perf tools: Fix endianity swapping for adds_features bitmask
Based on Jiri's latest attempt:
https://lkml.org/lkml/2012/5/16/61
Basically, adds_features should be byte swapped assuming unsigned
longs are either 8-bytes (u64) or 4-bytes (u32).
Fixes 32-bit ppc dumping 64-bit x86 feature data:
========
captured on: Sun May 20 19:23:23 2012
hostname : nxos-vdc-dev3
os release : 3.4.0-rc7+
perf version : 3.4.rc4.137.g978da3
arch : x86_64
nrcpus online : 16
nrcpus avail : 16
cpudesc : Intel(R) Xeon(R) CPU E5540 @ 2.53GHz
cpuid : GenuineIntel,6,26,5
total memory : 24680324 kB
...
Verified 64-bit x86 can still dump feature data for 32-bit ppc.
Signed-off-by: David Ahern <dsahern@gmail.com>
Reviewed-by: Jiri Olsa <jolsa@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/4FBBB539.5010805@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/header.c | 16 | ||||
-rw-r--r-- | tools/perf/util/include/linux/bitops.h | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 10 | ||||
-rw-r--r-- | tools/perf/util/session.h | 1 |
4 files changed, 22 insertions, 7 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2dd5edf161b7..4f9b247fb312 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1942,7 +1942,6 @@ int perf_file_header__read(struct perf_file_header *header, | |||
1942 | else | 1942 | else |
1943 | return -1; | 1943 | return -1; |
1944 | } else if (ph->needs_swap) { | 1944 | } else if (ph->needs_swap) { |
1945 | unsigned int i; | ||
1946 | /* | 1945 | /* |
1947 | * feature bitmap is declared as an array of unsigned longs -- | 1946 | * feature bitmap is declared as an array of unsigned longs -- |
1948 | * not good since its size can differ between the host that | 1947 | * not good since its size can differ between the host that |
@@ -1958,14 +1957,17 @@ int perf_file_header__read(struct perf_file_header *header, | |||
1958 | * file), punt and fallback to the original behavior -- | 1957 | * file), punt and fallback to the original behavior -- |
1959 | * clearing all feature bits and setting buildid. | 1958 | * clearing all feature bits and setting buildid. |
1960 | */ | 1959 | */ |
1961 | for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) | 1960 | mem_bswap_64(&header->adds_features, |
1962 | header->adds_features[i] = bswap_64(header->adds_features[i]); | 1961 | BITS_TO_U64(HEADER_FEAT_BITS)); |
1963 | 1962 | ||
1964 | if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { | 1963 | if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { |
1965 | for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) { | 1964 | /* unswap as u64 */ |
1966 | header->adds_features[i] = bswap_64(header->adds_features[i]); | 1965 | mem_bswap_64(&header->adds_features, |
1967 | header->adds_features[i] = bswap_32(header->adds_features[i]); | 1966 | BITS_TO_U64(HEADER_FEAT_BITS)); |
1968 | } | 1967 | |
1968 | /* unswap as u32 */ | ||
1969 | mem_bswap_32(&header->adds_features, | ||
1970 | BITS_TO_U32(HEADER_FEAT_BITS)); | ||
1969 | } | 1971 | } |
1970 | 1972 | ||
1971 | if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { | 1973 | if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { |
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index f1584833bd22..587a230d2075 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #define BITS_PER_LONG __WORDSIZE | 8 | #define BITS_PER_LONG __WORDSIZE |
9 | #define BITS_PER_BYTE 8 | 9 | #define BITS_PER_BYTE 8 |
10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) | 10 | #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) |
11 | #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) | ||
12 | #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) | ||
11 | 13 | ||
12 | #define for_each_set_bit(bit, addr, size) \ | 14 | #define for_each_set_bit(bit, addr, size) \ |
13 | for ((bit) = find_first_bit((addr), (size)); \ | 15 | for ((bit) = find_first_bit((addr), (size)); \ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 2600916efa83..c3e399bcf18d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -442,6 +442,16 @@ static void perf_tool__fill_defaults(struct perf_tool *tool) | |||
442 | tool->finished_round = process_finished_round_stub; | 442 | tool->finished_round = process_finished_round_stub; |
443 | } | 443 | } |
444 | } | 444 | } |
445 | |||
446 | void mem_bswap_32(void *src, int byte_size) | ||
447 | { | ||
448 | u32 *m = src; | ||
449 | while (byte_size > 0) { | ||
450 | *m = bswap_32(*m); | ||
451 | byte_size -= sizeof(u32); | ||
452 | ++m; | ||
453 | } | ||
454 | } | ||
445 | 455 | ||
446 | void mem_bswap_64(void *src, int byte_size) | 456 | void mem_bswap_64(void *src, int byte_size) |
447 | { | 457 | { |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7a5434c00565..0c702e3f0a36 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -80,6 +80,7 @@ struct branch_info *machine__resolve_bstack(struct machine *self, | |||
80 | bool perf_session__has_traces(struct perf_session *self, const char *msg); | 80 | bool perf_session__has_traces(struct perf_session *self, const char *msg); |
81 | 81 | ||
82 | void mem_bswap_64(void *src, int byte_size); | 82 | void mem_bswap_64(void *src, int byte_size); |
83 | void mem_bswap_32(void *src, int byte_size); | ||
83 | void perf_event__attr_swap(struct perf_event_attr *attr); | 84 | void perf_event__attr_swap(struct perf_event_attr *attr); |
84 | 85 | ||
85 | int perf_session__create_kernel_maps(struct perf_session *self); | 86 | int perf_session__create_kernel_maps(struct perf_session *self); |