Skip to contentSkip to conversation

perf: add support for capturing skid IP

PATCH Superseded Stephane Eranian 3 participants 24 messages Jun 15, 2017 – Jun 16, 2017

Subsystems (2)

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

cover perf: add support for capturing skid IP

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

On some architectures, it is possible to avoid the IP skid using hardware support. For instance, on Intel x86, the use of PEBS helps eliminate the skid on Haswell and later processors. On older Intel processor, software, i..e, the kernel, may succeed in eliminating the skid.

Without this patch, on Haswell processors, if you set:
- attr.precise = 0, then you get the skid IP
- attr.precise = 1, then you get the skid PEBS ip (off-by-1)
- attr.precise = 2, then you get the skidless PEBS ip

The IP is captured when the event has PERF_SAMPLE_IP set in sample_type. However, there are certain measurements where you need to have BOTH the skidless IP and the skid IP. For instance, when studying branches, the skid IP usually points to the target of the branch while the skidless IP points to the branch instruction itself. Today, it is not possible to retrieve both at the same time. This patch makes this possible by specifying PERF_SAMPLE_IP|PERF_SAMPLE_SKID_IP.

As an example, consider the following code snipet:

 37.51 │42c2ed    je     42c2f3
       │42c2ef    add    $0x1,%rdx                                                                                                                                                                              ▒
       │42c2f3    sub    $0x1,%rax                                                                                                                                                                              ▒

When using PEBS (precise=2) and sampling on BR_INST_RETIRED.CONDITIONAL, the IP always points to 0x42c2ed. With precise=1, the IP would point to 0x42c2f3. It is interesting to collect both IPs in a single run to determine how often the conditional branch is taken vs. non-taken.

Stephane Eranian (5):
perf/core: add PERF_SAMPLE_SKID_IP record type perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS perf/tools: add support for PERF_SAMPLE_SKID_IP perf/record: add support for sampling skid ip perf/script: add support for skid ip

 arch/x86/events/intel/ds.c               |  7 +++++++
 include/linux/perf_event.h               |  2 ++
 include/uapi/linux/perf_event.h          |  4 +++-
 kernel/events/core.c                     | 14 ++++++++++++++
 tools/include/uapi/linux/perf_event.h    |  4 +++-
 tools/perf/Documentation/perf-record.txt |  8 ++++++++
 tools/perf/builtin-record.c              |  2 ++
 tools/perf/builtin-script.c              | 12 +++++++++++-
 tools/perf/perf.h                        |  1 +
 tools/perf/util/event.h                  |  1 +
 tools/perf/util/evsel.c                  | 11 ++++++++++-
 tools/perf/util/session.c                |  3 +++
 12 files changed, 65 insertions(+), 4 deletions(-)
Signature · 1 line
2.13.1.518.g3df882009-goog
#1 lore raw

PATCH 1/5 perf/core: add PERF_SAMPLE_SKID_IP record type

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

On some architectures, it is possible to avoid the IP skid using hardware support. For instance, on Intel x86, the use of PEBS helps eliminate the skid on Haswell and later processors.

Without this patch, on Haswell processors, if you set:
- attr.precise = 0, then you get the skid IP
- attr.precise = 1, then you get the skid PEBS ip (off-by-1)
- attr.precise = 2, then you get the skidless PEBS

The IP is captured when the event has PERF_RECORD_SAMPLE_IP set in sample_type. However, there are certain measurements where you need to have BOTH the skidless IP and the skid IP. For instance, when studying branches, the skid IP usually points to the target of the branch while the skidless IP points to the branch instruction itself. Today, it is not possible to retrieve both at the same time. This patch makes this possible by specifying PERF_SAMPLE_IP|PERF_SAMPLE_SKID_IP.

---
 include/linux/perf_event.h      |  2 ++
 include/uapi/linux/perf_event.h |  4 +++-
 kernel/events/core.c            | 14 ++++++++++++++
 3 files changed, 19 insertions(+), 1 deletion(-)
include/linux/perf_event.h +2 -0
index 7d6aa29094b2..ac63f6af6f53 100644
@@ -944,6 +944,7 @@ struct perf_sample_data {
 
 	struct perf_regs		regs_intr;
 	u64				stack_user_size;
+	u64				skid_ip;
 } ____cacheline_aligned;
 
 /* default value for data source */
@@ -964,6 +965,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
 	data->weight = 0;
 	data->data_src.val = PERF_MEM_NA;
 	data->txn = 0;
+	data->skid_ip = 0; /* mark as uinitialized */
 }
 
 extern void perf_output_sample(struct perf_output_handle *handle,
include/uapi/linux/perf_event.h +3 -1
index b1c0b187acfe..48e736eb20bd 100644
@@ -139,8 +139,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_IDENTIFIER			= 1U << 16,
 	PERF_SAMPLE_TRANSACTION			= 1U << 17,
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
+	PERF_SAMPLE_SKID_IP			= 1U << 19,
 
-	PERF_SAMPLE_MAX = 1U << 19,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 20,		/* non-ABI */
 };
 
 /*
@@ -791,6 +792,7 @@ enum perf_event_type {
 	 *	{ u64			transaction; } && PERF_SAMPLE_TRANSACTION
 	 *	{ u64			abi; # enum perf_sample_regs_abi
 	 *	  u64			regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
+	 *	{ u64			skid_ip;   } && PERF_SAMPLE_SKID_IP
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
kernel/events/core.c +14 -0
index 4d2c32f98482..e5afc3cbf287 100644
@@ -1563,6 +1563,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
 	if (sample_type & PERF_SAMPLE_TRANSACTION)
 		size += sizeof(data->txn);
 
+	if (sample_type & PERF_SAMPLE_SKID_IP)
+		size += sizeof(data->skid_ip);
+
 	event->header_size = size;
 }
 
@@ -5947,6 +5950,9 @@ void perf_output_sample(struct perf_output_handle *handle,
 		}
 	}
 
+	if (sample_type & PERF_SAMPLE_SKID_IP)
+		perf_output_put(handle, data->skid_ip);
+
 	if (!event->attr.watermark) {
 		int wakeup_events = event->attr.wakeup_events;
 
@@ -5980,6 +5986,14 @@ void perf_prepare_sample(struct perf_event_header *header,
 	if (sample_type & PERF_SAMPLE_IP)
 		data->ip = perf_instruction_pointer(regs);
 
+	/*
+	 * if skid_ip has not been set by arch specific code, then
+	 * we initialize it to IP as interrupt-based sampling has
+	 * skid
+	 */
+	if (!data->skid_ip && (sample_type & PERF_SAMPLE_SKID_IP))
+		data->skid_ip = perf_instruction_pointer(regs);
+
 	if (sample_type & PERF_SAMPLE_CALLCHAIN) {
 		int size = 1;
 
Signature · 1 line
2.13.1.518.g3df882009-goog
#2 lore raw

PATCH 2/5 perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS

In reply to Stephane Eranian

This patch adds support for SKID_IP to Intel x86 processors in PEBS mode. In that case, the off-by-1 IP from PEBS is returned in the SKID_IP field.

---
 arch/x86/events/intel/ds.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c +7 -0
index c6d23ffe422d..ee17de5d6b8d 100644
@@ -1169,6 +1169,13 @@ static void setup_pebs_sample_data(struct perf_event *event,
 	    x86_pmu.intel_cap.pebs_format >= 1)
 		data->addr = pebs->dla;
 
+	/*
+	 * unmodified, skid IP which is guaranteed to be the next
+	 * dyanmic instruction
+	 */
+	if (sample_type & PERF_SAMPLE_SKID_IP)
+		data->skid_ip = pebs->ip;
+
 	if (x86_pmu.intel_cap.pebs_format >= 2) {
 		/* Only set the TSX weight when no memory weight. */
 		if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
Signature · 1 line
2.13.1.518.g3df882009-goog
#3 lore raw

RE: [PATCH 2/5] perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS

Quoted 4 lines

This patch adds support for SKID_IP to Intel x86 processors in PEBS mode. In that case, the off-by-1 IP from PEBS is returned in the SKID_IP field.

It looks we can only get different skid_ip and ip with :pp event (attr.precise = 2). With the :p event (attr.precise = 1), the skid_ip and ip are the same. Right?

Thanks,
Kan

Quoted 27 lines
---
 arch/x86/events/intel/ds.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c index renamed from arch/x86/events/intel/ds.c +0 -0

c6d23ffe422d..ee17de5d6b8d 100644

arch/x86/events/intel/ds.c +7 -0
@@ -1169,6 +1169,13 @@ static void setup_pebs_sample_data(struct
 perf_event *event,
 	    x86_pmu.intel_cap.pebs_format >= 1)
 		data->addr = pebs->dla;
 
+	/*
+	 * unmodified, skid IP which is guaranteed to be the next
+	 * dyanmic instruction
+	 */
+	if (sample_type & PERF_SAMPLE_SKID_IP)
+		data->skid_ip = pebs->ip;
+
 	if (x86_pmu.intel_cap.pebs_format >= 2) {
 		/* Only set the TSX weight when no memory weight. */

if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
--
2.13.1.518.g3df882009-goog

#4 lore raw

Re: [PATCH 2/5] perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS

Quoted 8 lines · Kan
Quoted 4 lines

This patch adds support for SKID_IP to Intel x86 processors in PEBS mode. In that case, the off-by-1 IP from PEBS is returned in the SKID_IP field.

It looks we can only get different skid_ip and ip with :pp event (attr.precise = 2). With the :p event (attr.precise = 1), the skid_ip and ip are the same. Right?

Correct, because skid_ip would be equal to the pebs->ip.

Quoted 31 lines

Thanks,
Kan

Quoted 27 lines
---
 arch/x86/events/intel/ds.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c index renamed from arch/x86/events/intel/ds.c +0 -0

c6d23ffe422d..ee17de5d6b8d 100644

arch/x86/events/intel/ds.c +7 -0
@@ -1169,6 +1169,13 @@ static void setup_pebs_sample_data(struct
 perf_event *event,
          x86_pmu.intel_cap.pebs_format >= 1)
              data->addr = pebs->dla;
 
+     /*
+      * unmodified, skid IP which is guaranteed to be the next
+      * dyanmic instruction
+      */
+     if (sample_type & PERF_SAMPLE_SKID_IP)
+             data->skid_ip = pebs->ip;
+
      if (x86_pmu.intel_cap.pebs_format >= 2) {
              /* Only set the TSX weight when no memory weight. */
              if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)

--
2.13.1.518.g3df882009-goog

#5 lore raw

RE: [PATCH 2/5] perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS

Quoted 6 lines · Kan
Quoted 4 lines
Quoted 4 lines

This patch adds support for SKID_IP to Intel x86 processors in PEBS mode. In that case, the off-by-1 IP from PEBS is returned in the SKID_IP

Quoted 7 lines

field.

Quoted 2 lines

It looks we can only get different skid_ip and ip with :pp event (attr.precise

= 2).

Quoted 2 lines

With the :p event (attr.precise = 1), the skid_ip and ip are the same. Right?

Correct, because skid_ip would be equal to the pebs->ip.

I think it's better to make it clear for user by adding a check in perf tool. If --skid-ip is applied with :p event/non-PEBS event, the tool may suggest them to use :pp event instead.

Thanks,
Kan

Quoted 29 lines
Quoted 29 lines
Quoted 28 lines
---
 arch/x86/events/intel/ds.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c +7 -0
index c6d23ffe422d..ee17de5d6b8d 100644
@@ -1169,6 +1169,13 @@ static void setup_pebs_sample_data(struct
 perf_event *event,
          x86_pmu.intel_cap.pebs_format >= 1)
              data->addr = pebs->dla;
 
+     /*
+      * unmodified, skid IP which is guaranteed to be the next
+      * dyanmic instruction
+      */
+     if (sample_type & PERF_SAMPLE_SKID_IP)
+             data->skid_ip = pebs->ip;
+
      if (x86_pmu.intel_cap.pebs_format >= 2) {
              /* Only set the TSX weight when no memory weight. */
              if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)

--
2.13.1.518.g3df882009-goog

#6 lore raw

Re: [PATCH 2/5] perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS

In reply to Stephane Eranian

Hi,

Quoted 11 lines · Stephane Eranian
Quoted 8 lines · Kan
Quoted 4 lines

This patch adds support for SKID_IP to Intel x86 processors in PEBS mode. In that case, the off-by-1 IP from PEBS is returned in the SKID_IP field.

It looks we can only get different skid_ip and ip with :pp event (attr.precise = 2). With the :p event (attr.precise = 1), the skid_ip and ip are the same. Right?

Correct, because skid_ip would be equal to the pebs->ip.

To be more precise, you can always specify PERF_SAMPLE_SKID_IP with any event or sampling mode. By default, the value saved in each sample will be the same as the one used for PERF_SAMPLE_IP. On Intel x86, it only differs with precise mode=2 for events supporting PEBS.

Quoted 27 lines
Quoted 27 lines
Quoted 26 lines
---
 arch/x86/events/intel/ds.c | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c index renamed from arch/x86/events/intel/ds.c +0 -0

c6d23ffe422d..ee17de5d6b8d 100644

arch/x86/events/intel/ds.c +7 -0
@@ -1169,6 +1169,13 @@ static void setup_pebs_sample_data(struct
 perf_event *event,
          x86_pmu.intel_cap.pebs_format >= 1)
              data->addr = pebs->dla;
 
+     /*
+      * unmodified, skid IP which is guaranteed to be the next
+      * dyanmic instruction
+      */
+     if (sample_type & PERF_SAMPLE_SKID_IP)
+             data->skid_ip = pebs->ip;
+
      if (x86_pmu.intel_cap.pebs_format >= 2) {
              /* Only set the TSX weight when no memory weight. */
              if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)

--
2.13.1.518.g3df882009-goog

#7 lore raw

PATCH 3/5 perf/tools: add support for PERF_SAMPLE_SKID_IP

In reply to Stephane Eranian

This patch adds the support code to handle the PERF_SAMPLE_SKID_IP record type.

---
 tools/include/uapi/linux/perf_event.h |  4 +++-
 tools/perf/perf.h                     |  1 +
 tools/perf/util/event.h               |  1 +
 tools/perf/util/evsel.c               | 11 ++++++++++-
 tools/perf/util/session.c             |  3 +++
 5 files changed, 18 insertions(+), 2 deletions(-)
tools/include/uapi/linux/perf_event.h +3 -1
index b1c0b187acfe..0ebb6bee75a9 100644
@@ -139,8 +139,9 @@ enum perf_event_sample_format {
 	PERF_SAMPLE_IDENTIFIER			= 1U << 16,
 	PERF_SAMPLE_TRANSACTION			= 1U << 17,
 	PERF_SAMPLE_REGS_INTR			= 1U << 18,
+	PERF_SAMPLE_SKID_IP			= 1U << 19,
 
-	PERF_SAMPLE_MAX = 1U << 19,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 20,		/* non-ABI */
 };
 
 /*
@@ -791,6 +792,7 @@ enum perf_event_type {
 	 *	{ u64			transaction; } && PERF_SAMPLE_TRANSACTION
 	 *	{ u64			abi; # enum perf_sample_regs_abi
 	 *	  u64			regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
+	 *	{ u64			skid_ip; } && PERF_SAMPLE_SKID_IP
 	 * };
 	 */
 	PERF_RECORD_SAMPLE			= 9,
tools/perf/perf.h +1 -0
index 806c216a1078..64ce89a61f8c 100644
@@ -57,6 +57,7 @@ struct record_opts {
 	bool	     tail_synthesize;
 	bool	     overwrite;
 	bool	     ignore_missing_thread;
+	bool	     skid_ip;
 	unsigned int freq;
 	unsigned int mmap_pages;
 	unsigned int auxtrace_mmap_pages;
tools/perf/util/event.h +1 -0
index 7c3fa1c8cbcd..f19bf5e5696c 100644
@@ -199,6 +199,7 @@ struct perf_sample {
 	u32 cpu;
 	u32 raw_size;
 	u64 data_src;
+	u64 skid_ip;
 	u32 flags;
 	u16 insn_len;
 	u8  cpumode;
tools/perf/util/evsel.c +10 -1
index e4f7902d5afa..08d71e83bd07 100644
@@ -937,6 +937,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
 	if (opts->sample_weight)
 		perf_evsel__set_sample_bit(evsel, WEIGHT);
 
+	if (opts->skid_ip)
+		perf_evsel__set_sample_bit(evsel, SKID_IP);
+
 	attr->task  = track;
 	attr->mmap  = track;
 	attr->mmap2 = track && !perf_missing_features.mmap2;
@@ -1319,7 +1322,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
 		bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
 		bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
 		bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC),
-		bit_name(WEIGHT),
+		bit_name(WEIGHT), bit_name(SKID_IP),
 		{ .name = NULL, }
 	};
 #undef bit_name
@@ -2043,6 +2046,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
 		}
 	}
 
+	data->skid_ip = 0;
+	if (type & PERF_SAMPLE_SKID_IP) {
+		data->skid_ip = *array;
+		array++;
+	}
+
 	return 0;
 }
 
tools/perf/util/session.c +3 -0
index 7dc1096264c5..0bfc1051c708 100644
@@ -1123,6 +1123,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
 
 	if (sample_type & PERF_SAMPLE_READ)
 		sample_read__printf(sample, evsel->attr.read_format);
+
+	if (sample_type & PERF_SAMPLE_SKID_IP)
+		printf("... skid_ip: %" PRIu64 "\n", sample->skid_ip);
 }
 
 static struct machine *machines__find_for_cpumode(struct machines *machines,
Signature · 1 line
2.13.1.518.g3df882009-goog
#8 lore raw

PATCH 4/5 perf/record: add support for sampling skid ip

In reply to Stephane Eranian

This patch adds a new --skid-ip option to perf record to capture the unmodified interrupted instruction pointer in each sample. With this option, the perf tool can request that the kernel records both the ip and skid IP in each sample. Unless precise mode is enabled both IPis are the same. They may be different in precise mode depending on the event.

$ perf record --skid-ip .....
---
 tools/perf/Documentation/perf-record.txt | 8 ++++++++
 tools/perf/builtin-record.c              | 2 ++
 2 files changed, 10 insertions(+)
tools/perf/Documentation/perf-record.txt +8 -0
index b0e9e921d534..fa24376c20e0 100644
@@ -477,6 +477,14 @@ config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'.
 
 Implies --tail-synthesize.
 
+--skid-ip::
+Capture the unmodified interrupt instruction pointer (IP) in each sample. Usually
+with event-based sampling, the ip has skid and rarely points to the instruction which
+caused the event to overflow. On some architectures, the hardware can eliminate the
+skid and perf_events returns it as the IP when precise sampling is enabled. But for
+certain measurements, it may be useful to have both the corrected and skid ip. This
+option enables capturing the skid ip in addition to the corrected ip. Default: off
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/builtin-record.c +2 -0
index ee7d0a82ccd0..66b497dc4333 100644
@@ -1669,6 +1669,8 @@ static struct option __record_options[] = {
 			  "signal"),
 	OPT_BOOLEAN(0, "dry-run", &dry_run,
 		    "Parse options then exit"),
+	OPT_BOOLEAN(0, "skid-ip", &record.opts.skid_ip,
+		    "capture skid ip in addition to ip"),
 	OPT_END()
 };
 
Signature · 1 line
2.13.1.518.g3df882009-goog
#9 lore raw

PATCH 5/5 perf/script: add support for skid ip

In reply to Stephane Eranian

This patch adds a skid_ip field to perf script
to dump the raw value of the PERF_SAMPLE_SKID_IP
field in each sample.

$ perf script -F ip,skid_ip ......
---
 tools/perf/builtin-script.c | 12 +++++++++++-
 tools/perf/util/session.c   |  2 +-
 2 files changed, 12 insertions(+), 2 deletions(-)
tools/perf/builtin-script.c +11 -1
index 4761b0d7fcb5..ba6720cf70ce 100644
@@ -85,6 +85,7 @@ enum perf_output_field {
 	PERF_OUTPUT_INSN	    = 1U << 21,
 	PERF_OUTPUT_INSNLEN	    = 1U << 22,
 	PERF_OUTPUT_BRSTACKINSN	    = 1U << 23,
+	PERF_OUTPUT_SKID_IP	    = 1U << 24,
 };
 
 struct output_option {
@@ -115,6 +116,7 @@ struct output_option {
 	{.str = "insn", .field = PERF_OUTPUT_INSN},
 	{.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
 	{.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
+	{.str = "skid_ip", .field = PERF_OUTPUT_SKID_IP},
 };
 
 /* default set to maintain compatibility with current format */
@@ -1125,6 +1127,11 @@ static size_t data_src__printf(u64 data_src)
 	return printf("%-*s", maxlen, out);
 }
 
+static void print_sample_skid_ip(struct perf_sample *sample)
+{
+	printf(" %"PRIx64" ", sample->skid_ip);
+}
+
 static void process_event(struct perf_script *script,
 			  struct perf_sample *sample, struct perf_evsel *evsel,
 			  struct addr_location *al,
@@ -1193,7 +1200,10 @@ static void process_event(struct perf_script *script,
 
 	if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
 		print_sample_bpf_output(sample);
-	print_insn(sample, attr, thread, machine);
+
+	if (PRINT_FIELD(SKID_IP))
+		print_sample_skid_ip(sample);
+
 	printf("\n");
 }
 
tools/perf/util/session.c +1 -1
index 0bfc1051c708..51b90630cb32 100644
@@ -1125,7 +1125,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
 		sample_read__printf(sample, evsel->attr.read_format);
 
 	if (sample_type & PERF_SAMPLE_SKID_IP)
-		printf("... skid_ip: %" PRIu64 "\n", sample->skid_ip);
+		printf("... skid_ip: 0x%" PRIx64 "\n", sample->skid_ip);
 }
 
 static struct machine *machines__find_for_cpumode(struct machines *machines,
Signature · 1 line
2.13.1.518.g3df882009-goog
#10 lore raw
In reply to Stephane Eranian
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

-Andi

#11 lore raw
Quoted 6 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Quoted 6 lines

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

You'd still have to modify tooling to present correct column headers. It is mostly interesting for branches for sure but any situation where you want to skidless IP and the skid IP would work because they tell you something about the sampled instruction.

#12 lore raw
Quoted 7 lines · Stephane Eranian
Quoted 6 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Quoted 7 lines
Quoted 6 lines

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

You'd still have to modify tooling to present correct column headers.

Why? It's from/to?

-Andi

#13 lore raw
Quoted 10 lines · Andi Kleen
Quoted 9 lines · Stephane Eranian
Quoted 8 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Patches look reasonable for me.

Quoted 8 lines
Quoted 5 lines
Quoted 4 lines

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

You'd still have to modify tooling to present correct column headers.

Why? It's from/to?

Ah, yes you are right, but it is not clear to me how you would specify this cleanly with the interface.
Especially in the case where this could be used for non-branch instructions.

Quoted 1 line

-Andi

#14 lore raw
Quoted 15 lines · Stephane Eranian
Quoted 14 lines · Andi Kleen
Quoted 13 lines · Stephane Eranian
Quoted 12 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

You'd still have to modify tooling to present correct column headers.

Why? It's from/to?

Ah, yes you are right, but it is not clear to me how you would specify this cleanly with the interface.
Especially in the case where this could be used for non-branch instructions.

Generally the skid ip is only interesting for instructions that have some kind of control flow change, or an exception/interrupt.

So if it's interesting the headers would be correct.

Actually it's even correct for non control flow change, because the IP moves from "FROM" to "TO" ...

-Andi

#15 lore raw
Quoted 18 lines · Andi Kleen
Quoted 17 lines · Stephane Eranian
Quoted 16 lines · Andi Kleen
Quoted 14 lines · Stephane Eranian
Quoted 6 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Quoted 6 lines

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

You'd still have to modify tooling to present correct column headers.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

Why? It's from/to?

Ah, yes you are right, but it is not clear to me how you would specify this cleanly with the interface.
Especially in the case where this could be used for non-branch instructions.

Generally the skid ip is only interesting for instructions that have some kind of control flow change, or an exception/interrupt.

True, right now I found use for the control flow changes, but any PEBS enabled event + precise=2 could potentially be useful.

Quoted 5 lines

So if it's interesting the headers would be correct.

Actually it's even correct for non control flow change, because the IP moves from "FROM" to "TO" ...

Sure.
But I am not too fond of tying this to a branch abstraction. You'd have to express
this with the perf_events interface.To trigger LBR-style hardware, you'd have to define a new PERF_SAMPLE_BRANCH_SKID_IP of some sort and then you tie this to a branch kind of sampling feature:

$   perf record -j skid_ip -e BR_INST_RETIRED.CONDITIONAL:pp

Is what I think you are thinking about.

#16 lore raw
Quoted 42 lines · Stephane Eranian
Quoted 18 lines · Andi Kleen
Quoted 17 lines · Stephane Eranian
Quoted 16 lines · Andi Kleen
Quoted 14 lines · Stephane Eranian
Quoted 6 lines · Andi Kleen
Quoted 4 lines · Stephane Eranian

This patchs adds a new sample record type called PERF_SAMPLE_SKID_IP. The goal is to record
the unmodified interrupted instruction pointer (IP) as seen by the kernel and reflected in the machine state.

Quoted 6 lines

Patches look reasonable for me.

If you only cared about branches it would be more natural to model it like a 1 entry LBR. That would make a lot more tooling work automatically.

You'd still have to modify tooling to present correct column headers.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

Why? It's from/to?

Ah, yes you are right, but it is not clear to me how you would specify this cleanly with the interface.
Especially in the case where this could be used for non-branch instructions.

Generally the skid ip is only interesting for instructions that have some kind of control flow change, or an exception/interrupt.

True, right now I found use for the control flow changes, but any PEBS enabled event + precise=2 could potentially be useful.

Quoted 5 lines

So if it's interesting the headers would be correct.

Actually it's even correct for non control flow change, because the IP moves from "FROM" to "TO" ...

Sure.
But I am not too fond of tying this to a branch abstraction. You'd have to express
this with the perf_events interface.To trigger LBR-style hardware, you'd have to define a new PERF_SAMPLE_BRANCH_SKID_IP of some sort and then you tie this to a branch kind of sampling feature:

Quoted 3 lines
$   perf record -j skid_ip -e BR_INST_RETIRED.CONDITIONAL:pp

Is what I think you are thinking about.

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

#17 lore raw
Quoted 5 lines

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

That should be fine. After all if you have real LBRs you don't need the skid IP.

-Andi

#18 lore raw

Andi,

Quoted 9 lines · Andi Kleen
Quoted 5 lines

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

That should be fine. After all if you have real LBRs you don't need the skid IP.

Yes, you still do. This is not the same thing. LBR captures only taken branches. I care about taken AND non-taken branches and I don't want to sample on a non-taken event, assuming it is available.

You need to inject the skid ip into the LBR stack somehow. Either directly in the
registers or in the cpuc->lbr_entries. The injection can only happen on interrupt
whereas the LBR captures 32 branches. So you'd have the skid ip info only for the
most recent branch in the stack.

#19 lore raw
Quoted 9 lines · Stephane Eranian

Andi,

Quoted 6 lines · Andi Kleen
Quoted 5 lines

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

Quoted 6 lines
Quoted 3 lines

That should be fine. After all if you have real LBRs you don't need the skid IP.

Yes, you still do. This is not the same thing. LBR captures only taken branches. I care about taken AND non-taken branches and I don't want to sample on a non-taken event, assuming it is available.

Ok that's a reasonable argument for reporting it separately, like in your original patch.

-Andi

#20 lore raw
Quoted 13 lines · Andi Kleen
Quoted 12 lines · Stephane Eranian

Andi,

Quoted 9 lines · Andi Kleen
Quoted 5 lines

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

That should be fine. After all if you have real LBRs you don't need the skid IP.

Quoted 7 lines
Quoted 3 lines

Yes, you still do. This is not the same thing. LBR captures only taken branches. I care about taken AND non-taken branches and I don't want to sample on a non-taken event, assuming it is available.

Ok that's a reasonable argument for reporting it separately, like in your original patch.

Yeah, I think it is easier and more portable, especially on hardware with a PEBS-like mechanism but no branch buffer (like LBR). FYI, I did do a test implementation yesterday to evaluate the difficulty.

Quoted 1 line

-Andi

#21 lore raw
Quoted 18 lines · Stephane Eranian
Quoted 17 lines · Andi Kleen
Quoted 15 lines · Stephane Eranian

Andi,

Quoted 9 lines · Andi Kleen
Quoted 5 lines

Looking at this approach, the user interface is straightforward, implementation in the x86 code is a bit more hairy because of the way the branch_stack is captured, via the cpuc->lbr_entries. If you assume that SKID_IP cannot be used with any other branch stack mode, then it is easy. It becomes messy if you don't.

That should be fine. After all if you have real LBRs you don't need the skid IP.

Yes, you still do. This is not the same thing. LBR captures only taken branches. I care about taken AND non-taken branches and I don't want to sample on a non-taken event, assuming it is available.

Quoted 7 lines
Quoted 3 lines

Ok that's a reasonable argument for reporting it separately, like in your original patch.

Yeah, I think it is easier and more portable, especially on hardware with a PEBS-like mechanism but no branch buffer (like LBR). FYI, I did do a test implementation yesterday to evaluate the difficulty.

A more generalized usage of the feature is to evaluate the amount of skid for any precise event.

Quoted 1 line
Quoted 1 line

-Andi

#22 lore raw
Quoted 6 lines
Quoted 4 lines

Yeah, I think it is easier and more portable, especially on hardware with a PEBS-like mechanism but no branch buffer (like LBR). FYI, I did do a test implementation yesterday to evaluate the difficulty.

A more generalized usage of the feature is to evaluate the amount of skid for any precise event.

It should be always the same (one instruction), except for the control flow change case.

-Andi

#23 lore raw
Quoted 10 lines · Andi Kleen
Quoted 6 lines
Quoted 4 lines

Yeah, I think it is easier and more portable, especially on hardware with a PEBS-like mechanism but no branch buffer (like LBR). FYI, I did do a test implementation yesterday to evaluate the difficulty.

A more generalized usage of the feature is to evaluate the amount of skid for any precise event.

It should be always the same (one instruction), except for the control flow change case.

That's on Intel X86. What about the other arch?

Quoted 1 line

-Andi