Need to support hw_idx field in branch stack samples
- Dominant language
- C++
- Stars
- 619
- Forks
- 127
- PR merge metrics
- No merged PRs in 30d
Description
Linux commit 42bbabed09ce6208026648a71a45b4394c74585a ("perf tools:
Add hw_idx in struct branch_stack") [changed](https://lkml.org/lkml/2020/2/28/734) the format of branch stacks in perf samples, by adding a new field. When samples use this new format, a new flag PERF_SAMPLE_BRANCH_HW_INDEX is set in branch_sample_type in the event. Anything reading perf.data samples needs to test this flag and be prepared to consume the extra field, something like this:
```
diff --git a/src/quipper/kernel/perf_event.h b/src/quipper/kernel/perf_event.h
index a28d22d..af472ec 100644
--- a/src/quipper/kernel/perf_event.h
+++ b/src/quipper/kernel/perf_event.h
@@ -165,7 +165,9 @@ enum perf_branch_sample_type {
PERF_SAMPLE_BRANCH_NO_TX = 1U << 9, /* not in transaction */
PERF_SAMPLE_BRANCH_COND = 1U << 10, /* conditional branches */
- PERF_SAMPLE_BRANCH_MAX = 1U << 11, /* non-ABI */
+ PERF_SAMPLE_BRANCH_HW_INDEX = 1U << 17, /* sample contains hw_idx field */
+
+ PERF_SAMPLE_BRANCH_MAX = 1U << 18, /* non-ABI */
};
#define PERF_SAMPLE_BRANCH_PLM_ALL \
diff --git a/src/quipper/sample_info_reader.cc b/src/quipper/sample_info_reader.cc
index 42c17f3..dfb25f0 100644
--- a/src/quipper/sample_info_reader.cc
+++ b/src/quipper/sample_info_reader.cc
@@ -113,9 +113,10 @@ void ReadRawData(DataReader* reader, struct perf_sample* sample) {
reader->SeekSet(reader_offset);
}
-// Read call chain info from perf data. Corresponds to sample format type
-// PERF_SAMPLE_CALLCHAIN.
-void ReadBranchStack(DataReader* reader, struct perf_sample* sample) {
+// Read branch stack info from perf data. Corresponds to sample format type
+// PERF_SAMPLE_BRANCH_STACK.
+void ReadBranchStack(DataReader* reader, uint64_t branch_sample_type,
+ struct perf_sample* sample) {
// Make sure there is no existing allocated memory in
// |sample->branch_stack|.
CHECK_EQ(static_cast(NULL), sample->branch_stack);
@@ -124,6 +125,11 @@ void ReadBranchStack(DataReader* reader, struct perf_sample* sample) {
// branch_entry structs.
uint64_t branch_stack_size = 0;
reader->ReadUint64(&branch_stack_size);
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) {
+ // The branch stack may contain an extra field, which we ignore.
+ uint64_t hw_idx;
+ reader->ReadUint64(&hw_idx);
+ }
struct branch_stack* branch_stack = reinterpret_cast(
new uint8_t[sizeof(uint64_t) +
@@ -263,7 +269,7 @@ size_t ReadPerfSampleFromData(const event_t& event,
// { u64 nr;
// { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
if (sample_fields & PERF_SAMPLE_BRANCH_STACK) {
- ReadBranchStack(&reader, sample);
+ ReadBranchStack(&reader, attr.branch_sample_type, sample);
}
// { u64 abi; # enum perf_sample_regs_abi
```
Contributor guide
Assessment
This issue has not been assessed yet.