.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * intel-bts.c: Intel Processor Trace support |
---|
3 | 4 | * Copyright (c) 2013-2015, Intel Corporation. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | | - * |
---|
14 | 5 | */ |
---|
15 | 6 | |
---|
16 | 7 | #include <endian.h> |
---|
.. | .. |
---|
21 | 12 | #include <linux/types.h> |
---|
22 | 13 | #include <linux/bitops.h> |
---|
23 | 14 | #include <linux/log2.h> |
---|
| 15 | +#include <linux/zalloc.h> |
---|
24 | 16 | |
---|
25 | | -#include "cpumap.h" |
---|
26 | 17 | #include "color.h" |
---|
27 | 18 | #include "evsel.h" |
---|
28 | 19 | #include "evlist.h" |
---|
29 | 20 | #include "machine.h" |
---|
| 21 | +#include "symbol.h" |
---|
30 | 22 | #include "session.h" |
---|
31 | | -#include "util.h" |
---|
| 23 | +#include "tool.h" |
---|
32 | 24 | #include "thread.h" |
---|
33 | 25 | #include "thread-stack.h" |
---|
34 | 26 | #include "debug.h" |
---|
.. | .. |
---|
36 | 28 | #include "auxtrace.h" |
---|
37 | 29 | #include "intel-pt-decoder/intel-pt-insn-decoder.h" |
---|
38 | 30 | #include "intel-bts.h" |
---|
| 31 | +#include "util/synthetic-events.h" |
---|
39 | 32 | |
---|
40 | 33 | #define MAX_TIMESTAMP (~0ULL) |
---|
41 | 34 | |
---|
.. | .. |
---|
142 | 135 | |
---|
143 | 136 | auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE, |
---|
144 | 137 | INTEL_BTS_ERR_LOST, sample->cpu, sample->pid, |
---|
145 | | - sample->tid, 0, "Lost trace data"); |
---|
| 138 | + sample->tid, 0, "Lost trace data", sample->time); |
---|
146 | 139 | |
---|
147 | 140 | err = perf_session__deliver_synth_event(bts->session, &event, NULL); |
---|
148 | 141 | if (err) |
---|
.. | .. |
---|
326 | 319 | { |
---|
327 | 320 | struct machine *machine = btsq->bts->machine; |
---|
328 | 321 | struct thread *thread; |
---|
329 | | - struct addr_location al; |
---|
330 | 322 | unsigned char buf[INTEL_PT_INSN_BUF_SZ]; |
---|
331 | 323 | ssize_t len; |
---|
332 | | - int x86_64; |
---|
333 | | - uint8_t cpumode; |
---|
| 324 | + bool x86_64; |
---|
334 | 325 | int err = -1; |
---|
335 | | - |
---|
336 | | - if (machine__kernel_ip(machine, ip)) |
---|
337 | | - cpumode = PERF_RECORD_MISC_KERNEL; |
---|
338 | | - else |
---|
339 | | - cpumode = PERF_RECORD_MISC_USER; |
---|
340 | 326 | |
---|
341 | 327 | thread = machine__find_thread(machine, -1, btsq->tid); |
---|
342 | 328 | if (!thread) |
---|
343 | 329 | return -1; |
---|
344 | 330 | |
---|
345 | | - if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso) |
---|
346 | | - goto out_put; |
---|
347 | | - |
---|
348 | | - len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, |
---|
349 | | - INTEL_PT_INSN_BUF_SZ); |
---|
| 331 | + len = thread__memcpy(thread, machine, buf, ip, INTEL_PT_INSN_BUF_SZ, &x86_64); |
---|
350 | 332 | if (len <= 0) |
---|
351 | 333 | goto out_put; |
---|
352 | | - |
---|
353 | | - /* Load maps to ensure dso->is_64_bit has been updated */ |
---|
354 | | - map__load(al.map); |
---|
355 | | - |
---|
356 | | - x86_64 = al.map->dso->is_64_bit; |
---|
357 | 334 | |
---|
358 | 335 | if (intel_pt_get_insn(buf, len, x86_64, &btsq->intel_pt_insn)) |
---|
359 | 336 | goto out_put; |
---|
.. | .. |
---|
372 | 349 | |
---|
373 | 350 | auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE, |
---|
374 | 351 | INTEL_BTS_ERR_NOINSN, cpu, pid, tid, ip, |
---|
375 | | - "Failed to get instruction"); |
---|
| 352 | + "Failed to get instruction", 0); |
---|
376 | 353 | |
---|
377 | 354 | err = perf_session__deliver_synth_event(bts->session, &event, NULL); |
---|
378 | 355 | if (err) |
---|
.. | .. |
---|
451 | 428 | continue; |
---|
452 | 429 | intel_bts_get_branch_type(btsq, branch); |
---|
453 | 430 | if (btsq->bts->synth_opts.thread_stack) |
---|
454 | | - thread_stack__event(thread, btsq->sample_flags, |
---|
| 431 | + thread_stack__event(thread, btsq->cpu, btsq->sample_flags, |
---|
455 | 432 | le64_to_cpu(branch->from), |
---|
456 | 433 | le64_to_cpu(branch->to), |
---|
457 | 434 | btsq->intel_pt_insn.length, |
---|
458 | | - buffer->buffer_nr + 1); |
---|
| 435 | + buffer->buffer_nr + 1, true, 0, 0); |
---|
459 | 436 | if (filter && !(filter & btsq->sample_flags)) |
---|
460 | 437 | continue; |
---|
461 | 438 | err = intel_bts_synth_branch_sample(btsq, branch); |
---|
.. | .. |
---|
523 | 500 | !btsq->bts->synth_opts.thread_stack && thread && |
---|
524 | 501 | (!old_buffer || btsq->bts->sampling_mode || |
---|
525 | 502 | (btsq->bts->snapshot_mode && !buffer->consecutive))) |
---|
526 | | - thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); |
---|
| 503 | + thread_stack__set_trace_nr(thread, btsq->cpu, buffer->buffer_nr + 1); |
---|
527 | 504 | |
---|
528 | 505 | err = intel_bts_process_buffer(btsq, buffer, thread); |
---|
529 | 506 | |
---|
.. | .. |
---|
751 | 728 | free(bts); |
---|
752 | 729 | } |
---|
753 | 730 | |
---|
| 731 | +static bool intel_bts_evsel_is_auxtrace(struct perf_session *session, |
---|
| 732 | + struct evsel *evsel) |
---|
| 733 | +{ |
---|
| 734 | + struct intel_bts *bts = container_of(session->auxtrace, struct intel_bts, |
---|
| 735 | + auxtrace); |
---|
| 736 | + |
---|
| 737 | + return evsel->core.attr.type == bts->pmu_type; |
---|
| 738 | +} |
---|
| 739 | + |
---|
754 | 740 | struct intel_bts_synth { |
---|
755 | 741 | struct perf_tool dummy_tool; |
---|
756 | 742 | struct perf_session *session; |
---|
.. | .. |
---|
783 | 769 | static int intel_bts_synth_events(struct intel_bts *bts, |
---|
784 | 770 | struct perf_session *session) |
---|
785 | 771 | { |
---|
786 | | - struct perf_evlist *evlist = session->evlist; |
---|
787 | | - struct perf_evsel *evsel; |
---|
| 772 | + struct evlist *evlist = session->evlist; |
---|
| 773 | + struct evsel *evsel; |
---|
788 | 774 | struct perf_event_attr attr; |
---|
789 | 775 | bool found = false; |
---|
790 | 776 | u64 id; |
---|
791 | 777 | int err; |
---|
792 | 778 | |
---|
793 | 779 | evlist__for_each_entry(evlist, evsel) { |
---|
794 | | - if (evsel->attr.type == bts->pmu_type && evsel->ids) { |
---|
| 780 | + if (evsel->core.attr.type == bts->pmu_type && evsel->core.ids) { |
---|
795 | 781 | found = true; |
---|
796 | 782 | break; |
---|
797 | 783 | } |
---|
.. | .. |
---|
805 | 791 | memset(&attr, 0, sizeof(struct perf_event_attr)); |
---|
806 | 792 | attr.size = sizeof(struct perf_event_attr); |
---|
807 | 793 | attr.type = PERF_TYPE_HARDWARE; |
---|
808 | | - attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK; |
---|
| 794 | + attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK; |
---|
809 | 795 | attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID | |
---|
810 | 796 | PERF_SAMPLE_PERIOD; |
---|
811 | 797 | attr.sample_type &= ~(u64)PERF_SAMPLE_TIME; |
---|
812 | 798 | attr.sample_type &= ~(u64)PERF_SAMPLE_CPU; |
---|
813 | | - attr.exclude_user = evsel->attr.exclude_user; |
---|
814 | | - attr.exclude_kernel = evsel->attr.exclude_kernel; |
---|
815 | | - attr.exclude_hv = evsel->attr.exclude_hv; |
---|
816 | | - attr.exclude_host = evsel->attr.exclude_host; |
---|
817 | | - attr.exclude_guest = evsel->attr.exclude_guest; |
---|
818 | | - attr.sample_id_all = evsel->attr.sample_id_all; |
---|
819 | | - attr.read_format = evsel->attr.read_format; |
---|
| 799 | + attr.exclude_user = evsel->core.attr.exclude_user; |
---|
| 800 | + attr.exclude_kernel = evsel->core.attr.exclude_kernel; |
---|
| 801 | + attr.exclude_hv = evsel->core.attr.exclude_hv; |
---|
| 802 | + attr.exclude_host = evsel->core.attr.exclude_host; |
---|
| 803 | + attr.exclude_guest = evsel->core.attr.exclude_guest; |
---|
| 804 | + attr.sample_id_all = evsel->core.attr.sample_id_all; |
---|
| 805 | + attr.read_format = evsel->core.attr.read_format; |
---|
820 | 806 | |
---|
821 | | - id = evsel->id[0] + 1000000000; |
---|
| 807 | + id = evsel->core.id[0] + 1000000000; |
---|
822 | 808 | if (!id) |
---|
823 | 809 | id = 1; |
---|
824 | 810 | |
---|
.. | .. |
---|
839 | 825 | bts->branches_id = id; |
---|
840 | 826 | /* |
---|
841 | 827 | * We only use sample types from PERF_SAMPLE_MASK so we can use |
---|
842 | | - * __perf_evsel__sample_size() here. |
---|
| 828 | + * __evsel__sample_size() here. |
---|
843 | 829 | */ |
---|
844 | | - bts->branches_event_size = sizeof(struct sample_event) + |
---|
845 | | - __perf_evsel__sample_size(attr.sample_type); |
---|
| 830 | + bts->branches_event_size = sizeof(struct perf_record_sample) + |
---|
| 831 | + __evsel__sample_size(attr.sample_type); |
---|
846 | 832 | } |
---|
847 | 833 | |
---|
848 | 834 | return 0; |
---|
.. | .. |
---|
857 | 843 | [INTEL_BTS_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", |
---|
858 | 844 | }; |
---|
859 | 845 | |
---|
860 | | -static void intel_bts_print_info(u64 *arr, int start, int finish) |
---|
| 846 | +static void intel_bts_print_info(__u64 *arr, int start, int finish) |
---|
861 | 847 | { |
---|
862 | 848 | int i; |
---|
863 | 849 | |
---|
.. | .. |
---|
871 | 857 | int intel_bts_process_auxtrace_info(union perf_event *event, |
---|
872 | 858 | struct perf_session *session) |
---|
873 | 859 | { |
---|
874 | | - struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; |
---|
| 860 | + struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; |
---|
875 | 861 | size_t min_sz = sizeof(u64) * INTEL_BTS_SNAPSHOT_MODE; |
---|
876 | 862 | struct intel_bts *bts; |
---|
877 | 863 | int err; |
---|
878 | 864 | |
---|
879 | | - if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + |
---|
| 865 | + if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) + |
---|
880 | 866 | min_sz) |
---|
881 | 867 | return -EINVAL; |
---|
882 | 868 | |
---|
.. | .. |
---|
906 | 892 | bts->auxtrace.flush_events = intel_bts_flush; |
---|
907 | 893 | bts->auxtrace.free_events = intel_bts_free_events; |
---|
908 | 894 | bts->auxtrace.free = intel_bts_free; |
---|
| 895 | + bts->auxtrace.evsel_is_auxtrace = intel_bts_evsel_is_auxtrace; |
---|
909 | 896 | session->auxtrace = &bts->auxtrace; |
---|
910 | 897 | |
---|
911 | 898 | intel_bts_print_info(&auxtrace_info->priv[0], INTEL_BTS_PMU_TYPE, |
---|
.. | .. |
---|
914 | 901 | if (dump_trace) |
---|
915 | 902 | return 0; |
---|
916 | 903 | |
---|
917 | | - if (session->itrace_synth_opts && session->itrace_synth_opts->set) { |
---|
| 904 | + if (session->itrace_synth_opts->set) { |
---|
918 | 905 | bts->synth_opts = *session->itrace_synth_opts; |
---|
919 | 906 | } else { |
---|
920 | | - itrace_synth_opts__set_default(&bts->synth_opts); |
---|
921 | | - if (session->itrace_synth_opts) |
---|
922 | | - bts->synth_opts.thread_stack = |
---|
| 907 | + itrace_synth_opts__set_default(&bts->synth_opts, |
---|
| 908 | + session->itrace_synth_opts->default_no_sample); |
---|
| 909 | + bts->synth_opts.thread_stack = |
---|
923 | 910 | session->itrace_synth_opts->thread_stack; |
---|
924 | 911 | } |
---|
925 | 912 | |
---|