perf: add support for capturing skid IP
Subsystems (2)
v2 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,%raxWhen 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.
Understanding the skid is also interesting for other precise events.
In V2, we rebased to 10d94ff4d558 (v4.14-rc7).
Stephane Eranian (5):
perf/core: add PERF_RECORD_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 | 6 ++++++ tools/perf/perf.h | 1 + tools/perf/util/event.h | 1 + tools/perf/util/evsel.c | 10 ++++++++++ tools/perf/util/session.c | 3 +++ 12 files changed, 60 insertions(+), 2 deletions(-)
Signature · 1 line
2.7.4
PATCH v2 1/5 perf/core: add PERF_RECORD_SAMPLE_SKID_IP record type
From: Stephane Eranian <[email protected]>
This patchs adds a new sample record type. The goal
is to record the interrupted instruction pointer (IP)
as seen by the kernel and reflected in the machine state (pt_regs).
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 > 0, then you get the PEBS ip corrected for skid
The IP normally comes when the event has PERF_RECORD_SAMPLE_IP set. However, there are certain measuremewnts where you need to have BOTH the corrected IP and the skid IP. For instance, when studying branches, the skid IP usually points to the target of the branch while the corrected IP point 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
@@ -917,6 +917,7 @@ struct perf_sample_data {u64 stack_user_size;u64 phys_addr; +u64 skid_ip; }____cacheline_aligned ;/* default value for data source */
@@ -937,6 +938,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
@@ -140,8 +140,9 @@ enum perf_event_sample_format {PERF_SAMPLE_TRANSACTION =1U <<17 ,PERF_SAMPLE_REGS_INTR =1U <<18 ,PERF_SAMPLE_PHYS_ADDR =1U <<19 , +PERF_SAMPLE_SKID_IP =1U <<20 , - PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 21, /* non-ABI */ };/*
@@ -816,6 +817,7 @@ enum perf_event_type {* { u64 abi; # enum perf_sample_regs_abi * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR +* { u64 skid_ip; } && PERF_SAMPLE_SKID_IP * }; */ PERF_RECORD_SAMPLE = 9,
kernel/events/core.c +14 -0
@@ -1565,6 +1565,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)if (sample_type &PERF_SAMPLE_PHYS_ADDR ) size +=sizeof (data->phys_addr); +if (sample_type &PERF_SAMPLE_SKID_IP ) + size +=sizeof (data->skid_ip); + event->header_size = size; }
@@ -5934,6 +5937,9 @@ void perf_output_sample(struct perf_output_handle *handle,if (sample_type &PERF_SAMPLE_PHYS_ADDR )perf_output_put (handle, data->phys_addr); +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;
@@ -5999,6 +6005,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.7.4
Peter Zijlstra
maintainerRe: [PATCH v2 1/5] perf/core: add PERF_RECORD_SAMPLE_SKID_IP record type
Quoted 13 lines · Stephane Eranian
include/linux/perf_event.h +1
-0@@ -917,6 +917,7 @@ struct perf_sample_data {u64 stack_user_size;u64 phys_addr; +u64 skid_ip; }____cacheline_aligned ;/* default value for data source */
include/linux/perf_event.h static inline void perf_sample_data_init(struct perf_sample_data *data, · line 942
Quoted 5 lines
include/linux/perf_event.h +1
-0@@ -937,6 +938,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 */ }
I keep forgetting to write the comment explaining how this function only touches a single cacheline; you just wrecked that :/
Re: [PATCH v2 1/5] perf/core: add PERF_RECORD_SAMPLE_SKID_IP record type
Quoted 13 lines · Peter Zijlstra
Quoted 11 lines · Stephane Eranian
include/linux/perf_event.h +1
-0@@ -917,6 +917,7 @@ struct perf_sample_data {u64 stack_user_size;u64 phys_addr; +u64 skid_ip; }____cacheline_aligned ;
Quoted 10 lines
include/linux/perf_event.h static inline void perf_sample_data_init(struct perf_sample_data *data, · line 942
Quoted 7 lines
include/linux/perf_event.h +1
-0/* default value for data source */ @@ -937,6 +938,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 */ }I keep forgetting to write the comment explaining how this function only touches a single cacheline; you just wrecked that :/
Ok, but I need to add that field. So are you saying there is a pad I could use instead?
PATCH v2 2/5 perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS
In reply to Stephane EranianFrom: Stephane Eranian <[email protected]>
This atch adds support for SKID_IP to Intel x86 processors in PEBS mode.
--- arch/x86/events/intel/ds.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/x86/events/intel/ds.c +7 -0
@@ -1189,6 +1189,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.7.4
Re: [PATCH v2 2/5] perf/x86: add PERF_SAMPLE_SKID_IP support for X86 PEBS
Quoted 4 lines · Stephane Eranian
From: Stephane Eranian <[email protected]>
This atch adds support for
SKID_IPto Intel x86 processors in PEBS mode.
s/atch/patch/
Quoted 11 lines
Signed-off-by Stephane Eranian <[email protected]>--- arch/x86/events/intel/ds.c | 7 +++++++ 1 file changed, 7 insertions(+)arch/x86/events/intel/ds.c +0
-0
arch/x86/events/intel/ds.c static void setup_pebs_sample_data(struct perf_event *event, · line 1195
Quoted 7 lines
arch/x86/events/intel/ds.c +4
-0@@ -1189,6 +1189,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 +*/
s/dyanmic/dynamic/
jirka
Quoted 9 lines
arch/x86/events/intel/ds.c +3
-0+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.7.4
PATCH v2 3/5 perf/tools: add support for PERF_SAMPLE_SKID_IP
In reply to Stephane EranianThis 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 | 10 ++++++++++ tools/perf/util/session.c | 3 +++ 5 files changed, 18 insertions(+), 1 deletion(-)
tools/include/uapi/linux/perf_event.h +3 -1
@@ -140,8 +140,9 @@ enum perf_event_sample_format {PERF_SAMPLE_TRANSACTION =1U <<17 ,PERF_SAMPLE_REGS_INTR =1U <<18 ,PERF_SAMPLE_PHYS_ADDR =1U <<19 , +PERF_SAMPLE_SKID_IP =1U <<20 , - PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */ + PERF_SAMPLE_MAX = 1U << 21, /* non-ABI */ };/*
@@ -816,6 +817,7 @@ enum perf_event_type {* { u64 abi; # enum perf_sample_regs_abi * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR +* { u64 skid_ip; } && PERF_SAMPLE_SKID_IP * }; */ PERF_RECORD_SAMPLE = 9,
tools/perf/perf.h +1 -0
@@ -59,6 +59,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
@@ -201,6 +201,7 @@ struct perf_sample {u32 raw_size;u64 data_src;u64 phys_addr; +u64 skid_ip;u32 flags;u16 insn_len;u8 cpumode;
tools/perf/util/evsel.c +10 -0
@@ -980,6 +980,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;
@@ -1478,6 +1481,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value)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 (PHYS_ADDR ), +bit_name (SKID_IP ), { .name = NULL, } };#undef bit_name
@@ -2225,6 +2229,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, array++; } + data->skid_ip =0 ; +if (type &PERF_SAMPLE_SKID_IP ) { + data->skid_ip = *array; + array++; + } +return 0 ; }
tools/perf/util/session.c +3 -0
@@ -1130,6 +1130,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 void dump_read (struct perf_evsel *evsel,union perf_event *event)
Signature · 1 line
2.7.4
PATCH v2 4/5 perf/record: add support for sampling skid ip
In reply to Stephane EranianThis patch adds a new --skid-ip option to perf record to capture the unmodified interrupted instruction pointer in each sample. With this option, the kernel captures both the ip and skid ip. Unless precise mode is enabled both ip are the same. They may be different in precise mode depending on the event and precise sampling mode.
$ 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
@@ -483,6 +483,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 point 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 with precise sampling is enabled. But for +certain measurements, it may be useful to have both the correct and skid ip. This +option enable capturing the skid ip in additional to the corrected ip. Default: off + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/builtin-record.c +2 -0
@@ -1585,6 +1585,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 additional to ip" ), OPT_END() };
Signature · 1 line
2.7.4
Re: [PATCH v2 4/5] perf/record: add support for sampling skid ip
Quoted 8 lines · 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 kernel captures both the ip and skid ip. Unless precise mode is enabled both ip are the same. They may be different in precise mode depending on the event and precise sampling mode.
$ perf record --skid-ip .....
perf record already has too many options. I would rather just make it a event qualifier which is more flexible too
perf record -e cpu/cpu-cycles,skidip=1/
-Andi
PATCH v2 5/5 perf/script: add support for skid ip
In reply to Stephane EranianFrom: Stephane Eranian <[email protected]>
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 | 6 ++++++ tools/perf/util/session.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-)
tools/perf/builtin-script.c +6 -0
@@ -89,6 +89,7 @@ enum perf_output_field {PERF_OUTPUT_SYNTH =1U <<25 ,PERF_OUTPUT_PHYS_ADDR =1U <<26 ,PERF_OUTPUT_UREGS =1U <<27 , + PERF_OUTPUT_SKID_IP = 1U << 28, }; struct output_option {
@@ -123,6 +124,7 @@ struct output_option { {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, {.str = "synth", .field = PERF_OUTPUT_SYNTH}, {.str = "phys_addr", .field = PERF_OUTPUT_PHYS_ADDR}, + {.str = "skid_ip", .field = PERF_OUTPUT_SKID_IP}, }; enum {
@@ -1514,6 +1516,10 @@ static void process_event(struct perf_script *script,if (PRINT_FIELD (PHYS_ADDR ))printf ("%16" PRIx64, sample->phys_addr); + +if (PRINT_FIELD (SKID_IP )) +printf (" %" PRIx64" " , sample->skid_ip); +printf ("\n" ); }
tools/perf/util/session.c +1 -1
@@ -1132,7 +1132,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 void dump_read (struct perf_evsel *evsel,union perf_event *event)
Signature · 1 line
2.7.4
Re: [PATCH v2 5/5] perf/script: add support for skid ip
Quoted 6 lines · Stephane Eranian
From: Stephane Eranian <[email protected]>
This patch adds a
skid_ipfield to perf script
to dump the raw value of thePERF_SAMPLE_SKID_IP
field in each sample.
Quoted 6 lines
$ perf script -F +ip,+skid_ip ......Signed-off-by Stephane Eranian <[email protected]>--- tools/perf/builtin-script.c | 6 ++++++ tools/perf/util/session.c | 2 +-
please update the doc as well (-F option section)
thanks,
jirka