diff options
Diffstat (limited to 'tools')
26 files changed, 1465 insertions, 96 deletions
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt index 00ad2d608727..aa5e092c4352 100644 --- a/tools/build/Documentation/Build.txt +++ b/tools/build/Documentation/Build.txt | |||
| @@ -66,6 +66,7 @@ To follow the above example, the user provides following 'Build' files: | |||
| 66 | ex/Build: | 66 | ex/Build: |
| 67 | ex-y += a.o | 67 | ex-y += a.o |
| 68 | ex-y += b.o | 68 | ex-y += b.o |
| 69 | ex-y += b.o # duplicates in the lists are allowed | ||
| 69 | 70 | ||
| 70 | libex-y += c.o | 71 | libex-y += c.o |
| 71 | libex-y += d.o | 72 | libex-y += d.o |
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build index 8120af9c0341..0c5f485521d6 100644 --- a/tools/build/Makefile.build +++ b/tools/build/Makefile.build | |||
| @@ -63,7 +63,7 @@ quiet_cmd_gen = GEN $@ | |||
| 63 | # If there's nothing to link, create empty $@ object. | 63 | # If there's nothing to link, create empty $@ object. |
| 64 | quiet_cmd_ld_multi = LD $@ | 64 | quiet_cmd_ld_multi = LD $@ |
| 65 | cmd_ld_multi = $(if $(strip $(obj-y)),\ | 65 | cmd_ld_multi = $(if $(strip $(obj-y)),\ |
| 66 | $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@) | 66 | $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@) |
| 67 | 67 | ||
| 68 | # Build rules | 68 | # Build rules |
| 69 | $(OUTPUT)%.o: %.c FORCE | 69 | $(OUTPUT)%.o: %.c FORCE |
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build index 70d876237c57..429c7d452101 100644 --- a/tools/build/tests/ex/Build +++ b/tools/build/tests/ex/Build | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | ex-y += ex.o | 1 | ex-y += ex.o |
| 2 | ex-y += a.o | 2 | ex-y += a.o |
| 3 | ex-y += b.o | 3 | ex-y += b.o |
| 4 | ex-y += b.o | ||
| 4 | ex-y += empty/ | 5 | ex-y += empty/ |
| 5 | ex-y += empty2/ | 6 | ex-y += empty2/ |
| 6 | 7 | ||
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index 2866b62eb293..4a0501d7a3b4 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt | |||
| @@ -142,19 +142,21 @@ which is the same as | |||
| 142 | 142 | ||
| 143 | -e intel_pt/tsc=1,noretcomp=0/ | 143 | -e intel_pt/tsc=1,noretcomp=0/ |
| 144 | 144 | ||
| 145 | Note there are now new config terms - see section 'config terms' further below. | ||
| 146 | |||
| 145 | The config terms are listed in /sys/devices/intel_pt/format. They are bit | 147 | The config terms are listed in /sys/devices/intel_pt/format. They are bit |
| 146 | fields within the config member of the struct perf_event_attr which is | 148 | fields within the config member of the struct perf_event_attr which is |
| 147 | passed to the kernel by the perf_event_open system call. They correspond to bit | 149 | passed to the kernel by the perf_event_open system call. They correspond to bit |
| 148 | fields in the IA32_RTIT_CTL MSR. Here is a list of them and their definitions: | 150 | fields in the IA32_RTIT_CTL MSR. Here is a list of them and their definitions: |
| 149 | 151 | ||
| 150 | $ for f in `ls /sys/devices/intel_pt/format`;do | 152 | $ grep -H . /sys/bus/event_source/devices/intel_pt/format/* |
| 151 | > echo $f | 153 | /sys/bus/event_source/devices/intel_pt/format/cyc:config:1 |
| 152 | > cat /sys/devices/intel_pt/format/$f | 154 | /sys/bus/event_source/devices/intel_pt/format/cyc_thresh:config:19-22 |
| 153 | > done | 155 | /sys/bus/event_source/devices/intel_pt/format/mtc:config:9 |
| 154 | noretcomp | 156 | /sys/bus/event_source/devices/intel_pt/format/mtc_period:config:14-17 |
| 155 | config:11 | 157 | /sys/bus/event_source/devices/intel_pt/format/noretcomp:config:11 |
| 156 | tsc | 158 | /sys/bus/event_source/devices/intel_pt/format/psb_period:config:24-27 |
| 157 | config:10 | 159 | /sys/bus/event_source/devices/intel_pt/format/tsc:config:10 |
| 158 | 160 | ||
| 159 | Note that the default config must be overridden for each term i.e. | 161 | Note that the default config must be overridden for each term i.e. |
| 160 | 162 | ||
| @@ -209,9 +211,185 @@ perf_event_attr is displayed if the -vv option is used e.g. | |||
| 209 | ------------------------------------------------------------ | 211 | ------------------------------------------------------------ |
| 210 | 212 | ||
| 211 | 213 | ||
| 214 | config terms | ||
| 215 | ------------ | ||
| 216 | |||
| 217 | The June 2015 version of Intel 64 and IA-32 Architectures Software Developer | ||
| 218 | Manuals, Chapter 36 Intel Processor Trace, defined new Intel PT features. | ||
| 219 | Some of the features are reflect in new config terms. All the config terms are | ||
| 220 | described below. | ||
| 221 | |||
| 222 | tsc Always supported. Produces TSC timestamp packets to provide | ||
| 223 | timing information. In some cases it is possible to decode | ||
| 224 | without timing information, for example a per-thread context | ||
| 225 | that does not overlap executable memory maps. | ||
| 226 | |||
| 227 | The default config selects tsc (i.e. tsc=1). | ||
| 228 | |||
| 229 | noretcomp Always supported. Disables "return compression" so a TIP packet | ||
| 230 | is produced when a function returns. Causes more packets to be | ||
| 231 | produced but might make decoding more reliable. | ||
| 232 | |||
| 233 | The default config does not select noretcomp (i.e. noretcomp=0). | ||
| 234 | |||
| 235 | psb_period Allows the frequency of PSB packets to be specified. | ||
| 236 | |||
| 237 | The PSB packet is a synchronization packet that provides a | ||
| 238 | starting point for decoding or recovery from errors. | ||
| 239 | |||
| 240 | Support for psb_period is indicated by: | ||
| 241 | |||
| 242 | /sys/bus/event_source/devices/intel_pt/caps/psb_cyc | ||
| 243 | |||
| 244 | which contains "1" if the feature is supported and "0" | ||
| 245 | otherwise. | ||
| 246 | |||
| 247 | Valid values are given by: | ||
| 248 | |||
| 249 | /sys/bus/event_source/devices/intel_pt/caps/psb_periods | ||
| 250 | |||
| 251 | which contains a hexadecimal value, the bits of which represent | ||
| 252 | valid values e.g. bit 2 set means value 2 is valid. | ||
| 253 | |||
| 254 | The psb_period value is converted to the approximate number of | ||
| 255 | trace bytes between PSB packets as: | ||
| 256 | |||
| 257 | 2 ^ (value + 11) | ||
| 258 | |||
| 259 | e.g. value 3 means 16KiB bytes between PSBs | ||
| 260 | |||
| 261 | If an invalid value is entered, the error message | ||
| 262 | will give a list of valid values e.g. | ||
| 263 | |||
| 264 | $ perf record -e intel_pt/psb_period=15/u uname | ||
| 265 | Invalid psb_period for intel_pt. Valid values are: 0-5 | ||
| 266 | |||
| 267 | If MTC packets are selected, the default config selects a value | ||
| 268 | of 3 (i.e. psb_period=3) or the nearest lower value that is | ||
| 269 | supported (0 is always supported). Otherwise the default is 0. | ||
| 270 | |||
| 271 | If decoding is expected to be reliable and the buffer is large | ||
| 272 | then a large PSB period can be used. | ||
| 273 | |||
| 274 | Because a TSC packet is produced with PSB, the PSB period can | ||
| 275 | also affect the granularity to timing information in the absence | ||
| 276 | of MTC or CYC. | ||
| 277 | |||
| 278 | mtc Produces MTC timing packets. | ||
| 279 | |||
| 280 | MTC packets provide finer grain timestamp information than TSC | ||
| 281 | packets. MTC packets record time using the hardware crystal | ||
| 282 | clock (CTC) which is related to TSC packets using a TMA packet. | ||
| 283 | |||
| 284 | Support for this feature is indicated by: | ||
| 285 | |||
| 286 | /sys/bus/event_source/devices/intel_pt/caps/mtc | ||
| 287 | |||
| 288 | which contains "1" if the feature is supported and | ||
| 289 | "0" otherwise. | ||
| 290 | |||
| 291 | The frequency of MTC packets can also be specified - see | ||
| 292 | mtc_period below. | ||
| 293 | |||
| 294 | mtc_period Specifies how frequently MTC packets are produced - see mtc | ||
| 295 | above for how to determine if MTC packets are supported. | ||
| 296 | |||
| 297 | Valid values are given by: | ||
| 298 | |||
| 299 | /sys/bus/event_source/devices/intel_pt/caps/mtc_periods | ||
| 300 | |||
| 301 | which contains a hexadecimal value, the bits of which represent | ||
| 302 | valid values e.g. bit 2 set means value 2 is valid. | ||
| 303 | |||
| 304 | The mtc_period value is converted to the MTC frequency as: | ||
| 305 | |||
| 306 | CTC-frequency / (2 ^ value) | ||
| 307 | |||
| 308 | e.g. value 3 means one eighth of CTC-frequency | ||
| 309 | |||
| 310 | Where CTC is the hardware crystal clock, the frequency of which | ||
| 311 | can be related to TSC via values provided in cpuid leaf 0x15. | ||
| 312 | |||
| 313 | If an invalid value is entered, the error message | ||
| 314 | will give a list of valid values e.g. | ||
| 315 | |||
| 316 | $ perf record -e intel_pt/mtc_period=15/u uname | ||
| 317 | Invalid mtc_period for intel_pt. Valid values are: 0,3,6,9 | ||
| 318 | |||
| 319 | The default value is 3 or the nearest lower value | ||
| 320 | that is supported (0 is always supported). | ||
| 321 | |||
| 322 | cyc Produces CYC timing packets. | ||
| 323 | |||
| 324 | CYC packets provide even finer grain timestamp information than | ||
| 325 | MTC and TSC packets. A CYC packet contains the number of CPU | ||
| 326 | cycles since the last CYC packet. Unlike MTC and TSC packets, | ||
| 327 | CYC packets are only sent when another packet is also sent. | ||
| 328 | |||
| 329 | Support for this feature is indicated by: | ||
| 330 | |||
| 331 | /sys/bus/event_source/devices/intel_pt/caps/psb_cyc | ||
| 332 | |||
| 333 | which contains "1" if the feature is supported and | ||
| 334 | "0" otherwise. | ||
| 335 | |||
| 336 | The number of CYC packets produced can be reduced by specifying | ||
| 337 | a threshold - see cyc_thresh below. | ||
| 338 | |||
| 339 | cyc_thresh Specifies how frequently CYC packets are produced - see cyc | ||
| 340 | above for how to determine if CYC packets are supported. | ||
| 341 | |||
| 342 | Valid cyc_thresh values are given by: | ||
| 343 | |||
| 344 | /sys/bus/event_source/devices/intel_pt/caps/cycle_thresholds | ||
| 345 | |||
| 346 | which contains a hexadecimal value, the bits of which represent | ||
| 347 | valid values e.g. bit 2 set means value 2 is valid. | ||
| 348 | |||
| 349 | The cyc_thresh value represents the minimum number of CPU cycles | ||
| 350 | that must have passed before a CYC packet can be sent. The | ||
| 351 | number of CPU cycles is: | ||
| 352 | |||
| 353 | 2 ^ (value - 1) | ||
| 354 | |||
| 355 | e.g. value 4 means 8 CPU cycles must pass before a CYC packet | ||
| 356 | can be sent. Note a CYC packet is still only sent when another | ||
| 357 | packet is sent, not at, e.g. every 8 CPU cycles. | ||
| 358 | |||
| 359 | If an invalid value is entered, the error message | ||
| 360 | will give a list of valid values e.g. | ||
| 361 | |||
| 362 | $ perf record -e intel_pt/cyc,cyc_thresh=15/u uname | ||
| 363 | Invalid cyc_thresh for intel_pt. Valid values are: 0-12 | ||
| 364 | |||
| 365 | CYC packets are not requested by default. | ||
| 366 | |||
| 367 | no_force_psb This is a driver option and is not in the IA32_RTIT_CTL MSR. | ||
| 368 | |||
| 369 | It stops the driver resetting the byte count to zero whenever | ||
| 370 | enabling the trace (for example on context switches) which in | ||
| 371 | turn results in no PSB being forced. However some processors | ||
| 372 | will produce a PSB anyway. | ||
| 373 | |||
| 374 | In any case, there is still a PSB when the trace is enabled for | ||
| 375 | the first time. | ||
| 376 | |||
| 377 | no_force_psb can be used to slightly decrease the trace size but | ||
| 378 | may make it harder for the decoder to recover from errors. | ||
| 379 | |||
| 380 | no_force_psb is not selected by default. | ||
| 381 | |||
| 382 | |||
| 212 | new snapshot option | 383 | new snapshot option |
| 213 | ------------------- | 384 | ------------------- |
| 214 | 385 | ||
| 386 | The difference between full trace and snapshot from the kernel's perspective is | ||
| 387 | that in full trace we don't overwrite trace data that the user hasn't collected | ||
| 388 | yet (and indicated that by advancing aux_tail), whereas in snapshot mode we let | ||
| 389 | the trace run and overwrite older data in the buffer so that whenever something | ||
| 390 | interesting happens, we can stop it and grab a snapshot of what was going on | ||
| 391 | around that interesting moment. | ||
| 392 | |||
| 215 | To select snapshot mode a new option has been added: | 393 | To select snapshot mode a new option has been added: |
| 216 | 394 | ||
| 217 | -S | 395 | -S |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index f31f15a5f873..af009bd6e6b7 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
| @@ -41,7 +41,6 @@ tools/include/asm-generic/bitops.h | |||
| 41 | tools/include/linux/atomic.h | 41 | tools/include/linux/atomic.h |
| 42 | tools/include/linux/bitops.h | 42 | tools/include/linux/bitops.h |
| 43 | tools/include/linux/compiler.h | 43 | tools/include/linux/compiler.h |
| 44 | tools/include/linux/export.h | ||
| 45 | tools/include/linux/hash.h | 44 | tools/include/linux/hash.h |
| 46 | tools/include/linux/kernel.h | 45 | tools/include/linux/kernel.h |
| 47 | tools/include/linux/list.h | 46 | tools/include/linux/list.h |
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index da7d2c15e611..2ca10d796c0b 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
| 20 | #include <linux/log2.h> | 20 | #include <linux/log2.h> |
| 21 | #include <cpuid.h> | ||
| 21 | 22 | ||
| 22 | #include "../../perf.h" | 23 | #include "../../perf.h" |
| 23 | #include "../../util/session.h" | 24 | #include "../../util/session.h" |
| @@ -99,17 +100,137 @@ static int intel_pt_parse_terms(struct list_head *formats, const char *str, | |||
| 99 | return intel_pt_parse_terms_with_default(formats, str, config); | 100 | return intel_pt_parse_terms_with_default(formats, str, config); |
| 100 | } | 101 | } |
| 101 | 102 | ||
| 102 | static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu __maybe_unused, | 103 | static u64 intel_pt_masked_bits(u64 mask, u64 bits) |
| 103 | struct perf_evlist *evlist __maybe_unused) | ||
| 104 | { | 104 | { |
| 105 | return 256; | 105 | const u64 top_bit = 1ULL << 63; |
| 106 | u64 res = 0; | ||
| 107 | int i; | ||
| 108 | |||
| 109 | for (i = 0; i < 64; i++) { | ||
| 110 | if (mask & top_bit) { | ||
| 111 | res <<= 1; | ||
| 112 | if (bits & top_bit) | ||
| 113 | res |= 1; | ||
| 114 | } | ||
| 115 | mask <<= 1; | ||
| 116 | bits <<= 1; | ||
| 117 | } | ||
| 118 | |||
| 119 | return res; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, | ||
| 123 | struct perf_evlist *evlist, u64 *res) | ||
| 124 | { | ||
| 125 | struct perf_evsel *evsel; | ||
| 126 | u64 mask; | ||
| 127 | |||
| 128 | *res = 0; | ||
| 129 | |||
| 130 | mask = perf_pmu__format_bits(&intel_pt_pmu->format, str); | ||
| 131 | if (!mask) | ||
| 132 | return -EINVAL; | ||
| 133 | |||
| 134 | evlist__for_each(evlist, evsel) { | ||
| 135 | if (evsel->attr.type == intel_pt_pmu->type) { | ||
| 136 | *res = intel_pt_masked_bits(mask, evsel->attr.config); | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | return -EINVAL; | ||
| 142 | } | ||
| 143 | |||
| 144 | static size_t intel_pt_psb_period(struct perf_pmu *intel_pt_pmu, | ||
| 145 | struct perf_evlist *evlist) | ||
| 146 | { | ||
| 147 | u64 val; | ||
| 148 | int err, topa_multiple_entries; | ||
| 149 | size_t psb_period; | ||
| 150 | |||
| 151 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/topa_multiple_entries", | ||
| 152 | "%d", &topa_multiple_entries) != 1) | ||
| 153 | topa_multiple_entries = 0; | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Use caps/topa_multiple_entries to indicate early hardware that had | ||
| 157 | * extra frequent PSBs. | ||
| 158 | */ | ||
| 159 | if (!topa_multiple_entries) { | ||
| 160 | psb_period = 256; | ||
| 161 | goto out; | ||
| 162 | } | ||
| 163 | |||
| 164 | err = intel_pt_read_config(intel_pt_pmu, "psb_period", evlist, &val); | ||
| 165 | if (err) | ||
| 166 | val = 0; | ||
| 167 | |||
| 168 | psb_period = 1 << (val + 11); | ||
| 169 | out: | ||
| 170 | pr_debug2("%s psb_period %zu\n", intel_pt_pmu->name, psb_period); | ||
| 171 | return psb_period; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int intel_pt_pick_bit(int bits, int target) | ||
| 175 | { | ||
| 176 | int pos, pick = -1; | ||
| 177 | |||
| 178 | for (pos = 0; bits; bits >>= 1, pos++) { | ||
| 179 | if (bits & 1) { | ||
| 180 | if (pos <= target || pick < 0) | ||
| 181 | pick = pos; | ||
| 182 | if (pos >= target) | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | return pick; | ||
| 106 | } | 188 | } |
| 107 | 189 | ||
| 108 | static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu) | 190 | static u64 intel_pt_default_config(struct perf_pmu *intel_pt_pmu) |
| 109 | { | 191 | { |
| 192 | char buf[256]; | ||
| 193 | int mtc, mtc_periods = 0, mtc_period; | ||
| 194 | int psb_cyc, psb_periods, psb_period; | ||
| 195 | int pos = 0; | ||
| 110 | u64 config; | 196 | u64 config; |
| 111 | 197 | ||
| 112 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &config); | 198 | pos += scnprintf(buf + pos, sizeof(buf) - pos, "tsc"); |
| 199 | |||
| 200 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc", "%d", | ||
| 201 | &mtc) != 1) | ||
| 202 | mtc = 1; | ||
| 203 | |||
| 204 | if (mtc) { | ||
| 205 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/mtc_periods", "%x", | ||
| 206 | &mtc_periods) != 1) | ||
| 207 | mtc_periods = 0; | ||
| 208 | if (mtc_periods) { | ||
| 209 | mtc_period = intel_pt_pick_bit(mtc_periods, 3); | ||
| 210 | pos += scnprintf(buf + pos, sizeof(buf) - pos, | ||
| 211 | ",mtc,mtc_period=%d", mtc_period); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_cyc", "%d", | ||
| 216 | &psb_cyc) != 1) | ||
| 217 | psb_cyc = 1; | ||
| 218 | |||
| 219 | if (psb_cyc && mtc_periods) { | ||
| 220 | if (perf_pmu__scan_file(intel_pt_pmu, "caps/psb_periods", "%x", | ||
| 221 | &psb_periods) != 1) | ||
| 222 | psb_periods = 0; | ||
| 223 | if (psb_periods) { | ||
| 224 | psb_period = intel_pt_pick_bit(psb_periods, 3); | ||
| 225 | pos += scnprintf(buf + pos, sizeof(buf) - pos, | ||
| 226 | ",psb_period=%d", psb_period); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | pr_debug2("%s default config: %s\n", intel_pt_pmu->name, buf); | ||
| 231 | |||
| 232 | intel_pt_parse_terms(&intel_pt_pmu->format, buf, &config); | ||
| 233 | |||
| 113 | return config; | 234 | return config; |
| 114 | } | 235 | } |
| 115 | 236 | ||
| @@ -157,6 +278,15 @@ static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused | |||
| 157 | return INTEL_PT_AUXTRACE_PRIV_SIZE; | 278 | return INTEL_PT_AUXTRACE_PRIV_SIZE; |
| 158 | } | 279 | } |
| 159 | 280 | ||
| 281 | static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) | ||
| 282 | { | ||
| 283 | unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; | ||
| 284 | |||
| 285 | __get_cpuid(0x15, &eax, &ebx, &ecx, &edx); | ||
| 286 | *n = ebx; | ||
| 287 | *d = eax; | ||
| 288 | } | ||
| 289 | |||
| 160 | static int intel_pt_info_fill(struct auxtrace_record *itr, | 290 | static int intel_pt_info_fill(struct auxtrace_record *itr, |
| 161 | struct perf_session *session, | 291 | struct perf_session *session, |
| 162 | struct auxtrace_info_event *auxtrace_info, | 292 | struct auxtrace_info_event *auxtrace_info, |
| @@ -168,7 +298,8 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
| 168 | struct perf_event_mmap_page *pc; | 298 | struct perf_event_mmap_page *pc; |
| 169 | struct perf_tsc_conversion tc = { .time_mult = 0, }; | 299 | struct perf_tsc_conversion tc = { .time_mult = 0, }; |
| 170 | bool cap_user_time_zero = false, per_cpu_mmaps; | 300 | bool cap_user_time_zero = false, per_cpu_mmaps; |
| 171 | u64 tsc_bit, noretcomp_bit; | 301 | u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit; |
| 302 | u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; | ||
| 172 | int err; | 303 | int err; |
| 173 | 304 | ||
| 174 | if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) | 305 | if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) |
| @@ -177,6 +308,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
| 177 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); | 308 | intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); |
| 178 | intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp", | 309 | intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp", |
| 179 | &noretcomp_bit); | 310 | &noretcomp_bit); |
| 311 | intel_pt_parse_terms(&intel_pt_pmu->format, "mtc", &mtc_bit); | ||
| 312 | mtc_freq_bits = perf_pmu__format_bits(&intel_pt_pmu->format, | ||
| 313 | "mtc_period"); | ||
| 314 | intel_pt_parse_terms(&intel_pt_pmu->format, "cyc", &cyc_bit); | ||
| 315 | |||
| 316 | intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); | ||
| 180 | 317 | ||
| 181 | if (!session->evlist->nr_mmaps) | 318 | if (!session->evlist->nr_mmaps) |
| 182 | return -EINVAL; | 319 | return -EINVAL; |
| @@ -207,6 +344,11 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, | |||
| 207 | auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch; | 344 | auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch; |
| 208 | auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode; | 345 | auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode; |
| 209 | auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps; | 346 | auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps; |
| 347 | auxtrace_info->priv[INTEL_PT_MTC_BIT] = mtc_bit; | ||
| 348 | auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS] = mtc_freq_bits; | ||
| 349 | auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n; | ||
| 350 | auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d; | ||
| 351 | auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit; | ||
| 210 | 352 | ||
| 211 | return 0; | 353 | return 0; |
| 212 | } | 354 | } |
| @@ -239,6 +381,117 @@ static int intel_pt_track_switches(struct perf_evlist *evlist) | |||
| 239 | return 0; | 381 | return 0; |
| 240 | } | 382 | } |
| 241 | 383 | ||
| 384 | static void intel_pt_valid_str(char *str, size_t len, u64 valid) | ||
| 385 | { | ||
| 386 | unsigned int val, last = 0, state = 1; | ||
| 387 | int p = 0; | ||
| 388 | |||
| 389 | str[0] = '\0'; | ||
| 390 | |||
| 391 | for (val = 0; val <= 64; val++, valid >>= 1) { | ||
| 392 | if (valid & 1) { | ||
| 393 | last = val; | ||
| 394 | switch (state) { | ||
| 395 | case 0: | ||
| 396 | p += scnprintf(str + p, len - p, ","); | ||
| 397 | /* Fall through */ | ||
| 398 | case 1: | ||
| 399 | p += scnprintf(str + p, len - p, "%u", val); | ||
| 400 | state = 2; | ||
| 401 | break; | ||
| 402 | case 2: | ||
| 403 | state = 3; | ||
| 404 | break; | ||
| 405 | case 3: | ||
| 406 | state = 4; | ||
| 407 | break; | ||
| 408 | default: | ||
| 409 | break; | ||
| 410 | } | ||
| 411 | } else { | ||
| 412 | switch (state) { | ||
| 413 | case 3: | ||
| 414 | p += scnprintf(str + p, len - p, ",%u", last); | ||
| 415 | state = 0; | ||
| 416 | break; | ||
| 417 | case 4: | ||
| 418 | p += scnprintf(str + p, len - p, "-%u", last); | ||
| 419 | state = 0; | ||
| 420 | break; | ||
| 421 | default: | ||
| 422 | break; | ||
| 423 | } | ||
| 424 | if (state != 1) | ||
| 425 | state = 0; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | static int intel_pt_val_config_term(struct perf_pmu *intel_pt_pmu, | ||
| 431 | const char *caps, const char *name, | ||
| 432 | const char *supported, u64 config) | ||
| 433 | { | ||
| 434 | char valid_str[256]; | ||
| 435 | unsigned int shift; | ||
| 436 | unsigned long long valid; | ||
| 437 | u64 bits; | ||
| 438 | int ok; | ||
| 439 | |||
| 440 | if (perf_pmu__scan_file(intel_pt_pmu, caps, "%llx", &valid) != 1) | ||
| 441 | valid = 0; | ||
| 442 | |||
| 443 | if (supported && | ||
| 444 | perf_pmu__scan_file(intel_pt_pmu, supported, "%d", &ok) == 1 && !ok) | ||
| 445 | valid = 0; | ||
| 446 | |||
| 447 | valid |= 1; | ||
| 448 | |||
| 449 | bits = perf_pmu__format_bits(&intel_pt_pmu->format, name); | ||
| 450 | |||
| 451 | config &= bits; | ||
| 452 | |||
| 453 | for (shift = 0; bits && !(bits & 1); shift++) | ||
| 454 | bits >>= 1; | ||
| 455 | |||
| 456 | config >>= shift; | ||
| 457 | |||
| 458 | if (config > 63) | ||
| 459 | goto out_err; | ||
| 460 | |||
| 461 | if (valid & (1 << config)) | ||
| 462 | return 0; | ||
| 463 | out_err: | ||
| 464 | intel_pt_valid_str(valid_str, sizeof(valid_str), valid); | ||
| 465 | pr_err("Invalid %s for %s. Valid values are: %s\n", | ||
| 466 | name, INTEL_PT_PMU_NAME, valid_str); | ||
| 467 | return -EINVAL; | ||
| 468 | } | ||
| 469 | |||
| 470 | static int intel_pt_validate_config(struct perf_pmu *intel_pt_pmu, | ||
| 471 | struct perf_evsel *evsel) | ||
| 472 | { | ||
| 473 | int err; | ||
| 474 | |||
| 475 | if (!evsel) | ||
| 476 | return 0; | ||
| 477 | |||
| 478 | err = intel_pt_val_config_term(intel_pt_pmu, "caps/cycle_thresholds", | ||
| 479 | "cyc_thresh", "caps/psb_cyc", | ||
| 480 | evsel->attr.config); | ||
| 481 | if (err) | ||
| 482 | return err; | ||
| 483 | |||
| 484 | err = intel_pt_val_config_term(intel_pt_pmu, "caps/mtc_periods", | ||
| 485 | "mtc_period", "caps/mtc", | ||
| 486 | evsel->attr.config); | ||
| 487 | if (err) | ||
| 488 | return err; | ||
| 489 | |||
| 490 | return intel_pt_val_config_term(intel_pt_pmu, "caps/psb_periods", | ||
| 491 | "psb_period", "caps/psb_cyc", | ||
| 492 | evsel->attr.config); | ||
| 493 | } | ||
| 494 | |||
| 242 | static int intel_pt_recording_options(struct auxtrace_record *itr, | 495 | static int intel_pt_recording_options(struct auxtrace_record *itr, |
| 243 | struct perf_evlist *evlist, | 496 | struct perf_evlist *evlist, |
| 244 | struct record_opts *opts) | 497 | struct record_opts *opts) |
| @@ -251,6 +504,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
| 251 | const struct cpu_map *cpus = evlist->cpus; | 504 | const struct cpu_map *cpus = evlist->cpus; |
| 252 | bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; | 505 | bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; |
| 253 | u64 tsc_bit; | 506 | u64 tsc_bit; |
| 507 | int err; | ||
| 254 | 508 | ||
| 255 | ptr->evlist = evlist; | 509 | ptr->evlist = evlist; |
| 256 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; | 510 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; |
| @@ -281,6 +535,10 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
| 281 | if (!opts->full_auxtrace) | 535 | if (!opts->full_auxtrace) |
| 282 | return 0; | 536 | return 0; |
| 283 | 537 | ||
| 538 | err = intel_pt_validate_config(intel_pt_pmu, intel_pt_evsel); | ||
| 539 | if (err) | ||
| 540 | return err; | ||
| 541 | |||
| 284 | /* Set default sizes for snapshot mode */ | 542 | /* Set default sizes for snapshot mode */ |
| 285 | if (opts->auxtrace_snapshot_mode) { | 543 | if (opts->auxtrace_snapshot_mode) { |
| 286 | size_t psb_period = intel_pt_psb_period(intel_pt_pmu, evlist); | 544 | size_t psb_period = intel_pt_psb_period(intel_pt_pmu, evlist); |
| @@ -366,8 +624,6 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
| 366 | * threads. | 624 | * threads. |
| 367 | */ | 625 | */ |
| 368 | if (have_timing_info && !cpu_map__empty(cpus)) { | 626 | if (have_timing_info && !cpu_map__empty(cpus)) { |
| 369 | int err; | ||
| 370 | |||
| 371 | err = intel_pt_track_switches(evlist); | 627 | err = intel_pt_track_switches(evlist); |
| 372 | if (err == -EPERM) | 628 | if (err == -EPERM) |
| 373 | pr_debug2("Unable to select sched:sched_switch\n"); | 629 | pr_debug2("Unable to select sched:sched_switch\n"); |
| @@ -394,7 +650,6 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
| 394 | /* Add dummy event to keep tracking */ | 650 | /* Add dummy event to keep tracking */ |
| 395 | if (opts->full_auxtrace) { | 651 | if (opts->full_auxtrace) { |
| 396 | struct perf_evsel *tracking_evsel; | 652 | struct perf_evsel *tracking_evsel; |
| 397 | int err; | ||
| 398 | 653 | ||
| 399 | err = parse_events(evlist, "dummy:u", NULL); | 654 | err = parse_events(evlist, "dummy:u", NULL); |
| 400 | if (err) | 655 | if (err) |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index a32a64ef08e2..8edc205ff9a7 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -67,6 +67,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
| 67 | rb_erase(&al->sym->rb_node, | 67 | rb_erase(&al->sym->rb_node, |
| 68 | &al->map->dso->symbols[al->map->type]); | 68 | &al->map->dso->symbols[al->map->type]); |
| 69 | symbol__delete(al->sym); | 69 | symbol__delete(al->sym); |
| 70 | dso__reset_find_symbol_cache(al->map->dso); | ||
| 70 | } | 71 | } |
| 71 | return 0; | 72 | return 0; |
| 72 | } | 73 | } |
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c index c61d14b101e0..c4b99008e2c9 100644 --- a/tools/perf/ui/tui/progress.c +++ b/tools/perf/ui/tui/progress.c | |||
| @@ -33,9 +33,26 @@ static void tui_progress__update(struct ui_progress *p) | |||
| 33 | pthread_mutex_unlock(&ui__lock); | 33 | pthread_mutex_unlock(&ui__lock); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | static void tui_progress__finish(void) | ||
| 37 | { | ||
| 38 | int y; | ||
| 39 | |||
| 40 | if (use_browser <= 0) | ||
| 41 | return; | ||
| 42 | |||
| 43 | ui__refresh_dimensions(false); | ||
| 44 | pthread_mutex_lock(&ui__lock); | ||
| 45 | y = SLtt_Screen_Rows / 2 - 2; | ||
| 46 | SLsmg_set_color(0); | ||
| 47 | SLsmg_fill_region(y, 0, 3, SLtt_Screen_Cols, ' '); | ||
| 48 | SLsmg_refresh(); | ||
| 49 | pthread_mutex_unlock(&ui__lock); | ||
| 50 | } | ||
| 51 | |||
| 36 | static struct ui_progress_ops tui_progress__ops = | 52 | static struct ui_progress_ops tui_progress__ops = |
| 37 | { | 53 | { |
| 38 | .update = tui_progress__update, | 54 | .update = tui_progress__update, |
| 55 | .finish = tui_progress__finish, | ||
| 39 | }; | 56 | }; |
| 40 | 57 | ||
| 41 | void tui_progress__init(void) | 58 | void tui_progress__init(void) |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index c73276db6d6f..fc8db9c764ac 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
| @@ -324,6 +324,8 @@ struct dso *__dsos__findnew(struct dsos *dsos, const char *name); | |||
| 324 | struct dso *dsos__findnew(struct dsos *dsos, const char *name); | 324 | struct dso *dsos__findnew(struct dsos *dsos, const char *name); |
| 325 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); | 325 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits); |
| 326 | 326 | ||
| 327 | void dso__reset_find_symbol_cache(struct dso *dso); | ||
| 328 | |||
| 327 | size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | 329 | size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, |
| 328 | bool (skip)(struct dso *dso, int parm), int parm); | 330 | bool (skip)(struct dso *dso, int parm), int parm); |
| 329 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); | 331 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); |
diff --git a/tools/perf/util/intel-pt-decoder/inat.c b/tools/perf/util/intel-pt-decoder/inat.c index feeaa509dfe4..906d94aa0a24 100644 --- a/tools/perf/util/intel-pt-decoder/inat.c +++ b/tools/perf/util/intel-pt-decoder/inat.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | * | 19 | * |
| 20 | */ | 20 | */ |
| 21 | #include <asm/insn.h> | 21 | #include "insn.h" |
| 22 | 22 | ||
| 23 | /* Attribute tables are generated from opcode map */ | 23 | /* Attribute tables are generated from opcode map */ |
| 24 | #include "inat-tables.c" | 24 | #include "inat-tables.c" |
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/perf/util/intel-pt-decoder/inat.h index 74a2e312e8a2..611645e903a8 100644 --- a/tools/perf/util/intel-pt-decoder/inat.h +++ b/tools/perf/util/intel-pt-decoder/inat.h | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 21 | * | 21 | * |
| 22 | */ | 22 | */ |
| 23 | #include <asm/inat_types.h> | 23 | #include "inat_types.h" |
| 24 | 24 | ||
| 25 | /* | 25 | /* |
| 26 | * Internal bits. Don't use bitmasks directly, because these bits are | 26 | * Internal bits. Don't use bitmasks directly, because these bits are |
diff --git a/tools/perf/util/intel-pt-decoder/inat_types.h b/tools/perf/util/intel-pt-decoder/inat_types.h new file mode 100644 index 000000000000..cb3c20ce39cf --- /dev/null +++ b/tools/perf/util/intel-pt-decoder/inat_types.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #ifndef _ASM_X86_INAT_TYPES_H | ||
| 2 | #define _ASM_X86_INAT_TYPES_H | ||
| 3 | /* | ||
| 4 | * x86 instruction attributes | ||
| 5 | * | ||
| 6 | * Written by Masami Hiramatsu <mhiramat@redhat.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License | ||
| 19 | * along with this program; if not, write to the Free Software | ||
| 20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 21 | * | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* Instruction attributes */ | ||
| 25 | typedef unsigned int insn_attr_t; | ||
| 26 | typedef unsigned char insn_byte_t; | ||
| 27 | typedef signed int insn_value_t; | ||
| 28 | |||
| 29 | #endif | ||
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c index 8f72b334aea0..47314a64399c 100644 --- a/tools/perf/util/intel-pt-decoder/insn.c +++ b/tools/perf/util/intel-pt-decoder/insn.c | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | #else | 23 | #else |
| 24 | #include <string.h> | 24 | #include <string.h> |
| 25 | #endif | 25 | #endif |
| 26 | #include <asm/inat.h> | 26 | #include "inat.h" |
| 27 | #include <asm/insn.h> | 27 | #include "insn.h" |
| 28 | 28 | ||
| 29 | /* Verify next sizeof(t) bytes can be on the same instruction */ | 29 | /* Verify next sizeof(t) bytes can be on the same instruction */ |
| 30 | #define validate_next(t, insn, n) \ | 30 | #define validate_next(t, insn, n) \ |
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h index e7814b74caf8..dd12da0f4593 100644 --- a/tools/perf/util/intel-pt-decoder/insn.h +++ b/tools/perf/util/intel-pt-decoder/insn.h | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | /* insn_attr_t is defined in inat.h */ | 23 | /* insn_attr_t is defined in inat.h */ |
| 24 | #include <asm/inat.h> | 24 | #include "inat.h" |
| 25 | 25 | ||
| 26 | struct insn_field { | 26 | struct insn_field { |
| 27 | union { | 27 | union { |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index f8ac462fec1a..22ba50224319 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
| @@ -85,7 +85,10 @@ struct intel_pt_decoder { | |||
| 85 | const unsigned char *buf; | 85 | const unsigned char *buf; |
| 86 | size_t len; | 86 | size_t len; |
| 87 | bool return_compression; | 87 | bool return_compression; |
| 88 | bool mtc_insn; | ||
| 88 | bool pge; | 89 | bool pge; |
| 90 | bool have_tma; | ||
| 91 | bool have_cyc; | ||
| 89 | uint64_t pos; | 92 | uint64_t pos; |
| 90 | uint64_t last_ip; | 93 | uint64_t last_ip; |
| 91 | uint64_t ip; | 94 | uint64_t ip; |
| @@ -94,20 +97,37 @@ struct intel_pt_decoder { | |||
| 94 | uint64_t tsc_timestamp; | 97 | uint64_t tsc_timestamp; |
| 95 | uint64_t ref_timestamp; | 98 | uint64_t ref_timestamp; |
| 96 | uint64_t ret_addr; | 99 | uint64_t ret_addr; |
| 100 | uint64_t ctc_timestamp; | ||
| 101 | uint64_t ctc_delta; | ||
| 102 | uint64_t cycle_cnt; | ||
| 103 | uint64_t cyc_ref_timestamp; | ||
| 104 | uint32_t last_mtc; | ||
| 105 | uint32_t tsc_ctc_ratio_n; | ||
| 106 | uint32_t tsc_ctc_ratio_d; | ||
| 107 | uint32_t tsc_ctc_mult; | ||
| 108 | uint32_t tsc_slip; | ||
| 109 | uint32_t ctc_rem_mask; | ||
| 110 | int mtc_shift; | ||
| 97 | struct intel_pt_stack stack; | 111 | struct intel_pt_stack stack; |
| 98 | enum intel_pt_pkt_state pkt_state; | 112 | enum intel_pt_pkt_state pkt_state; |
| 99 | struct intel_pt_pkt packet; | 113 | struct intel_pt_pkt packet; |
| 100 | struct intel_pt_pkt tnt; | 114 | struct intel_pt_pkt tnt; |
| 101 | int pkt_step; | 115 | int pkt_step; |
| 102 | int pkt_len; | 116 | int pkt_len; |
| 117 | int last_packet_type; | ||
| 103 | unsigned int cbr; | 118 | unsigned int cbr; |
| 104 | unsigned int max_non_turbo_ratio; | 119 | unsigned int max_non_turbo_ratio; |
| 120 | double max_non_turbo_ratio_fp; | ||
| 121 | double cbr_cyc_to_tsc; | ||
| 122 | double calc_cyc_to_tsc; | ||
| 123 | bool have_calc_cyc_to_tsc; | ||
| 105 | int exec_mode; | 124 | int exec_mode; |
| 106 | unsigned int insn_bytes; | 125 | unsigned int insn_bytes; |
| 107 | uint64_t sign_bit; | 126 | uint64_t sign_bit; |
| 108 | uint64_t sign_bits; | 127 | uint64_t sign_bits; |
| 109 | uint64_t period; | 128 | uint64_t period; |
| 110 | enum intel_pt_period_type period_type; | 129 | enum intel_pt_period_type period_type; |
| 130 | uint64_t tot_insn_cnt; | ||
| 111 | uint64_t period_insn_cnt; | 131 | uint64_t period_insn_cnt; |
| 112 | uint64_t period_mask; | 132 | uint64_t period_mask; |
| 113 | uint64_t period_ticks; | 133 | uint64_t period_ticks; |
| @@ -148,6 +168,13 @@ static void intel_pt_setup_period(struct intel_pt_decoder *decoder) | |||
| 148 | } | 168 | } |
| 149 | } | 169 | } |
| 150 | 170 | ||
| 171 | static uint64_t multdiv(uint64_t t, uint32_t n, uint32_t d) | ||
| 172 | { | ||
| 173 | if (!d) | ||
| 174 | return 0; | ||
| 175 | return (t / d) * n + ((t % d) * n) / d; | ||
| 176 | } | ||
| 177 | |||
| 151 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | 178 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) |
| 152 | { | 179 | { |
| 153 | struct intel_pt_decoder *decoder; | 180 | struct intel_pt_decoder *decoder; |
| @@ -170,10 +197,44 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | |||
| 170 | decoder->period = params->period; | 197 | decoder->period = params->period; |
| 171 | decoder->period_type = params->period_type; | 198 | decoder->period_type = params->period_type; |
| 172 | 199 | ||
| 173 | decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; | 200 | decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; |
| 201 | decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio; | ||
| 174 | 202 | ||
| 175 | intel_pt_setup_period(decoder); | 203 | intel_pt_setup_period(decoder); |
| 176 | 204 | ||
| 205 | decoder->mtc_shift = params->mtc_period; | ||
| 206 | decoder->ctc_rem_mask = (1 << decoder->mtc_shift) - 1; | ||
| 207 | |||
| 208 | decoder->tsc_ctc_ratio_n = params->tsc_ctc_ratio_n; | ||
| 209 | decoder->tsc_ctc_ratio_d = params->tsc_ctc_ratio_d; | ||
| 210 | |||
| 211 | if (!decoder->tsc_ctc_ratio_n) | ||
| 212 | decoder->tsc_ctc_ratio_d = 0; | ||
| 213 | |||
| 214 | if (decoder->tsc_ctc_ratio_d) { | ||
| 215 | if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d)) | ||
| 216 | decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n / | ||
| 217 | decoder->tsc_ctc_ratio_d; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * Allow for timestamps appearing to backwards because a TSC | ||
| 221 | * packet has slipped past a MTC packet, so allow 2 MTC ticks | ||
| 222 | * or ... | ||
| 223 | */ | ||
| 224 | decoder->tsc_slip = multdiv(2 << decoder->mtc_shift, | ||
| 225 | decoder->tsc_ctc_ratio_n, | ||
| 226 | decoder->tsc_ctc_ratio_d); | ||
| 227 | } | ||
| 228 | /* ... or 0x100 paranoia */ | ||
| 229 | if (decoder->tsc_slip < 0x100) | ||
| 230 | decoder->tsc_slip = 0x100; | ||
| 231 | |||
| 232 | intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift); | ||
| 233 | intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n); | ||
| 234 | intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d); | ||
| 235 | intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult); | ||
| 236 | intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip); | ||
| 237 | |||
| 177 | return decoder; | 238 | return decoder; |
| 178 | } | 239 | } |
| 179 | 240 | ||
| @@ -367,6 +428,7 @@ static inline void intel_pt_update_in_tx(struct intel_pt_decoder *decoder) | |||
| 367 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) | 428 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) |
| 368 | { | 429 | { |
| 369 | intel_pt_clear_tx_flags(decoder); | 430 | intel_pt_clear_tx_flags(decoder); |
| 431 | decoder->have_tma = false; | ||
| 370 | decoder->pkt_len = 1; | 432 | decoder->pkt_len = 1; |
| 371 | decoder->pkt_step = 1; | 433 | decoder->pkt_step = 1; |
| 372 | intel_pt_decoder_log_packet(decoder); | 434 | intel_pt_decoder_log_packet(decoder); |
| @@ -399,6 +461,7 @@ static int intel_pt_get_data(struct intel_pt_decoder *decoder) | |||
| 399 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; | 461 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; |
| 400 | decoder->ref_timestamp = buffer.ref_timestamp; | 462 | decoder->ref_timestamp = buffer.ref_timestamp; |
| 401 | decoder->timestamp = 0; | 463 | decoder->timestamp = 0; |
| 464 | decoder->have_tma = false; | ||
| 402 | decoder->state.trace_nr = buffer.trace_nr; | 465 | decoder->state.trace_nr = buffer.trace_nr; |
| 403 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", | 466 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", |
| 404 | decoder->ref_timestamp); | 467 | decoder->ref_timestamp); |
| @@ -460,10 +523,247 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder) | |||
| 460 | return ret; | 523 | return ret; |
| 461 | } | 524 | } |
| 462 | 525 | ||
| 526 | struct intel_pt_pkt_info { | ||
| 527 | struct intel_pt_decoder *decoder; | ||
| 528 | struct intel_pt_pkt packet; | ||
| 529 | uint64_t pos; | ||
| 530 | int pkt_len; | ||
| 531 | int last_packet_type; | ||
| 532 | void *data; | ||
| 533 | }; | ||
| 534 | |||
| 535 | typedef int (*intel_pt_pkt_cb_t)(struct intel_pt_pkt_info *pkt_info); | ||
| 536 | |||
| 537 | /* Lookahead packets in current buffer */ | ||
| 538 | static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder, | ||
| 539 | intel_pt_pkt_cb_t cb, void *data) | ||
| 540 | { | ||
| 541 | struct intel_pt_pkt_info pkt_info; | ||
| 542 | const unsigned char *buf = decoder->buf; | ||
| 543 | size_t len = decoder->len; | ||
| 544 | int ret; | ||
| 545 | |||
| 546 | pkt_info.decoder = decoder; | ||
| 547 | pkt_info.pos = decoder->pos; | ||
| 548 | pkt_info.pkt_len = decoder->pkt_step; | ||
| 549 | pkt_info.last_packet_type = decoder->last_packet_type; | ||
| 550 | pkt_info.data = data; | ||
| 551 | |||
| 552 | while (1) { | ||
| 553 | do { | ||
| 554 | pkt_info.pos += pkt_info.pkt_len; | ||
| 555 | buf += pkt_info.pkt_len; | ||
| 556 | len -= pkt_info.pkt_len; | ||
| 557 | |||
| 558 | if (!len) | ||
| 559 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 560 | |||
| 561 | ret = intel_pt_get_packet(buf, len, &pkt_info.packet); | ||
| 562 | if (!ret) | ||
| 563 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 564 | if (ret < 0) | ||
| 565 | return ret; | ||
| 566 | |||
| 567 | pkt_info.pkt_len = ret; | ||
| 568 | } while (pkt_info.packet.type == INTEL_PT_PAD); | ||
| 569 | |||
| 570 | ret = cb(&pkt_info); | ||
| 571 | if (ret) | ||
| 572 | return 0; | ||
| 573 | |||
| 574 | pkt_info.last_packet_type = pkt_info.packet.type; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | struct intel_pt_calc_cyc_to_tsc_info { | ||
| 579 | uint64_t cycle_cnt; | ||
| 580 | unsigned int cbr; | ||
| 581 | uint32_t last_mtc; | ||
| 582 | uint64_t ctc_timestamp; | ||
| 583 | uint64_t ctc_delta; | ||
| 584 | uint64_t tsc_timestamp; | ||
| 585 | uint64_t timestamp; | ||
| 586 | bool have_tma; | ||
| 587 | bool from_mtc; | ||
| 588 | double cbr_cyc_to_tsc; | ||
| 589 | }; | ||
| 590 | |||
| 591 | static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info) | ||
| 592 | { | ||
| 593 | struct intel_pt_decoder *decoder = pkt_info->decoder; | ||
| 594 | struct intel_pt_calc_cyc_to_tsc_info *data = pkt_info->data; | ||
| 595 | uint64_t timestamp; | ||
| 596 | double cyc_to_tsc; | ||
| 597 | unsigned int cbr; | ||
| 598 | uint32_t mtc, mtc_delta, ctc, fc, ctc_rem; | ||
| 599 | |||
| 600 | switch (pkt_info->packet.type) { | ||
| 601 | case INTEL_PT_TNT: | ||
| 602 | case INTEL_PT_TIP_PGE: | ||
| 603 | case INTEL_PT_TIP: | ||
| 604 | case INTEL_PT_FUP: | ||
| 605 | case INTEL_PT_PSB: | ||
| 606 | case INTEL_PT_PIP: | ||
| 607 | case INTEL_PT_MODE_EXEC: | ||
| 608 | case INTEL_PT_MODE_TSX: | ||
| 609 | case INTEL_PT_PSBEND: | ||
| 610 | case INTEL_PT_PAD: | ||
| 611 | case INTEL_PT_VMCS: | ||
| 612 | case INTEL_PT_MNT: | ||
| 613 | return 0; | ||
| 614 | |||
| 615 | case INTEL_PT_MTC: | ||
| 616 | if (!data->have_tma) | ||
| 617 | return 0; | ||
| 618 | |||
| 619 | mtc = pkt_info->packet.payload; | ||
| 620 | if (mtc > data->last_mtc) | ||
| 621 | mtc_delta = mtc - data->last_mtc; | ||
| 622 | else | ||
| 623 | mtc_delta = mtc + 256 - data->last_mtc; | ||
| 624 | data->ctc_delta += mtc_delta << decoder->mtc_shift; | ||
| 625 | data->last_mtc = mtc; | ||
| 626 | |||
| 627 | if (decoder->tsc_ctc_mult) { | ||
| 628 | timestamp = data->ctc_timestamp + | ||
| 629 | data->ctc_delta * decoder->tsc_ctc_mult; | ||
| 630 | } else { | ||
| 631 | timestamp = data->ctc_timestamp + | ||
| 632 | multdiv(data->ctc_delta, | ||
| 633 | decoder->tsc_ctc_ratio_n, | ||
| 634 | decoder->tsc_ctc_ratio_d); | ||
| 635 | } | ||
| 636 | |||
| 637 | if (timestamp < data->timestamp) | ||
| 638 | return 1; | ||
| 639 | |||
| 640 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { | ||
| 641 | data->timestamp = timestamp; | ||
| 642 | return 0; | ||
| 643 | } | ||
| 644 | |||
| 645 | break; | ||
| 646 | |||
| 647 | case INTEL_PT_TSC: | ||
| 648 | timestamp = pkt_info->packet.payload | | ||
| 649 | (data->timestamp & (0xffULL << 56)); | ||
| 650 | if (data->from_mtc && timestamp < data->timestamp && | ||
| 651 | data->timestamp - timestamp < decoder->tsc_slip) | ||
| 652 | return 1; | ||
| 653 | while (timestamp < data->timestamp) | ||
| 654 | timestamp += (1ULL << 56); | ||
| 655 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { | ||
| 656 | if (data->from_mtc) | ||
| 657 | return 1; | ||
| 658 | data->tsc_timestamp = timestamp; | ||
| 659 | data->timestamp = timestamp; | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | break; | ||
| 663 | |||
| 664 | case INTEL_PT_TMA: | ||
| 665 | if (data->from_mtc) | ||
| 666 | return 1; | ||
| 667 | |||
| 668 | if (!decoder->tsc_ctc_ratio_d) | ||
| 669 | return 0; | ||
| 670 | |||
| 671 | ctc = pkt_info->packet.payload; | ||
| 672 | fc = pkt_info->packet.count; | ||
| 673 | ctc_rem = ctc & decoder->ctc_rem_mask; | ||
| 674 | |||
| 675 | data->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; | ||
| 676 | |||
| 677 | data->ctc_timestamp = data->tsc_timestamp - fc; | ||
| 678 | if (decoder->tsc_ctc_mult) { | ||
| 679 | data->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult; | ||
| 680 | } else { | ||
| 681 | data->ctc_timestamp -= | ||
| 682 | multdiv(ctc_rem, decoder->tsc_ctc_ratio_n, | ||
| 683 | decoder->tsc_ctc_ratio_d); | ||
| 684 | } | ||
| 685 | |||
| 686 | data->ctc_delta = 0; | ||
| 687 | data->have_tma = true; | ||
| 688 | |||
| 689 | return 0; | ||
| 690 | |||
| 691 | case INTEL_PT_CYC: | ||
| 692 | data->cycle_cnt += pkt_info->packet.payload; | ||
| 693 | return 0; | ||
| 694 | |||
| 695 | case INTEL_PT_CBR: | ||
| 696 | cbr = pkt_info->packet.payload; | ||
| 697 | if (data->cbr && data->cbr != cbr) | ||
| 698 | return 1; | ||
| 699 | data->cbr = cbr; | ||
| 700 | data->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; | ||
| 701 | return 0; | ||
| 702 | |||
| 703 | case INTEL_PT_TIP_PGD: | ||
| 704 | case INTEL_PT_TRACESTOP: | ||
| 705 | case INTEL_PT_OVF: | ||
| 706 | case INTEL_PT_BAD: /* Does not happen */ | ||
| 707 | default: | ||
| 708 | return 1; | ||
| 709 | } | ||
| 710 | |||
| 711 | if (!data->cbr && decoder->cbr) { | ||
| 712 | data->cbr = decoder->cbr; | ||
| 713 | data->cbr_cyc_to_tsc = decoder->cbr_cyc_to_tsc; | ||
| 714 | } | ||
| 715 | |||
| 716 | if (!data->cycle_cnt) | ||
| 717 | return 1; | ||
| 718 | |||
| 719 | cyc_to_tsc = (double)(timestamp - decoder->timestamp) / data->cycle_cnt; | ||
| 720 | |||
| 721 | if (data->cbr && cyc_to_tsc > data->cbr_cyc_to_tsc && | ||
| 722 | cyc_to_tsc / data->cbr_cyc_to_tsc > 1.25) { | ||
| 723 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle too big (c.f. CBR-based value %g), pos " x64_fmt "\n", | ||
| 724 | cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos); | ||
| 725 | return 1; | ||
| 726 | } | ||
| 727 | |||
| 728 | decoder->calc_cyc_to_tsc = cyc_to_tsc; | ||
| 729 | decoder->have_calc_cyc_to_tsc = true; | ||
| 730 | |||
| 731 | if (data->cbr) { | ||
| 732 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. CBR-based value %g, pos " x64_fmt "\n", | ||
| 733 | cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos); | ||
| 734 | } else { | ||
| 735 | intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. unknown CBR-based value, pos " x64_fmt "\n", | ||
| 736 | cyc_to_tsc, pkt_info->pos); | ||
| 737 | } | ||
| 738 | |||
| 739 | return 1; | ||
| 740 | } | ||
| 741 | |||
| 742 | static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder, | ||
| 743 | bool from_mtc) | ||
| 744 | { | ||
| 745 | struct intel_pt_calc_cyc_to_tsc_info data = { | ||
| 746 | .cycle_cnt = 0, | ||
| 747 | .cbr = 0, | ||
| 748 | .last_mtc = decoder->last_mtc, | ||
| 749 | .ctc_timestamp = decoder->ctc_timestamp, | ||
| 750 | .ctc_delta = decoder->ctc_delta, | ||
| 751 | .tsc_timestamp = decoder->tsc_timestamp, | ||
| 752 | .timestamp = decoder->timestamp, | ||
| 753 | .have_tma = decoder->have_tma, | ||
| 754 | .from_mtc = from_mtc, | ||
| 755 | .cbr_cyc_to_tsc = 0, | ||
| 756 | }; | ||
| 757 | |||
| 758 | intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data); | ||
| 759 | } | ||
| 760 | |||
| 463 | static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder) | 761 | static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder) |
| 464 | { | 762 | { |
| 465 | int ret; | 763 | int ret; |
| 466 | 764 | ||
| 765 | decoder->last_packet_type = decoder->packet.type; | ||
| 766 | |||
| 467 | do { | 767 | do { |
| 468 | decoder->pos += decoder->pkt_step; | 768 | decoder->pos += decoder->pkt_step; |
| 469 | decoder->buf += decoder->pkt_step; | 769 | decoder->buf += decoder->pkt_step; |
| @@ -522,6 +822,7 @@ static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder) | |||
| 522 | case INTEL_PT_PERIOD_TICKS: | 822 | case INTEL_PT_PERIOD_TICKS: |
| 523 | return intel_pt_next_period(decoder); | 823 | return intel_pt_next_period(decoder); |
| 524 | case INTEL_PT_PERIOD_NONE: | 824 | case INTEL_PT_PERIOD_NONE: |
| 825 | case INTEL_PT_PERIOD_MTC: | ||
| 525 | default: | 826 | default: |
| 526 | return 0; | 827 | return 0; |
| 527 | } | 828 | } |
| @@ -541,6 +842,7 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder) | |||
| 541 | decoder->last_masked_timestamp = masked_timestamp; | 842 | decoder->last_masked_timestamp = masked_timestamp; |
| 542 | break; | 843 | break; |
| 543 | case INTEL_PT_PERIOD_NONE: | 844 | case INTEL_PT_PERIOD_NONE: |
| 845 | case INTEL_PT_PERIOD_MTC: | ||
| 544 | default: | 846 | default: |
| 545 | break; | 847 | break; |
| 546 | } | 848 | } |
| @@ -554,11 +856,15 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, | |||
| 554 | uint64_t max_insn_cnt, insn_cnt = 0; | 856 | uint64_t max_insn_cnt, insn_cnt = 0; |
| 555 | int err; | 857 | int err; |
| 556 | 858 | ||
| 859 | if (!decoder->mtc_insn) | ||
| 860 | decoder->mtc_insn = true; | ||
| 861 | |||
| 557 | max_insn_cnt = intel_pt_next_sample(decoder); | 862 | max_insn_cnt = intel_pt_next_sample(decoder); |
| 558 | 863 | ||
| 559 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, | 864 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, |
| 560 | max_insn_cnt, decoder->data); | 865 | max_insn_cnt, decoder->data); |
| 561 | 866 | ||
| 867 | decoder->tot_insn_cnt += insn_cnt; | ||
| 562 | decoder->timestamp_insn_cnt += insn_cnt; | 868 | decoder->timestamp_insn_cnt += insn_cnt; |
| 563 | decoder->period_insn_cnt += insn_cnt; | 869 | decoder->period_insn_cnt += insn_cnt; |
| 564 | 870 | ||
| @@ -859,6 +1165,8 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
| 859 | { | 1165 | { |
| 860 | uint64_t timestamp; | 1166 | uint64_t timestamp; |
| 861 | 1167 | ||
| 1168 | decoder->have_tma = false; | ||
| 1169 | |||
| 862 | if (decoder->ref_timestamp) { | 1170 | if (decoder->ref_timestamp) { |
| 863 | timestamp = decoder->packet.payload | | 1171 | timestamp = decoder->packet.payload | |
| 864 | (decoder->ref_timestamp & (0xffULL << 56)); | 1172 | (decoder->ref_timestamp & (0xffULL << 56)); |
| @@ -876,21 +1184,29 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
| 876 | } else if (decoder->timestamp) { | 1184 | } else if (decoder->timestamp) { |
| 877 | timestamp = decoder->packet.payload | | 1185 | timestamp = decoder->packet.payload | |
| 878 | (decoder->timestamp & (0xffULL << 56)); | 1186 | (decoder->timestamp & (0xffULL << 56)); |
| 1187 | decoder->tsc_timestamp = timestamp; | ||
| 879 | if (timestamp < decoder->timestamp && | 1188 | if (timestamp < decoder->timestamp && |
| 880 | decoder->timestamp - timestamp < 0x100) { | 1189 | decoder->timestamp - timestamp < decoder->tsc_slip) { |
| 881 | intel_pt_log_to("ERROR: Suppressing backwards timestamp", | 1190 | intel_pt_log_to("Suppressing backwards timestamp", |
| 882 | timestamp); | 1191 | timestamp); |
| 883 | timestamp = decoder->timestamp; | 1192 | timestamp = decoder->timestamp; |
| 884 | } | 1193 | } |
| 885 | while (timestamp < decoder->timestamp) { | 1194 | while (timestamp < decoder->timestamp) { |
| 886 | intel_pt_log_to("Wraparound timestamp", timestamp); | 1195 | intel_pt_log_to("Wraparound timestamp", timestamp); |
| 887 | timestamp += (1ULL << 56); | 1196 | timestamp += (1ULL << 56); |
| 1197 | decoder->tsc_timestamp = timestamp; | ||
| 888 | } | 1198 | } |
| 889 | decoder->tsc_timestamp = timestamp; | ||
| 890 | decoder->timestamp = timestamp; | 1199 | decoder->timestamp = timestamp; |
| 891 | decoder->timestamp_insn_cnt = 0; | 1200 | decoder->timestamp_insn_cnt = 0; |
| 892 | } | 1201 | } |
| 893 | 1202 | ||
| 1203 | if (decoder->last_packet_type == INTEL_PT_CYC) { | ||
| 1204 | decoder->cyc_ref_timestamp = decoder->timestamp; | ||
| 1205 | decoder->cycle_cnt = 0; | ||
| 1206 | decoder->have_calc_cyc_to_tsc = false; | ||
| 1207 | intel_pt_calc_cyc_to_tsc(decoder, false); | ||
| 1208 | } | ||
| 1209 | |||
| 894 | intel_pt_log_to("Setting timestamp", decoder->timestamp); | 1210 | intel_pt_log_to("Setting timestamp", decoder->timestamp); |
| 895 | } | 1211 | } |
| 896 | 1212 | ||
| @@ -898,11 +1214,117 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) | |||
| 898 | { | 1214 | { |
| 899 | intel_pt_log("ERROR: Buffer overflow\n"); | 1215 | intel_pt_log("ERROR: Buffer overflow\n"); |
| 900 | intel_pt_clear_tx_flags(decoder); | 1216 | intel_pt_clear_tx_flags(decoder); |
| 1217 | decoder->have_tma = false; | ||
| 1218 | decoder->cbr = 0; | ||
| 901 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; | 1219 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; |
| 902 | decoder->overflow = true; | 1220 | decoder->overflow = true; |
| 903 | return -EOVERFLOW; | 1221 | return -EOVERFLOW; |
| 904 | } | 1222 | } |
| 905 | 1223 | ||
| 1224 | static void intel_pt_calc_tma(struct intel_pt_decoder *decoder) | ||
| 1225 | { | ||
| 1226 | uint32_t ctc = decoder->packet.payload; | ||
| 1227 | uint32_t fc = decoder->packet.count; | ||
| 1228 | uint32_t ctc_rem = ctc & decoder->ctc_rem_mask; | ||
| 1229 | |||
| 1230 | if (!decoder->tsc_ctc_ratio_d) | ||
| 1231 | return; | ||
| 1232 | |||
| 1233 | decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; | ||
| 1234 | decoder->ctc_timestamp = decoder->tsc_timestamp - fc; | ||
| 1235 | if (decoder->tsc_ctc_mult) { | ||
| 1236 | decoder->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult; | ||
| 1237 | } else { | ||
| 1238 | decoder->ctc_timestamp -= multdiv(ctc_rem, | ||
| 1239 | decoder->tsc_ctc_ratio_n, | ||
| 1240 | decoder->tsc_ctc_ratio_d); | ||
| 1241 | } | ||
| 1242 | decoder->ctc_delta = 0; | ||
| 1243 | decoder->have_tma = true; | ||
| 1244 | intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n", | ||
| 1245 | decoder->ctc_timestamp, decoder->last_mtc, ctc_rem); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder) | ||
| 1249 | { | ||
| 1250 | uint64_t timestamp; | ||
| 1251 | uint32_t mtc, mtc_delta; | ||
| 1252 | |||
| 1253 | if (!decoder->have_tma) | ||
| 1254 | return; | ||
| 1255 | |||
| 1256 | mtc = decoder->packet.payload; | ||
| 1257 | |||
| 1258 | if (mtc > decoder->last_mtc) | ||
| 1259 | mtc_delta = mtc - decoder->last_mtc; | ||
| 1260 | else | ||
| 1261 | mtc_delta = mtc + 256 - decoder->last_mtc; | ||
| 1262 | |||
| 1263 | decoder->ctc_delta += mtc_delta << decoder->mtc_shift; | ||
| 1264 | |||
| 1265 | if (decoder->tsc_ctc_mult) { | ||
| 1266 | timestamp = decoder->ctc_timestamp + | ||
| 1267 | decoder->ctc_delta * decoder->tsc_ctc_mult; | ||
| 1268 | } else { | ||
| 1269 | timestamp = decoder->ctc_timestamp + | ||
| 1270 | multdiv(decoder->ctc_delta, | ||
| 1271 | decoder->tsc_ctc_ratio_n, | ||
| 1272 | decoder->tsc_ctc_ratio_d); | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | if (timestamp < decoder->timestamp) | ||
| 1276 | intel_pt_log("Suppressing MTC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n", | ||
| 1277 | timestamp, decoder->timestamp); | ||
| 1278 | else | ||
| 1279 | decoder->timestamp = timestamp; | ||
| 1280 | |||
| 1281 | decoder->timestamp_insn_cnt = 0; | ||
| 1282 | decoder->last_mtc = mtc; | ||
| 1283 | |||
| 1284 | if (decoder->last_packet_type == INTEL_PT_CYC) { | ||
| 1285 | decoder->cyc_ref_timestamp = decoder->timestamp; | ||
| 1286 | decoder->cycle_cnt = 0; | ||
| 1287 | decoder->have_calc_cyc_to_tsc = false; | ||
| 1288 | intel_pt_calc_cyc_to_tsc(decoder, true); | ||
| 1289 | } | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) | ||
| 1293 | { | ||
| 1294 | unsigned int cbr = decoder->packet.payload; | ||
| 1295 | |||
| 1296 | if (decoder->cbr == cbr) | ||
| 1297 | return; | ||
| 1298 | |||
| 1299 | decoder->cbr = cbr; | ||
| 1300 | decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder) | ||
| 1304 | { | ||
| 1305 | uint64_t timestamp = decoder->cyc_ref_timestamp; | ||
| 1306 | |||
| 1307 | decoder->have_cyc = true; | ||
| 1308 | |||
| 1309 | decoder->cycle_cnt += decoder->packet.payload; | ||
| 1310 | |||
| 1311 | if (!decoder->cyc_ref_timestamp) | ||
| 1312 | return; | ||
| 1313 | |||
| 1314 | if (decoder->have_calc_cyc_to_tsc) | ||
| 1315 | timestamp += decoder->cycle_cnt * decoder->calc_cyc_to_tsc; | ||
| 1316 | else if (decoder->cbr) | ||
| 1317 | timestamp += decoder->cycle_cnt * decoder->cbr_cyc_to_tsc; | ||
| 1318 | else | ||
| 1319 | return; | ||
| 1320 | |||
| 1321 | if (timestamp < decoder->timestamp) | ||
| 1322 | intel_pt_log("Suppressing CYC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n", | ||
| 1323 | timestamp, decoder->timestamp); | ||
| 1324 | else | ||
| 1325 | decoder->timestamp = timestamp; | ||
| 1326 | } | ||
| 1327 | |||
| 906 | /* Walk PSB+ packets when already in sync. */ | 1328 | /* Walk PSB+ packets when already in sync. */ |
| 907 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | 1329 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) |
| 908 | { | 1330 | { |
| @@ -921,8 +1343,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
| 921 | case INTEL_PT_TIP_PGE: | 1343 | case INTEL_PT_TIP_PGE: |
| 922 | case INTEL_PT_TIP: | 1344 | case INTEL_PT_TIP: |
| 923 | case INTEL_PT_TNT: | 1345 | case INTEL_PT_TNT: |
| 1346 | case INTEL_PT_TRACESTOP: | ||
| 924 | case INTEL_PT_BAD: | 1347 | case INTEL_PT_BAD: |
| 925 | case INTEL_PT_PSB: | 1348 | case INTEL_PT_PSB: |
| 1349 | decoder->have_tma = false; | ||
| 926 | intel_pt_log("ERROR: Unexpected packet\n"); | 1350 | intel_pt_log("ERROR: Unexpected packet\n"); |
| 927 | return -EAGAIN; | 1351 | return -EAGAIN; |
| 928 | 1352 | ||
| @@ -933,8 +1357,12 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
| 933 | intel_pt_calc_tsc_timestamp(decoder); | 1357 | intel_pt_calc_tsc_timestamp(decoder); |
| 934 | break; | 1358 | break; |
| 935 | 1359 | ||
| 1360 | case INTEL_PT_TMA: | ||
| 1361 | intel_pt_calc_tma(decoder); | ||
| 1362 | break; | ||
| 1363 | |||
| 936 | case INTEL_PT_CBR: | 1364 | case INTEL_PT_CBR: |
| 937 | decoder->cbr = decoder->packet.payload; | 1365 | intel_pt_calc_cbr(decoder); |
| 938 | break; | 1366 | break; |
| 939 | 1367 | ||
| 940 | case INTEL_PT_MODE_EXEC: | 1368 | case INTEL_PT_MODE_EXEC: |
| @@ -942,7 +1370,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
| 942 | break; | 1370 | break; |
| 943 | 1371 | ||
| 944 | case INTEL_PT_PIP: | 1372 | case INTEL_PT_PIP: |
| 945 | decoder->cr3 = decoder->packet.payload; | 1373 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
| 946 | break; | 1374 | break; |
| 947 | 1375 | ||
| 948 | case INTEL_PT_FUP: | 1376 | case INTEL_PT_FUP: |
| @@ -954,6 +1382,15 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
| 954 | intel_pt_update_in_tx(decoder); | 1382 | intel_pt_update_in_tx(decoder); |
| 955 | break; | 1383 | break; |
| 956 | 1384 | ||
| 1385 | case INTEL_PT_MTC: | ||
| 1386 | intel_pt_calc_mtc_timestamp(decoder); | ||
| 1387 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
| 1388 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
| 1389 | break; | ||
| 1390 | |||
| 1391 | case INTEL_PT_CYC: | ||
| 1392 | case INTEL_PT_VMCS: | ||
| 1393 | case INTEL_PT_MNT: | ||
| 957 | case INTEL_PT_PAD: | 1394 | case INTEL_PT_PAD: |
| 958 | default: | 1395 | default: |
| 959 | break; | 1396 | break; |
| @@ -981,8 +1418,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) | |||
| 981 | switch (decoder->packet.type) { | 1418 | switch (decoder->packet.type) { |
| 982 | case INTEL_PT_TNT: | 1419 | case INTEL_PT_TNT: |
| 983 | case INTEL_PT_FUP: | 1420 | case INTEL_PT_FUP: |
| 1421 | case INTEL_PT_TRACESTOP: | ||
| 984 | case INTEL_PT_PSB: | 1422 | case INTEL_PT_PSB: |
| 985 | case INTEL_PT_TSC: | 1423 | case INTEL_PT_TSC: |
| 1424 | case INTEL_PT_TMA: | ||
| 986 | case INTEL_PT_CBR: | 1425 | case INTEL_PT_CBR: |
| 987 | case INTEL_PT_MODE_TSX: | 1426 | case INTEL_PT_MODE_TSX: |
| 988 | case INTEL_PT_BAD: | 1427 | case INTEL_PT_BAD: |
| @@ -1030,13 +1469,25 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) | |||
| 1030 | return 0; | 1469 | return 0; |
| 1031 | 1470 | ||
| 1032 | case INTEL_PT_PIP: | 1471 | case INTEL_PT_PIP: |
| 1033 | decoder->cr3 = decoder->packet.payload; | 1472 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
| 1473 | break; | ||
| 1474 | |||
| 1475 | case INTEL_PT_MTC: | ||
| 1476 | intel_pt_calc_mtc_timestamp(decoder); | ||
| 1477 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
| 1478 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
| 1479 | break; | ||
| 1480 | |||
| 1481 | case INTEL_PT_CYC: | ||
| 1482 | intel_pt_calc_cyc_timestamp(decoder); | ||
| 1034 | break; | 1483 | break; |
| 1035 | 1484 | ||
| 1036 | case INTEL_PT_MODE_EXEC: | 1485 | case INTEL_PT_MODE_EXEC: |
| 1037 | decoder->exec_mode = decoder->packet.payload; | 1486 | decoder->exec_mode = decoder->packet.payload; |
| 1038 | break; | 1487 | break; |
| 1039 | 1488 | ||
| 1489 | case INTEL_PT_VMCS: | ||
| 1490 | case INTEL_PT_MNT: | ||
| 1040 | case INTEL_PT_PAD: | 1491 | case INTEL_PT_PAD: |
| 1041 | break; | 1492 | break; |
| 1042 | 1493 | ||
| @@ -1120,6 +1571,13 @@ next: | |||
| 1120 | } | 1571 | } |
| 1121 | return intel_pt_walk_fup_tip(decoder); | 1572 | return intel_pt_walk_fup_tip(decoder); |
| 1122 | 1573 | ||
| 1574 | case INTEL_PT_TRACESTOP: | ||
| 1575 | decoder->pge = false; | ||
| 1576 | decoder->continuous_period = false; | ||
| 1577 | intel_pt_clear_tx_flags(decoder); | ||
| 1578 | decoder->have_tma = false; | ||
| 1579 | break; | ||
| 1580 | |||
| 1123 | case INTEL_PT_PSB: | 1581 | case INTEL_PT_PSB: |
| 1124 | intel_pt_clear_stack(&decoder->stack); | 1582 | intel_pt_clear_stack(&decoder->stack); |
| 1125 | err = intel_pt_walk_psbend(decoder); | 1583 | err = intel_pt_walk_psbend(decoder); |
| @@ -1130,15 +1588,43 @@ next: | |||
| 1130 | break; | 1588 | break; |
| 1131 | 1589 | ||
| 1132 | case INTEL_PT_PIP: | 1590 | case INTEL_PT_PIP: |
| 1133 | decoder->cr3 = decoder->packet.payload; | 1591 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
| 1134 | break; | 1592 | break; |
| 1135 | 1593 | ||
| 1594 | case INTEL_PT_MTC: | ||
| 1595 | intel_pt_calc_mtc_timestamp(decoder); | ||
| 1596 | if (decoder->period_type != INTEL_PT_PERIOD_MTC) | ||
| 1597 | break; | ||
| 1598 | /* | ||
| 1599 | * Ensure that there has been an instruction since the | ||
| 1600 | * last MTC. | ||
| 1601 | */ | ||
| 1602 | if (!decoder->mtc_insn) | ||
| 1603 | break; | ||
| 1604 | decoder->mtc_insn = false; | ||
| 1605 | /* Ensure that there is a timestamp */ | ||
| 1606 | if (!decoder->timestamp) | ||
| 1607 | break; | ||
| 1608 | decoder->state.type = INTEL_PT_INSTRUCTION; | ||
| 1609 | decoder->state.from_ip = decoder->ip; | ||
| 1610 | decoder->state.to_ip = 0; | ||
| 1611 | decoder->mtc_insn = false; | ||
| 1612 | return 0; | ||
| 1613 | |||
| 1136 | case INTEL_PT_TSC: | 1614 | case INTEL_PT_TSC: |
| 1137 | intel_pt_calc_tsc_timestamp(decoder); | 1615 | intel_pt_calc_tsc_timestamp(decoder); |
| 1138 | break; | 1616 | break; |
| 1139 | 1617 | ||
| 1618 | case INTEL_PT_TMA: | ||
| 1619 | intel_pt_calc_tma(decoder); | ||
| 1620 | break; | ||
| 1621 | |||
| 1622 | case INTEL_PT_CYC: | ||
| 1623 | intel_pt_calc_cyc_timestamp(decoder); | ||
| 1624 | break; | ||
| 1625 | |||
| 1140 | case INTEL_PT_CBR: | 1626 | case INTEL_PT_CBR: |
| 1141 | decoder->cbr = decoder->packet.payload; | 1627 | intel_pt_calc_cbr(decoder); |
| 1142 | break; | 1628 | break; |
| 1143 | 1629 | ||
| 1144 | case INTEL_PT_MODE_EXEC: | 1630 | case INTEL_PT_MODE_EXEC: |
| @@ -1160,6 +1646,8 @@ next: | |||
| 1160 | return intel_pt_bug(decoder); | 1646 | return intel_pt_bug(decoder); |
| 1161 | 1647 | ||
| 1162 | case INTEL_PT_PSBEND: | 1648 | case INTEL_PT_PSBEND: |
| 1649 | case INTEL_PT_VMCS: | ||
| 1650 | case INTEL_PT_MNT: | ||
| 1163 | case INTEL_PT_PAD: | 1651 | case INTEL_PT_PAD: |
| 1164 | break; | 1652 | break; |
| 1165 | 1653 | ||
| @@ -1200,16 +1688,28 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
| 1200 | } | 1688 | } |
| 1201 | break; | 1689 | break; |
| 1202 | 1690 | ||
| 1691 | case INTEL_PT_MTC: | ||
| 1692 | intel_pt_calc_mtc_timestamp(decoder); | ||
| 1693 | break; | ||
| 1694 | |||
| 1203 | case INTEL_PT_TSC: | 1695 | case INTEL_PT_TSC: |
| 1204 | intel_pt_calc_tsc_timestamp(decoder); | 1696 | intel_pt_calc_tsc_timestamp(decoder); |
| 1205 | break; | 1697 | break; |
| 1206 | 1698 | ||
| 1699 | case INTEL_PT_TMA: | ||
| 1700 | intel_pt_calc_tma(decoder); | ||
| 1701 | break; | ||
| 1702 | |||
| 1703 | case INTEL_PT_CYC: | ||
| 1704 | intel_pt_calc_cyc_timestamp(decoder); | ||
| 1705 | break; | ||
| 1706 | |||
| 1207 | case INTEL_PT_CBR: | 1707 | case INTEL_PT_CBR: |
| 1208 | decoder->cbr = decoder->packet.payload; | 1708 | intel_pt_calc_cbr(decoder); |
| 1209 | break; | 1709 | break; |
| 1210 | 1710 | ||
| 1211 | case INTEL_PT_PIP: | 1711 | case INTEL_PT_PIP: |
| 1212 | decoder->cr3 = decoder->packet.payload; | 1712 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
| 1213 | break; | 1713 | break; |
| 1214 | 1714 | ||
| 1215 | case INTEL_PT_MODE_EXEC: | 1715 | case INTEL_PT_MODE_EXEC: |
| @@ -1220,7 +1720,12 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
| 1220 | intel_pt_update_in_tx(decoder); | 1720 | intel_pt_update_in_tx(decoder); |
| 1221 | break; | 1721 | break; |
| 1222 | 1722 | ||
| 1723 | case INTEL_PT_TRACESTOP: | ||
| 1724 | decoder->pge = false; | ||
| 1725 | decoder->continuous_period = false; | ||
| 1726 | intel_pt_clear_tx_flags(decoder); | ||
| 1223 | case INTEL_PT_TNT: | 1727 | case INTEL_PT_TNT: |
| 1728 | decoder->have_tma = false; | ||
| 1224 | intel_pt_log("ERROR: Unexpected packet\n"); | 1729 | intel_pt_log("ERROR: Unexpected packet\n"); |
| 1225 | if (decoder->ip) | 1730 | if (decoder->ip) |
| 1226 | decoder->pkt_state = INTEL_PT_STATE_ERR4; | 1731 | decoder->pkt_state = INTEL_PT_STATE_ERR4; |
| @@ -1238,6 +1743,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
| 1238 | return 0; | 1743 | return 0; |
| 1239 | 1744 | ||
| 1240 | case INTEL_PT_PSB: | 1745 | case INTEL_PT_PSB: |
| 1746 | case INTEL_PT_VMCS: | ||
| 1747 | case INTEL_PT_MNT: | ||
| 1241 | case INTEL_PT_PAD: | 1748 | case INTEL_PT_PAD: |
| 1242 | default: | 1749 | default: |
| 1243 | break; | 1750 | break; |
| @@ -1280,16 +1787,28 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
| 1280 | intel_pt_set_last_ip(decoder); | 1787 | intel_pt_set_last_ip(decoder); |
| 1281 | break; | 1788 | break; |
| 1282 | 1789 | ||
| 1790 | case INTEL_PT_MTC: | ||
| 1791 | intel_pt_calc_mtc_timestamp(decoder); | ||
| 1792 | break; | ||
| 1793 | |||
| 1283 | case INTEL_PT_TSC: | 1794 | case INTEL_PT_TSC: |
| 1284 | intel_pt_calc_tsc_timestamp(decoder); | 1795 | intel_pt_calc_tsc_timestamp(decoder); |
| 1285 | break; | 1796 | break; |
| 1286 | 1797 | ||
| 1798 | case INTEL_PT_TMA: | ||
| 1799 | intel_pt_calc_tma(decoder); | ||
| 1800 | break; | ||
| 1801 | |||
| 1802 | case INTEL_PT_CYC: | ||
| 1803 | intel_pt_calc_cyc_timestamp(decoder); | ||
| 1804 | break; | ||
| 1805 | |||
| 1287 | case INTEL_PT_CBR: | 1806 | case INTEL_PT_CBR: |
| 1288 | decoder->cbr = decoder->packet.payload; | 1807 | intel_pt_calc_cbr(decoder); |
| 1289 | break; | 1808 | break; |
| 1290 | 1809 | ||
| 1291 | case INTEL_PT_PIP: | 1810 | case INTEL_PT_PIP: |
| 1292 | decoder->cr3 = decoder->packet.payload; | 1811 | decoder->cr3 = decoder->packet.payload & (BIT63 - 1); |
| 1293 | break; | 1812 | break; |
| 1294 | 1813 | ||
| 1295 | case INTEL_PT_MODE_EXEC: | 1814 | case INTEL_PT_MODE_EXEC: |
| @@ -1306,6 +1825,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
| 1306 | case INTEL_PT_BAD: /* Does not happen */ | 1825 | case INTEL_PT_BAD: /* Does not happen */ |
| 1307 | return intel_pt_bug(decoder); | 1826 | return intel_pt_bug(decoder); |
| 1308 | 1827 | ||
| 1828 | case INTEL_PT_TRACESTOP: | ||
| 1829 | decoder->pge = false; | ||
| 1830 | decoder->continuous_period = false; | ||
| 1831 | intel_pt_clear_tx_flags(decoder); | ||
| 1832 | decoder->have_tma = false; | ||
| 1833 | break; | ||
| 1834 | |||
| 1309 | case INTEL_PT_PSB: | 1835 | case INTEL_PT_PSB: |
| 1310 | err = intel_pt_walk_psb(decoder); | 1836 | err = intel_pt_walk_psb(decoder); |
| 1311 | if (err) | 1837 | if (err) |
| @@ -1319,6 +1845,8 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
| 1319 | 1845 | ||
| 1320 | case INTEL_PT_TNT: | 1846 | case INTEL_PT_TNT: |
| 1321 | case INTEL_PT_PSBEND: | 1847 | case INTEL_PT_PSBEND: |
| 1848 | case INTEL_PT_VMCS: | ||
| 1849 | case INTEL_PT_MNT: | ||
| 1322 | case INTEL_PT_PAD: | 1850 | case INTEL_PT_PAD: |
| 1323 | default: | 1851 | default: |
| 1324 | break; | 1852 | break; |
| @@ -1529,6 +2057,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) | |||
| 1529 | decoder->state.timestamp = decoder->timestamp; | 2057 | decoder->state.timestamp = decoder->timestamp; |
| 1530 | decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); | 2058 | decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); |
| 1531 | decoder->state.cr3 = decoder->cr3; | 2059 | decoder->state.cr3 = decoder->cr3; |
| 2060 | decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; | ||
| 1532 | 2061 | ||
| 1533 | if (err) | 2062 | if (err) |
| 1534 | decoder->state.from_ip = decoder->ip; | 2063 | decoder->state.from_ip = decoder->ip; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 4c4880230cc9..02c38fec1c37 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | |||
| @@ -36,6 +36,7 @@ enum intel_pt_period_type { | |||
| 36 | INTEL_PT_PERIOD_NONE, | 36 | INTEL_PT_PERIOD_NONE, |
| 37 | INTEL_PT_PERIOD_INSTRUCTIONS, | 37 | INTEL_PT_PERIOD_INSTRUCTIONS, |
| 38 | INTEL_PT_PERIOD_TICKS, | 38 | INTEL_PT_PERIOD_TICKS, |
| 39 | INTEL_PT_PERIOD_MTC, | ||
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | enum { | 42 | enum { |
| @@ -58,6 +59,7 @@ struct intel_pt_state { | |||
| 58 | uint64_t from_ip; | 59 | uint64_t from_ip; |
| 59 | uint64_t to_ip; | 60 | uint64_t to_ip; |
| 60 | uint64_t cr3; | 61 | uint64_t cr3; |
| 62 | uint64_t tot_insn_cnt; | ||
| 61 | uint64_t timestamp; | 63 | uint64_t timestamp; |
| 62 | uint64_t est_timestamp; | 64 | uint64_t est_timestamp; |
| 63 | uint64_t trace_nr; | 65 | uint64_t trace_nr; |
| @@ -86,6 +88,9 @@ struct intel_pt_params { | |||
| 86 | uint64_t period; | 88 | uint64_t period; |
| 87 | enum intel_pt_period_type period_type; | 89 | enum intel_pt_period_type period_type; |
| 88 | unsigned max_non_turbo_ratio; | 90 | unsigned max_non_turbo_ratio; |
| 91 | unsigned int mtc_period; | ||
| 92 | uint32_t tsc_ctc_ratio_n; | ||
| 93 | uint32_t tsc_ctc_ratio_d; | ||
| 89 | }; | 94 | }; |
| 90 | 95 | ||
| 91 | struct intel_pt_decoder; | 96 | struct intel_pt_decoder; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c index 46980fc663ac..9e4eb8fcd559 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | #include "event.h" | 21 | #include "event.h" |
| 22 | 22 | ||
| 23 | #include <asm/insn.h> | 23 | #include "insn.h" |
| 24 | 24 | ||
| 25 | #include "inat.c" | 25 | #include "inat.c" |
| 26 | #include "insn.c" | 26 | #include "insn.c" |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c index 988c82c6652d..b1257c816310 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | 24 | ||
| 25 | #define BIT63 ((uint64_t)1 << 63) | 25 | #define BIT63 ((uint64_t)1 << 63) |
| 26 | 26 | ||
| 27 | #define NR_FLAG BIT63 | ||
| 28 | |||
| 27 | #if __BYTE_ORDER == __BIG_ENDIAN | 29 | #if __BYTE_ORDER == __BIG_ENDIAN |
| 28 | #define le16_to_cpu bswap_16 | 30 | #define le16_to_cpu bswap_16 |
| 29 | #define le32_to_cpu bswap_32 | 31 | #define le32_to_cpu bswap_32 |
| @@ -46,15 +48,21 @@ static const char * const packet_name[] = { | |||
| 46 | [INTEL_PT_TIP_PGD] = "TIP.PGD", | 48 | [INTEL_PT_TIP_PGD] = "TIP.PGD", |
| 47 | [INTEL_PT_TIP_PGE] = "TIP.PGE", | 49 | [INTEL_PT_TIP_PGE] = "TIP.PGE", |
| 48 | [INTEL_PT_TSC] = "TSC", | 50 | [INTEL_PT_TSC] = "TSC", |
| 51 | [INTEL_PT_TMA] = "TMA", | ||
| 49 | [INTEL_PT_MODE_EXEC] = "MODE.Exec", | 52 | [INTEL_PT_MODE_EXEC] = "MODE.Exec", |
| 50 | [INTEL_PT_MODE_TSX] = "MODE.TSX", | 53 | [INTEL_PT_MODE_TSX] = "MODE.TSX", |
| 54 | [INTEL_PT_MTC] = "MTC", | ||
| 51 | [INTEL_PT_TIP] = "TIP", | 55 | [INTEL_PT_TIP] = "TIP", |
| 52 | [INTEL_PT_FUP] = "FUP", | 56 | [INTEL_PT_FUP] = "FUP", |
| 57 | [INTEL_PT_CYC] = "CYC", | ||
| 58 | [INTEL_PT_VMCS] = "VMCS", | ||
| 53 | [INTEL_PT_PSB] = "PSB", | 59 | [INTEL_PT_PSB] = "PSB", |
| 54 | [INTEL_PT_PSBEND] = "PSBEND", | 60 | [INTEL_PT_PSBEND] = "PSBEND", |
| 55 | [INTEL_PT_CBR] = "CBR", | 61 | [INTEL_PT_CBR] = "CBR", |
| 62 | [INTEL_PT_TRACESTOP] = "TraceSTOP", | ||
| 56 | [INTEL_PT_PIP] = "PIP", | 63 | [INTEL_PT_PIP] = "PIP", |
| 57 | [INTEL_PT_OVF] = "OVF", | 64 | [INTEL_PT_OVF] = "OVF", |
| 65 | [INTEL_PT_MNT] = "MNT", | ||
| 58 | }; | 66 | }; |
| 59 | 67 | ||
| 60 | const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) | 68 | const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) |
| @@ -96,10 +104,18 @@ static int intel_pt_get_pip(const unsigned char *buf, size_t len, | |||
| 96 | packet->type = INTEL_PT_PIP; | 104 | packet->type = INTEL_PT_PIP; |
| 97 | memcpy_le64(&payload, buf + 2, 6); | 105 | memcpy_le64(&payload, buf + 2, 6); |
| 98 | packet->payload = payload >> 1; | 106 | packet->payload = payload >> 1; |
| 107 | if (payload & 1) | ||
| 108 | packet->payload |= NR_FLAG; | ||
| 99 | 109 | ||
| 100 | return 8; | 110 | return 8; |
| 101 | } | 111 | } |
| 102 | 112 | ||
| 113 | static int intel_pt_get_tracestop(struct intel_pt_pkt *packet) | ||
| 114 | { | ||
| 115 | packet->type = INTEL_PT_TRACESTOP; | ||
| 116 | return 2; | ||
| 117 | } | ||
| 118 | |||
| 103 | static int intel_pt_get_cbr(const unsigned char *buf, size_t len, | 119 | static int intel_pt_get_cbr(const unsigned char *buf, size_t len, |
| 104 | struct intel_pt_pkt *packet) | 120 | struct intel_pt_pkt *packet) |
| 105 | { | 121 | { |
| @@ -110,6 +126,24 @@ static int intel_pt_get_cbr(const unsigned char *buf, size_t len, | |||
| 110 | return 4; | 126 | return 4; |
| 111 | } | 127 | } |
| 112 | 128 | ||
| 129 | static int intel_pt_get_vmcs(const unsigned char *buf, size_t len, | ||
| 130 | struct intel_pt_pkt *packet) | ||
| 131 | { | ||
| 132 | unsigned int count = (52 - 5) >> 3; | ||
| 133 | |||
| 134 | if (count < 1 || count > 7) | ||
| 135 | return INTEL_PT_BAD_PACKET; | ||
| 136 | |||
| 137 | if (len < count + 2) | ||
| 138 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 139 | |||
| 140 | packet->type = INTEL_PT_VMCS; | ||
| 141 | packet->count = count; | ||
| 142 | memcpy_le64(&packet->payload, buf + 2, count); | ||
| 143 | |||
| 144 | return count + 2; | ||
| 145 | } | ||
| 146 | |||
| 113 | static int intel_pt_get_ovf(struct intel_pt_pkt *packet) | 147 | static int intel_pt_get_ovf(struct intel_pt_pkt *packet) |
| 114 | { | 148 | { |
| 115 | packet->type = INTEL_PT_OVF; | 149 | packet->type = INTEL_PT_OVF; |
| @@ -139,12 +173,49 @@ static int intel_pt_get_psbend(struct intel_pt_pkt *packet) | |||
| 139 | return 2; | 173 | return 2; |
| 140 | } | 174 | } |
| 141 | 175 | ||
| 176 | static int intel_pt_get_tma(const unsigned char *buf, size_t len, | ||
| 177 | struct intel_pt_pkt *packet) | ||
| 178 | { | ||
| 179 | if (len < 7) | ||
| 180 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 181 | |||
| 182 | packet->type = INTEL_PT_TMA; | ||
| 183 | packet->payload = buf[2] | (buf[3] << 8); | ||
| 184 | packet->count = buf[5] | ((buf[6] & BIT(0)) << 8); | ||
| 185 | return 7; | ||
| 186 | } | ||
| 187 | |||
| 142 | static int intel_pt_get_pad(struct intel_pt_pkt *packet) | 188 | static int intel_pt_get_pad(struct intel_pt_pkt *packet) |
| 143 | { | 189 | { |
| 144 | packet->type = INTEL_PT_PAD; | 190 | packet->type = INTEL_PT_PAD; |
| 145 | return 1; | 191 | return 1; |
| 146 | } | 192 | } |
| 147 | 193 | ||
| 194 | static int intel_pt_get_mnt(const unsigned char *buf, size_t len, | ||
| 195 | struct intel_pt_pkt *packet) | ||
| 196 | { | ||
| 197 | if (len < 11) | ||
| 198 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 199 | packet->type = INTEL_PT_MNT; | ||
| 200 | memcpy_le64(&packet->payload, buf + 3, 8); | ||
| 201 | return 11 | ||
| 202 | ; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int intel_pt_get_3byte(const unsigned char *buf, size_t len, | ||
| 206 | struct intel_pt_pkt *packet) | ||
| 207 | { | ||
| 208 | if (len < 3) | ||
| 209 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 210 | |||
| 211 | switch (buf[2]) { | ||
| 212 | case 0x88: /* MNT */ | ||
| 213 | return intel_pt_get_mnt(buf, len, packet); | ||
| 214 | default: | ||
| 215 | return INTEL_PT_BAD_PACKET; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 148 | static int intel_pt_get_ext(const unsigned char *buf, size_t len, | 219 | static int intel_pt_get_ext(const unsigned char *buf, size_t len, |
| 149 | struct intel_pt_pkt *packet) | 220 | struct intel_pt_pkt *packet) |
| 150 | { | 221 | { |
| @@ -156,14 +227,22 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len, | |||
| 156 | return intel_pt_get_long_tnt(buf, len, packet); | 227 | return intel_pt_get_long_tnt(buf, len, packet); |
| 157 | case 0x43: /* PIP */ | 228 | case 0x43: /* PIP */ |
| 158 | return intel_pt_get_pip(buf, len, packet); | 229 | return intel_pt_get_pip(buf, len, packet); |
| 230 | case 0x83: /* TraceStop */ | ||
| 231 | return intel_pt_get_tracestop(packet); | ||
| 159 | case 0x03: /* CBR */ | 232 | case 0x03: /* CBR */ |
| 160 | return intel_pt_get_cbr(buf, len, packet); | 233 | return intel_pt_get_cbr(buf, len, packet); |
| 234 | case 0xc8: /* VMCS */ | ||
| 235 | return intel_pt_get_vmcs(buf, len, packet); | ||
| 161 | case 0xf3: /* OVF */ | 236 | case 0xf3: /* OVF */ |
| 162 | return intel_pt_get_ovf(packet); | 237 | return intel_pt_get_ovf(packet); |
| 163 | case 0x82: /* PSB */ | 238 | case 0x82: /* PSB */ |
| 164 | return intel_pt_get_psb(buf, len, packet); | 239 | return intel_pt_get_psb(buf, len, packet); |
| 165 | case 0x23: /* PSBEND */ | 240 | case 0x23: /* PSBEND */ |
| 166 | return intel_pt_get_psbend(packet); | 241 | return intel_pt_get_psbend(packet); |
| 242 | case 0x73: /* TMA */ | ||
| 243 | return intel_pt_get_tma(buf, len, packet); | ||
| 244 | case 0xC3: /* 3-byte header */ | ||
| 245 | return intel_pt_get_3byte(buf, len, packet); | ||
| 167 | default: | 246 | default: |
| 168 | return INTEL_PT_BAD_PACKET; | 247 | return INTEL_PT_BAD_PACKET; |
| 169 | } | 248 | } |
| @@ -187,6 +266,28 @@ static int intel_pt_get_short_tnt(unsigned int byte, | |||
| 187 | return 1; | 266 | return 1; |
| 188 | } | 267 | } |
| 189 | 268 | ||
| 269 | static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, | ||
| 270 | size_t len, struct intel_pt_pkt *packet) | ||
| 271 | { | ||
| 272 | unsigned int offs = 1, shift; | ||
| 273 | uint64_t payload = byte >> 3; | ||
| 274 | |||
| 275 | byte >>= 2; | ||
| 276 | len -= 1; | ||
| 277 | for (shift = 5; byte & 1; shift += 7) { | ||
| 278 | if (offs > 9) | ||
| 279 | return INTEL_PT_BAD_PACKET; | ||
| 280 | if (len < offs) | ||
| 281 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 282 | byte = buf[offs++]; | ||
| 283 | payload |= (byte >> 1) << shift; | ||
| 284 | } | ||
| 285 | |||
| 286 | packet->type = INTEL_PT_CYC; | ||
| 287 | packet->payload = payload; | ||
| 288 | return offs; | ||
| 289 | } | ||
| 290 | |||
| 190 | static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, | 291 | static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, |
| 191 | const unsigned char *buf, size_t len, | 292 | const unsigned char *buf, size_t len, |
| 192 | struct intel_pt_pkt *packet) | 293 | struct intel_pt_pkt *packet) |
| @@ -269,6 +370,16 @@ static int intel_pt_get_tsc(const unsigned char *buf, size_t len, | |||
| 269 | return 8; | 370 | return 8; |
| 270 | } | 371 | } |
| 271 | 372 | ||
| 373 | static int intel_pt_get_mtc(const unsigned char *buf, size_t len, | ||
| 374 | struct intel_pt_pkt *packet) | ||
| 375 | { | ||
| 376 | if (len < 2) | ||
| 377 | return INTEL_PT_NEED_MORE_BYTES; | ||
| 378 | packet->type = INTEL_PT_MTC; | ||
| 379 | packet->payload = buf[1]; | ||
| 380 | return 2; | ||
| 381 | } | ||
| 382 | |||
| 272 | static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | 383 | static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, |
| 273 | struct intel_pt_pkt *packet) | 384 | struct intel_pt_pkt *packet) |
| 274 | { | 385 | { |
| @@ -288,6 +399,9 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | |||
| 288 | return intel_pt_get_short_tnt(byte, packet); | 399 | return intel_pt_get_short_tnt(byte, packet); |
| 289 | } | 400 | } |
| 290 | 401 | ||
| 402 | if ((byte & 2)) | ||
| 403 | return intel_pt_get_cyc(byte, buf, len, packet); | ||
| 404 | |||
| 291 | switch (byte & 0x1f) { | 405 | switch (byte & 0x1f) { |
| 292 | case 0x0D: | 406 | case 0x0D: |
| 293 | return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); | 407 | return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); |
| @@ -305,6 +419,8 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, | |||
| 305 | return intel_pt_get_mode(buf, len, packet); | 419 | return intel_pt_get_mode(buf, len, packet); |
| 306 | case 0x19: | 420 | case 0x19: |
| 307 | return intel_pt_get_tsc(buf, len, packet); | 421 | return intel_pt_get_tsc(buf, len, packet); |
| 422 | case 0x59: | ||
| 423 | return intel_pt_get_mtc(buf, len, packet); | ||
| 308 | default: | 424 | default: |
| 309 | return INTEL_PT_BAD_PACKET; | 425 | return INTEL_PT_BAD_PACKET; |
| 310 | } | 426 | } |
| @@ -329,7 +445,7 @@ int intel_pt_get_packet(const unsigned char *buf, size_t len, | |||
| 329 | int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | 445 | int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, |
| 330 | size_t buf_len) | 446 | size_t buf_len) |
| 331 | { | 447 | { |
| 332 | int ret, i; | 448 | int ret, i, nr; |
| 333 | unsigned long long payload = packet->payload; | 449 | unsigned long long payload = packet->payload; |
| 334 | const char *name = intel_pt_pkt_name(packet->type); | 450 | const char *name = intel_pt_pkt_name(packet->type); |
| 335 | 451 | ||
| @@ -338,6 +454,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
| 338 | case INTEL_PT_PAD: | 454 | case INTEL_PT_PAD: |
| 339 | case INTEL_PT_PSB: | 455 | case INTEL_PT_PSB: |
| 340 | case INTEL_PT_PSBEND: | 456 | case INTEL_PT_PSBEND: |
| 457 | case INTEL_PT_TRACESTOP: | ||
| 341 | case INTEL_PT_OVF: | 458 | case INTEL_PT_OVF: |
| 342 | return snprintf(buf, buf_len, "%s", name); | 459 | return snprintf(buf, buf_len, "%s", name); |
| 343 | case INTEL_PT_TNT: { | 460 | case INTEL_PT_TNT: { |
| @@ -371,17 +488,16 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
| 371 | case INTEL_PT_FUP: | 488 | case INTEL_PT_FUP: |
| 372 | if (!(packet->count)) | 489 | if (!(packet->count)) |
| 373 | return snprintf(buf, buf_len, "%s no ip", name); | 490 | return snprintf(buf, buf_len, "%s no ip", name); |
| 491 | case INTEL_PT_CYC: | ||
| 492 | case INTEL_PT_VMCS: | ||
| 493 | case INTEL_PT_MTC: | ||
| 494 | case INTEL_PT_MNT: | ||
| 374 | case INTEL_PT_CBR: | 495 | case INTEL_PT_CBR: |
| 375 | return snprintf(buf, buf_len, "%s 0x%llx", name, payload); | ||
| 376 | case INTEL_PT_TSC: | 496 | case INTEL_PT_TSC: |
| 377 | if (packet->count) | 497 | return snprintf(buf, buf_len, "%s 0x%llx", name, payload); |
| 378 | return snprintf(buf, buf_len, | 498 | case INTEL_PT_TMA: |
| 379 | "%s 0x%llx CTC 0x%x FC 0x%x", | 499 | return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name, |
| 380 | name, payload, packet->count & 0xffff, | 500 | (unsigned)payload, packet->count); |
| 381 | (packet->count >> 16) & 0x1ff); | ||
| 382 | else | ||
| 383 | return snprintf(buf, buf_len, "%s 0x%llx", | ||
| 384 | name, payload); | ||
| 385 | case INTEL_PT_MODE_EXEC: | 501 | case INTEL_PT_MODE_EXEC: |
| 386 | return snprintf(buf, buf_len, "%s %lld", name, payload); | 502 | return snprintf(buf, buf_len, "%s %lld", name, payload); |
| 387 | case INTEL_PT_MODE_TSX: | 503 | case INTEL_PT_MODE_TSX: |
| @@ -389,8 +505,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |||
| 389 | name, (unsigned)(payload >> 1) & 1, | 505 | name, (unsigned)(payload >> 1) & 1, |
| 390 | (unsigned)payload & 1); | 506 | (unsigned)payload & 1); |
| 391 | case INTEL_PT_PIP: | 507 | case INTEL_PT_PIP: |
| 392 | ret = snprintf(buf, buf_len, "%s 0x%llx", | 508 | nr = packet->payload & NR_FLAG ? 1 : 0; |
| 393 | name, payload); | 509 | payload &= ~NR_FLAG; |
| 510 | ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", | ||
| 511 | name, payload, nr); | ||
| 394 | return ret; | 512 | return ret; |
| 395 | default: | 513 | default: |
| 396 | break; | 514 | break; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h index 53404fa942b3..781bb79883bd 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h | |||
| @@ -37,15 +37,21 @@ enum intel_pt_pkt_type { | |||
| 37 | INTEL_PT_TIP_PGD, | 37 | INTEL_PT_TIP_PGD, |
| 38 | INTEL_PT_TIP_PGE, | 38 | INTEL_PT_TIP_PGE, |
| 39 | INTEL_PT_TSC, | 39 | INTEL_PT_TSC, |
| 40 | INTEL_PT_TMA, | ||
| 40 | INTEL_PT_MODE_EXEC, | 41 | INTEL_PT_MODE_EXEC, |
| 41 | INTEL_PT_MODE_TSX, | 42 | INTEL_PT_MODE_TSX, |
| 43 | INTEL_PT_MTC, | ||
| 42 | INTEL_PT_TIP, | 44 | INTEL_PT_TIP, |
| 43 | INTEL_PT_FUP, | 45 | INTEL_PT_FUP, |
| 46 | INTEL_PT_CYC, | ||
| 47 | INTEL_PT_VMCS, | ||
| 44 | INTEL_PT_PSB, | 48 | INTEL_PT_PSB, |
| 45 | INTEL_PT_PSBEND, | 49 | INTEL_PT_PSBEND, |
| 46 | INTEL_PT_CBR, | 50 | INTEL_PT_CBR, |
| 51 | INTEL_PT_TRACESTOP, | ||
| 47 | INTEL_PT_PIP, | 52 | INTEL_PT_PIP, |
| 48 | INTEL_PT_OVF, | 53 | INTEL_PT_OVF, |
| 54 | INTEL_PT_MNT, | ||
| 49 | }; | 55 | }; |
| 50 | 56 | ||
| 51 | struct intel_pt_pkt { | 57 | struct intel_pt_pkt { |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index a5acd2fe2447..bb41c20e6005 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
| @@ -91,6 +91,11 @@ struct intel_pt { | |||
| 91 | bool synth_needs_swap; | 91 | bool synth_needs_swap; |
| 92 | 92 | ||
| 93 | u64 tsc_bit; | 93 | u64 tsc_bit; |
| 94 | u64 mtc_bit; | ||
| 95 | u64 mtc_freq_bits; | ||
| 96 | u32 tsc_ctc_ratio_n; | ||
| 97 | u32 tsc_ctc_ratio_d; | ||
| 98 | u64 cyc_bit; | ||
| 94 | u64 noretcomp_bit; | 99 | u64 noretcomp_bit; |
| 95 | unsigned max_non_turbo_ratio; | 100 | unsigned max_non_turbo_ratio; |
| 96 | }; | 101 | }; |
| @@ -126,6 +131,7 @@ struct intel_pt_queue { | |||
| 126 | u64 timestamp; | 131 | u64 timestamp; |
| 127 | u32 flags; | 132 | u32 flags; |
| 128 | u16 insn_len; | 133 | u16 insn_len; |
| 134 | u64 last_insn_cnt; | ||
| 129 | }; | 135 | }; |
| 130 | 136 | ||
| 131 | static void intel_pt_dump(struct intel_pt *pt __maybe_unused, | 137 | static void intel_pt_dump(struct intel_pt *pt __maybe_unused, |
| @@ -567,6 +573,25 @@ static bool intel_pt_return_compression(struct intel_pt *pt) | |||
| 567 | return true; | 573 | return true; |
| 568 | } | 574 | } |
| 569 | 575 | ||
| 576 | static unsigned int intel_pt_mtc_period(struct intel_pt *pt) | ||
| 577 | { | ||
| 578 | struct perf_evsel *evsel; | ||
| 579 | unsigned int shift; | ||
| 580 | u64 config; | ||
| 581 | |||
| 582 | if (!pt->mtc_freq_bits) | ||
| 583 | return 0; | ||
| 584 | |||
| 585 | for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) | ||
| 586 | config >>= 1; | ||
| 587 | |||
| 588 | evlist__for_each(pt->session->evlist, evsel) { | ||
| 589 | if (intel_pt_get_config(pt, &evsel->attr, &config)) | ||
| 590 | return (config & pt->mtc_freq_bits) >> shift; | ||
| 591 | } | ||
| 592 | return 0; | ||
| 593 | } | ||
| 594 | |||
| 570 | static bool intel_pt_timeless_decoding(struct intel_pt *pt) | 595 | static bool intel_pt_timeless_decoding(struct intel_pt *pt) |
| 571 | { | 596 | { |
| 572 | struct perf_evsel *evsel; | 597 | struct perf_evsel *evsel; |
| @@ -667,6 +692,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, | |||
| 667 | params.data = ptq; | 692 | params.data = ptq; |
| 668 | params.return_compression = intel_pt_return_compression(pt); | 693 | params.return_compression = intel_pt_return_compression(pt); |
| 669 | params.max_non_turbo_ratio = pt->max_non_turbo_ratio; | 694 | params.max_non_turbo_ratio = pt->max_non_turbo_ratio; |
| 695 | params.mtc_period = intel_pt_mtc_period(pt); | ||
| 696 | params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; | ||
| 697 | params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; | ||
| 670 | 698 | ||
| 671 | if (pt->synth_opts.instructions) { | 699 | if (pt->synth_opts.instructions) { |
| 672 | if (pt->synth_opts.period) { | 700 | if (pt->synth_opts.period) { |
| @@ -920,11 +948,13 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | |||
| 920 | sample.addr = ptq->state->to_ip; | 948 | sample.addr = ptq->state->to_ip; |
| 921 | sample.id = ptq->pt->instructions_id; | 949 | sample.id = ptq->pt->instructions_id; |
| 922 | sample.stream_id = ptq->pt->instructions_id; | 950 | sample.stream_id = ptq->pt->instructions_id; |
| 923 | sample.period = ptq->pt->instructions_sample_period; | 951 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; |
| 924 | sample.cpu = ptq->cpu; | 952 | sample.cpu = ptq->cpu; |
| 925 | sample.flags = ptq->flags; | 953 | sample.flags = ptq->flags; |
| 926 | sample.insn_len = ptq->insn_len; | 954 | sample.insn_len = ptq->insn_len; |
| 927 | 955 | ||
| 956 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; | ||
| 957 | |||
| 928 | if (pt->synth_opts.callchain) { | 958 | if (pt->synth_opts.callchain) { |
| 929 | thread_stack__sample(ptq->thread, ptq->chain, | 959 | thread_stack__sample(ptq->thread, ptq->chain, |
| 930 | pt->synth_opts.callchain_sz, sample.ip); | 960 | pt->synth_opts.callchain_sz, sample.ip); |
| @@ -1748,16 +1778,20 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) | |||
| 1748 | } | 1778 | } |
| 1749 | 1779 | ||
| 1750 | static const char * const intel_pt_info_fmts[] = { | 1780 | static const char * const intel_pt_info_fmts[] = { |
| 1751 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", | 1781 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", |
| 1752 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", | 1782 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", |
| 1753 | [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", | 1783 | [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", |
| 1754 | [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", | 1784 | [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", |
| 1755 | [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", | 1785 | [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", |
| 1756 | [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n", | 1786 | [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n", |
| 1757 | [INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n", | 1787 | [INTEL_PT_NORETCOMP_BIT] = " NoRETComp bit %#"PRIx64"\n", |
| 1758 | [INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n", | 1788 | [INTEL_PT_HAVE_SCHED_SWITCH] = " Have sched_switch %"PRId64"\n", |
| 1759 | [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", | 1789 | [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", |
| 1760 | [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", | 1790 | [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", |
| 1791 | [INTEL_PT_MTC_BIT] = " MTC bit %#"PRIx64"\n", | ||
| 1792 | [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", | ||
| 1793 | [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", | ||
| 1794 | [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", | ||
| 1761 | }; | 1795 | }; |
| 1762 | 1796 | ||
| 1763 | static void intel_pt_print_info(u64 *arr, int start, int finish) | 1797 | static void intel_pt_print_info(u64 *arr, int start, int finish) |
| @@ -1809,6 +1843,17 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
| 1809 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, | 1843 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, |
| 1810 | INTEL_PT_PER_CPU_MMAPS); | 1844 | INTEL_PT_PER_CPU_MMAPS); |
| 1811 | 1845 | ||
| 1846 | if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + | ||
| 1847 | (sizeof(u64) * INTEL_PT_CYC_BIT)) { | ||
| 1848 | pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; | ||
| 1849 | pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; | ||
| 1850 | pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; | ||
| 1851 | pt->tsc_ctc_ratio_d = auxtrace_info->priv[INTEL_PT_TSC_CTC_D]; | ||
| 1852 | pt->cyc_bit = auxtrace_info->priv[INTEL_PT_CYC_BIT]; | ||
| 1853 | intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_MTC_BIT, | ||
| 1854 | INTEL_PT_CYC_BIT); | ||
| 1855 | } | ||
| 1856 | |||
| 1812 | pt->timeless_decoding = intel_pt_timeless_decoding(pt); | 1857 | pt->timeless_decoding = intel_pt_timeless_decoding(pt); |
| 1813 | pt->have_tsc = intel_pt_have_tsc(pt); | 1858 | pt->have_tsc = intel_pt_have_tsc(pt); |
| 1814 | pt->sampling_mode = false; | 1859 | pt->sampling_mode = false; |
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h index a1bfe93473ba..0065949df693 100644 --- a/tools/perf/util/intel-pt.h +++ b/tools/perf/util/intel-pt.h | |||
| @@ -29,6 +29,11 @@ enum { | |||
| 29 | INTEL_PT_HAVE_SCHED_SWITCH, | 29 | INTEL_PT_HAVE_SCHED_SWITCH, |
| 30 | INTEL_PT_SNAPSHOT_MODE, | 30 | INTEL_PT_SNAPSHOT_MODE, |
| 31 | INTEL_PT_PER_CPU_MMAPS, | 31 | INTEL_PT_PER_CPU_MMAPS, |
| 32 | INTEL_PT_MTC_BIT, | ||
| 33 | INTEL_PT_MTC_FREQ_BITS, | ||
| 34 | INTEL_PT_TSC_CTC_N, | ||
| 35 | INTEL_PT_TSC_CTC_D, | ||
| 36 | INTEL_PT_CYC_BIT, | ||
| 32 | INTEL_PT_AUXTRACE_PRIV_MAX, | 37 | INTEL_PT_AUXTRACE_PRIV_MAX, |
| 33 | }; | 38 | }; |
| 34 | 39 | ||
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c index 52be201b9b25..b1b9e2385f4b 100644 --- a/tools/perf/util/ordered-events.c +++ b/tools/perf/util/ordered-events.c | |||
| @@ -220,6 +220,9 @@ static int __ordered_events__flush(struct ordered_events *oe) | |||
| 220 | else if (last_ts <= limit) | 220 | else if (last_ts <= limit) |
| 221 | oe->last = list_entry(head->prev, struct ordered_event, list); | 221 | oe->last = list_entry(head->prev, struct ordered_event, list); |
| 222 | 222 | ||
| 223 | if (show_progress) | ||
| 224 | ui_progress__finish(); | ||
| 225 | |||
| 223 | return 0; | 226 | return 0; |
| 224 | } | 227 | } |
| 225 | 228 | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f07374bc9c5a..eb5f18b75402 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -515,7 +515,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp, | |||
| 515 | if (ret < 0) | 515 | if (ret < 0) |
| 516 | goto error; | 516 | goto error; |
| 517 | addr += stext; | 517 | addr += stext; |
| 518 | } else { | 518 | } else if (tp->symbol) { |
| 519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); | 519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); |
| 520 | if (addr == 0) | 520 | if (addr == 0) |
| 521 | goto error; | 521 | goto error; |
| @@ -1194,15 +1194,37 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | |||
| 1194 | *ptr++ = '\0'; | 1194 | *ptr++ = '\0'; |
| 1195 | } | 1195 | } |
| 1196 | 1196 | ||
| 1197 | tmp = strdup(arg); | 1197 | if (arg[0] == '\0') |
| 1198 | if (tmp == NULL) | 1198 | tmp = NULL; |
| 1199 | return -ENOMEM; | 1199 | else { |
| 1200 | tmp = strdup(arg); | ||
| 1201 | if (tmp == NULL) | ||
| 1202 | return -ENOMEM; | ||
| 1203 | } | ||
| 1200 | 1204 | ||
| 1201 | if (file_spec) | 1205 | if (file_spec) |
| 1202 | pp->file = tmp; | 1206 | pp->file = tmp; |
| 1203 | else | 1207 | else { |
| 1204 | pp->function = tmp; | 1208 | pp->function = tmp; |
| 1205 | 1209 | ||
| 1210 | /* | ||
| 1211 | * Keep pp->function even if this is absolute address, | ||
| 1212 | * so it can mark whether abs_address is valid. | ||
| 1213 | * Which make 'perf probe lib.bin 0x0' possible. | ||
| 1214 | * | ||
| 1215 | * Note that checking length of tmp is not needed | ||
| 1216 | * because when we access tmp[1] we know tmp[0] is '0', | ||
| 1217 | * so tmp[1] should always valid (but could be '\0'). | ||
| 1218 | */ | ||
| 1219 | if (tmp && !strncmp(tmp, "0x", 2)) { | ||
| 1220 | pp->abs_address = strtoul(pp->function, &tmp, 0); | ||
| 1221 | if (*tmp != '\0') { | ||
| 1222 | semantic_error("Invalid absolute address.\n"); | ||
| 1223 | return -EINVAL; | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | |||
| 1206 | /* Parse other options */ | 1228 | /* Parse other options */ |
| 1207 | while (ptr) { | 1229 | while (ptr) { |
| 1208 | arg = ptr; | 1230 | arg = ptr; |
| @@ -1519,9 +1541,31 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev) | |||
| 1519 | } else | 1541 | } else |
| 1520 | p = argv[1]; | 1542 | p = argv[1]; |
| 1521 | fmt1_str = strtok_r(p, "+", &fmt); | 1543 | fmt1_str = strtok_r(p, "+", &fmt); |
| 1522 | if (fmt1_str[0] == '0') /* only the address started with 0x */ | 1544 | /* only the address started with 0x */ |
| 1523 | tp->address = strtoul(fmt1_str, NULL, 0); | 1545 | if (fmt1_str[0] == '0') { |
| 1524 | else { | 1546 | /* |
| 1547 | * Fix a special case: | ||
| 1548 | * if address == 0, kernel reports something like: | ||
| 1549 | * p:probe_libc/abs_0 /lib/libc-2.18.so:0x (null) arg1=%ax | ||
| 1550 | * Newer kernel may fix that, but we want to | ||
| 1551 | * support old kernel also. | ||
| 1552 | */ | ||
| 1553 | if (strcmp(fmt1_str, "0x") == 0) { | ||
| 1554 | if (!argv[2] || strcmp(argv[2], "(null)")) { | ||
| 1555 | ret = -EINVAL; | ||
| 1556 | goto out; | ||
| 1557 | } | ||
| 1558 | tp->address = 0; | ||
| 1559 | |||
| 1560 | free(argv[2]); | ||
| 1561 | for (i = 2; argv[i + 1] != NULL; i++) | ||
| 1562 | argv[i] = argv[i + 1]; | ||
| 1563 | |||
| 1564 | argv[i] = NULL; | ||
| 1565 | argc -= 1; | ||
| 1566 | } else | ||
| 1567 | tp->address = strtoul(fmt1_str, NULL, 0); | ||
| 1568 | } else { | ||
| 1525 | /* Only the symbol-based probe has offset */ | 1569 | /* Only the symbol-based probe has offset */ |
| 1526 | tp->symbol = strdup(fmt1_str); | 1570 | tp->symbol = strdup(fmt1_str); |
| 1527 | if (tp->symbol == NULL) { | 1571 | if (tp->symbol == NULL) { |
| @@ -1778,14 +1822,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) | |||
| 1778 | if (len <= 0) | 1822 | if (len <= 0) |
| 1779 | goto error; | 1823 | goto error; |
| 1780 | 1824 | ||
| 1781 | /* Uprobes must have tp->address and tp->module */ | 1825 | /* Uprobes must have tp->module */ |
| 1782 | if (tev->uprobes && (!tp->address || !tp->module)) | 1826 | if (tev->uprobes && !tp->module) |
| 1783 | goto error; | 1827 | goto error; |
| 1828 | /* | ||
| 1829 | * If tp->address == 0, then this point must be a | ||
| 1830 | * absolute address uprobe. | ||
| 1831 | * try_to_find_absolute_address() should have made | ||
| 1832 | * tp->symbol to "0x0". | ||
| 1833 | */ | ||
| 1834 | if (tev->uprobes && !tp->address) { | ||
| 1835 | if (!tp->symbol || strcmp(tp->symbol, "0x0")) | ||
| 1836 | goto error; | ||
| 1837 | } | ||
| 1784 | 1838 | ||
| 1785 | /* Use the tp->address for uprobes */ | 1839 | /* Use the tp->address for uprobes */ |
| 1786 | if (tev->uprobes) | 1840 | if (tev->uprobes) |
| 1787 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", | 1841 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", |
| 1788 | tp->module, tp->address); | 1842 | tp->module, tp->address); |
| 1843 | else if (!strncmp(tp->symbol, "0x", 2)) | ||
| 1844 | /* Absolute address. See try_to_find_absolute_address() */ | ||
| 1845 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", | ||
| 1846 | tp->module ?: "", tp->module ? ":" : "", | ||
| 1847 | tp->address); | ||
| 1789 | else | 1848 | else |
| 1790 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", | 1849 | ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", |
| 1791 | tp->module ?: "", tp->module ? ":" : "", | 1850 | tp->module ?: "", tp->module ? ":" : "", |
| @@ -1815,17 +1874,17 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, | |||
| 1815 | { | 1874 | { |
| 1816 | struct symbol *sym = NULL; | 1875 | struct symbol *sym = NULL; |
| 1817 | struct map *map; | 1876 | struct map *map; |
| 1818 | u64 addr; | 1877 | u64 addr = tp->address; |
| 1819 | int ret = -ENOENT; | 1878 | int ret = -ENOENT; |
| 1820 | 1879 | ||
| 1821 | if (!is_kprobe) { | 1880 | if (!is_kprobe) { |
| 1822 | map = dso__new_map(tp->module); | 1881 | map = dso__new_map(tp->module); |
| 1823 | if (!map) | 1882 | if (!map) |
| 1824 | goto out; | 1883 | goto out; |
| 1825 | addr = tp->address; | ||
| 1826 | sym = map__find_symbol(map, addr, NULL); | 1884 | sym = map__find_symbol(map, addr, NULL); |
| 1827 | } else { | 1885 | } else { |
| 1828 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | 1886 | if (tp->symbol) |
| 1887 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | ||
| 1829 | if (addr) { | 1888 | if (addr) { |
| 1830 | addr += tp->offset; | 1889 | addr += tp->offset; |
| 1831 | sym = __find_kernel_function(addr, &map); | 1890 | sym = __find_kernel_function(addr, &map); |
| @@ -1848,8 +1907,8 @@ out: | |||
| 1848 | } | 1907 | } |
| 1849 | 1908 | ||
| 1850 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, | 1909 | static int convert_to_perf_probe_point(struct probe_trace_point *tp, |
| 1851 | struct perf_probe_point *pp, | 1910 | struct perf_probe_point *pp, |
| 1852 | bool is_kprobe) | 1911 | bool is_kprobe) |
| 1853 | { | 1912 | { |
| 1854 | char buf[128]; | 1913 | char buf[128]; |
| 1855 | int ret; | 1914 | int ret; |
| @@ -1866,7 +1925,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp, | |||
| 1866 | if (tp->symbol) { | 1925 | if (tp->symbol) { |
| 1867 | pp->function = strdup(tp->symbol); | 1926 | pp->function = strdup(tp->symbol); |
| 1868 | pp->offset = tp->offset; | 1927 | pp->offset = tp->offset; |
| 1869 | } else if (!tp->module && !is_kprobe) { | 1928 | } else { |
| 1870 | ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); | 1929 | ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address); |
| 1871 | if (ret < 0) | 1930 | if (ret < 0) |
| 1872 | return ret; | 1931 | return ret; |
| @@ -2305,7 +2364,9 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, | |||
| 2305 | if (pev->event) | 2364 | if (pev->event) |
| 2306 | event = pev->event; | 2365 | event = pev->event; |
| 2307 | else | 2366 | else |
| 2308 | if (pev->point.function && !strisglob(pev->point.function)) | 2367 | if (pev->point.function && |
| 2368 | (strncmp(pev->point.function, "0x", 2) != 0) && | ||
| 2369 | !strisglob(pev->point.function)) | ||
| 2309 | event = pev->point.function; | 2370 | event = pev->point.function; |
| 2310 | else | 2371 | else |
| 2311 | event = tev->point.realname; | 2372 | event = tev->point.realname; |
| @@ -2572,6 +2633,98 @@ err_out: | |||
| 2572 | goto out; | 2633 | goto out; |
| 2573 | } | 2634 | } |
| 2574 | 2635 | ||
| 2636 | static int try_to_find_absolute_address(struct perf_probe_event *pev, | ||
| 2637 | struct probe_trace_event **tevs) | ||
| 2638 | { | ||
| 2639 | struct perf_probe_point *pp = &pev->point; | ||
| 2640 | struct probe_trace_event *tev; | ||
| 2641 | struct probe_trace_point *tp; | ||
| 2642 | int i, err; | ||
| 2643 | |||
| 2644 | if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2))) | ||
| 2645 | return -EINVAL; | ||
| 2646 | if (perf_probe_event_need_dwarf(pev)) | ||
| 2647 | return -EINVAL; | ||
| 2648 | |||
| 2649 | /* | ||
| 2650 | * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at | ||
| 2651 | * absolute address. | ||
| 2652 | * | ||
| 2653 | * Only one tev can be generated by this. | ||
| 2654 | */ | ||
| 2655 | *tevs = zalloc(sizeof(*tev)); | ||
| 2656 | if (!*tevs) | ||
| 2657 | return -ENOMEM; | ||
| 2658 | |||
| 2659 | tev = *tevs; | ||
| 2660 | tp = &tev->point; | ||
| 2661 | |||
| 2662 | /* | ||
| 2663 | * Don't use tp->offset, use address directly, because | ||
| 2664 | * in synthesize_probe_trace_command() address cannot be | ||
| 2665 | * zero. | ||
| 2666 | */ | ||
| 2667 | tp->address = pev->point.abs_address; | ||
| 2668 | tp->retprobe = pp->retprobe; | ||
| 2669 | tev->uprobes = pev->uprobes; | ||
| 2670 | |||
| 2671 | err = -ENOMEM; | ||
| 2672 | /* | ||
| 2673 | * Give it a '0x' leading symbol name. | ||
| 2674 | * In __add_probe_trace_events, a NULL symbol is interpreted as | ||
| 2675 | * invalud. | ||
| 2676 | */ | ||
| 2677 | if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0) | ||
| 2678 | goto errout; | ||
| 2679 | |||
| 2680 | /* For kprobe, check range */ | ||
| 2681 | if ((!tev->uprobes) && | ||
| 2682 | (kprobe_warn_out_range(tev->point.symbol, | ||
| 2683 | tev->point.address))) { | ||
| 2684 | err = -EACCES; | ||
| 2685 | goto errout; | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0) | ||
| 2689 | goto errout; | ||
| 2690 | |||
| 2691 | if (pev->target) { | ||
| 2692 | tp->module = strdup(pev->target); | ||
| 2693 | if (!tp->module) | ||
| 2694 | goto errout; | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | if (tev->group) { | ||
| 2698 | tev->group = strdup(pev->group); | ||
| 2699 | if (!tev->group) | ||
| 2700 | goto errout; | ||
| 2701 | } | ||
| 2702 | |||
| 2703 | if (pev->event) { | ||
| 2704 | tev->event = strdup(pev->event); | ||
| 2705 | if (!tev->event) | ||
| 2706 | goto errout; | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | tev->nargs = pev->nargs; | ||
| 2710 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); | ||
| 2711 | if (!tev->args) { | ||
| 2712 | err = -ENOMEM; | ||
| 2713 | goto errout; | ||
| 2714 | } | ||
| 2715 | for (i = 0; i < tev->nargs; i++) | ||
| 2716 | copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]); | ||
| 2717 | |||
| 2718 | return 1; | ||
| 2719 | |||
| 2720 | errout: | ||
| 2721 | if (*tevs) { | ||
| 2722 | clear_probe_trace_events(*tevs, 1); | ||
| 2723 | *tevs = NULL; | ||
| 2724 | } | ||
| 2725 | return err; | ||
| 2726 | } | ||
| 2727 | |||
| 2575 | bool __weak arch__prefers_symtab(void) { return false; } | 2728 | bool __weak arch__prefers_symtab(void) { return false; } |
| 2576 | 2729 | ||
| 2577 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, | 2730 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, |
| @@ -2588,6 +2741,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
| 2588 | } | 2741 | } |
| 2589 | } | 2742 | } |
| 2590 | 2743 | ||
| 2744 | ret = try_to_find_absolute_address(pev, tevs); | ||
| 2745 | if (ret > 0) | ||
| 2746 | return ret; | ||
| 2747 | |||
| 2591 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { | 2748 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { |
| 2592 | ret = find_probe_trace_events_from_map(pev, tevs); | 2749 | ret = find_probe_trace_events_from_map(pev, tevs); |
| 2593 | if (ret > 0) | 2750 | if (ret > 0) |
| @@ -2758,3 +2915,22 @@ end: | |||
| 2758 | return ret; | 2915 | return ret; |
| 2759 | } | 2916 | } |
| 2760 | 2917 | ||
| 2918 | int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, | ||
| 2919 | struct perf_probe_arg *pvar) | ||
| 2920 | { | ||
| 2921 | tvar->value = strdup(pvar->var); | ||
| 2922 | if (tvar->value == NULL) | ||
| 2923 | return -ENOMEM; | ||
| 2924 | if (pvar->type) { | ||
| 2925 | tvar->type = strdup(pvar->type); | ||
| 2926 | if (tvar->type == NULL) | ||
| 2927 | return -ENOMEM; | ||
| 2928 | } | ||
| 2929 | if (pvar->name) { | ||
| 2930 | tvar->name = strdup(pvar->name); | ||
| 2931 | if (tvar->name == NULL) | ||
| 2932 | return -ENOMEM; | ||
| 2933 | } else | ||
| 2934 | tvar->name = NULL; | ||
| 2935 | return 0; | ||
| 2936 | } | ||
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 83ee95e9743b..6e7ec68a4aa8 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
| @@ -59,6 +59,7 @@ struct perf_probe_point { | |||
| 59 | bool retprobe; /* Return probe flag */ | 59 | bool retprobe; /* Return probe flag */ |
| 60 | char *lazy_line; /* Lazy matching pattern */ | 60 | char *lazy_line; /* Lazy matching pattern */ |
| 61 | unsigned long offset; /* Offset from function entry */ | 61 | unsigned long offset; /* Offset from function entry */ |
| 62 | unsigned long abs_address; /* Absolute address of the point */ | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | /* Perf probe probing argument field chain */ | 65 | /* Perf probe probing argument field chain */ |
| @@ -156,4 +157,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...) | |||
| 156 | /* Maximum index number of event-name postfix */ | 157 | /* Maximum index number of event-name postfix */ |
| 157 | #define MAX_EVENT_INDEX 1024 | 158 | #define MAX_EVENT_INDEX 1024 |
| 158 | 159 | ||
| 160 | int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, | ||
| 161 | struct perf_probe_arg *pvar); | ||
| 162 | |||
| 159 | #endif /*_PROBE_EVENT_H */ | 163 | #endif /*_PROBE_EVENT_H */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 7b80f8cb62b9..29c43c0680a8 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
| 553 | char buf[32], *ptr; | 553 | char buf[32], *ptr; |
| 554 | int ret = 0; | 554 | int ret = 0; |
| 555 | 555 | ||
| 556 | if (!is_c_varname(pf->pvar->var)) { | 556 | /* Copy raw parameters */ |
| 557 | /* Copy raw parameters */ | 557 | if (!is_c_varname(pf->pvar->var)) |
| 558 | pf->tvar->value = strdup(pf->pvar->var); | 558 | return copy_to_probe_trace_arg(pf->tvar, pf->pvar); |
| 559 | if (pf->tvar->value == NULL) | ||
| 560 | return -ENOMEM; | ||
| 561 | if (pf->pvar->type) { | ||
| 562 | pf->tvar->type = strdup(pf->pvar->type); | ||
| 563 | if (pf->tvar->type == NULL) | ||
| 564 | return -ENOMEM; | ||
| 565 | } | ||
| 566 | if (pf->pvar->name) { | ||
| 567 | pf->tvar->name = strdup(pf->pvar->name); | ||
| 568 | if (pf->tvar->name == NULL) | ||
| 569 | return -ENOMEM; | ||
| 570 | } else | ||
| 571 | pf->tvar->name = NULL; | ||
| 572 | return 0; | ||
| 573 | } | ||
| 574 | 559 | ||
| 575 | if (pf->pvar->name) | 560 | if (pf->pvar->name) |
| 576 | pf->tvar->name = strdup(pf->pvar->name); | 561 | pf->tvar->name = strdup(pf->pvar->name); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 42e98ab5a9bb..46ae0532a8a6 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -441,6 +441,16 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols, | |||
| 441 | return &s->sym; | 441 | return &s->sym; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | void dso__reset_find_symbol_cache(struct dso *dso) | ||
| 445 | { | ||
| 446 | enum map_type type; | ||
| 447 | |||
| 448 | for (type = MAP__FUNCTION; type <= MAP__VARIABLE; ++type) { | ||
| 449 | dso->last_find_result[type].addr = 0; | ||
| 450 | dso->last_find_result[type].symbol = NULL; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 444 | struct symbol *dso__find_symbol(struct dso *dso, | 454 | struct symbol *dso__find_symbol(struct dso *dso, |
| 445 | enum map_type type, u64 addr) | 455 | enum map_type type, u64 addr) |
| 446 | { | 456 | { |
