18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * intel_pt.c: Intel Processor Trace support
48c2ecf20Sopenharmony_ci * Copyright (c) 2013-2015, Intel Corporation.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <inttypes.h>
88c2ecf20Sopenharmony_ci#include <stdio.h>
98c2ecf20Sopenharmony_ci#include <stdbool.h>
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/string.h>
138c2ecf20Sopenharmony_ci#include <linux/types.h>
148c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "session.h"
178c2ecf20Sopenharmony_ci#include "machine.h"
188c2ecf20Sopenharmony_ci#include "memswap.h"
198c2ecf20Sopenharmony_ci#include "sort.h"
208c2ecf20Sopenharmony_ci#include "tool.h"
218c2ecf20Sopenharmony_ci#include "event.h"
228c2ecf20Sopenharmony_ci#include "evlist.h"
238c2ecf20Sopenharmony_ci#include "evsel.h"
248c2ecf20Sopenharmony_ci#include "map.h"
258c2ecf20Sopenharmony_ci#include "color.h"
268c2ecf20Sopenharmony_ci#include "thread.h"
278c2ecf20Sopenharmony_ci#include "thread-stack.h"
288c2ecf20Sopenharmony_ci#include "symbol.h"
298c2ecf20Sopenharmony_ci#include "callchain.h"
308c2ecf20Sopenharmony_ci#include "dso.h"
318c2ecf20Sopenharmony_ci#include "debug.h"
328c2ecf20Sopenharmony_ci#include "auxtrace.h"
338c2ecf20Sopenharmony_ci#include "tsc.h"
348c2ecf20Sopenharmony_ci#include "intel-pt.h"
358c2ecf20Sopenharmony_ci#include "config.h"
368c2ecf20Sopenharmony_ci#include "util/perf_api_probe.h"
378c2ecf20Sopenharmony_ci#include "util/synthetic-events.h"
388c2ecf20Sopenharmony_ci#include "time-utils.h"
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "../arch/x86/include/uapi/asm/perf_regs.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#include "intel-pt-decoder/intel-pt-log.h"
438c2ecf20Sopenharmony_ci#include "intel-pt-decoder/intel-pt-decoder.h"
448c2ecf20Sopenharmony_ci#include "intel-pt-decoder/intel-pt-insn-decoder.h"
458c2ecf20Sopenharmony_ci#include "intel-pt-decoder/intel-pt-pkt-decoder.h"
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define MAX_TIMESTAMP (~0ULL)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistruct range {
508c2ecf20Sopenharmony_ci	u64 start;
518c2ecf20Sopenharmony_ci	u64 end;
528c2ecf20Sopenharmony_ci};
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistruct intel_pt {
558c2ecf20Sopenharmony_ci	struct auxtrace auxtrace;
568c2ecf20Sopenharmony_ci	struct auxtrace_queues queues;
578c2ecf20Sopenharmony_ci	struct auxtrace_heap heap;
588c2ecf20Sopenharmony_ci	u32 auxtrace_type;
598c2ecf20Sopenharmony_ci	struct perf_session *session;
608c2ecf20Sopenharmony_ci	struct machine *machine;
618c2ecf20Sopenharmony_ci	struct evsel *switch_evsel;
628c2ecf20Sopenharmony_ci	struct thread *unknown_thread;
638c2ecf20Sopenharmony_ci	bool timeless_decoding;
648c2ecf20Sopenharmony_ci	bool sampling_mode;
658c2ecf20Sopenharmony_ci	bool snapshot_mode;
668c2ecf20Sopenharmony_ci	bool per_cpu_mmaps;
678c2ecf20Sopenharmony_ci	bool have_tsc;
688c2ecf20Sopenharmony_ci	bool data_queued;
698c2ecf20Sopenharmony_ci	bool est_tsc;
708c2ecf20Sopenharmony_ci	bool sync_switch;
718c2ecf20Sopenharmony_ci	bool mispred_all;
728c2ecf20Sopenharmony_ci	bool use_thread_stack;
738c2ecf20Sopenharmony_ci	bool callstack;
748c2ecf20Sopenharmony_ci	unsigned int br_stack_sz;
758c2ecf20Sopenharmony_ci	unsigned int br_stack_sz_plus;
768c2ecf20Sopenharmony_ci	int have_sched_switch;
778c2ecf20Sopenharmony_ci	u32 pmu_type;
788c2ecf20Sopenharmony_ci	u64 kernel_start;
798c2ecf20Sopenharmony_ci	u64 switch_ip;
808c2ecf20Sopenharmony_ci	u64 ptss_ip;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	struct perf_tsc_conversion tc;
838c2ecf20Sopenharmony_ci	bool cap_user_time_zero;
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	struct itrace_synth_opts synth_opts;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	bool sample_instructions;
888c2ecf20Sopenharmony_ci	u64 instructions_sample_type;
898c2ecf20Sopenharmony_ci	u64 instructions_id;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	bool sample_branches;
928c2ecf20Sopenharmony_ci	u32 branches_filter;
938c2ecf20Sopenharmony_ci	u64 branches_sample_type;
948c2ecf20Sopenharmony_ci	u64 branches_id;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	bool sample_transactions;
978c2ecf20Sopenharmony_ci	u64 transactions_sample_type;
988c2ecf20Sopenharmony_ci	u64 transactions_id;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	bool sample_ptwrites;
1018c2ecf20Sopenharmony_ci	u64 ptwrites_sample_type;
1028c2ecf20Sopenharmony_ci	u64 ptwrites_id;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	bool sample_pwr_events;
1058c2ecf20Sopenharmony_ci	u64 pwr_events_sample_type;
1068c2ecf20Sopenharmony_ci	u64 mwait_id;
1078c2ecf20Sopenharmony_ci	u64 pwre_id;
1088c2ecf20Sopenharmony_ci	u64 exstop_id;
1098c2ecf20Sopenharmony_ci	u64 pwrx_id;
1108c2ecf20Sopenharmony_ci	u64 cbr_id;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	bool sample_pebs;
1138c2ecf20Sopenharmony_ci	struct evsel *pebs_evsel;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	u64 tsc_bit;
1168c2ecf20Sopenharmony_ci	u64 mtc_bit;
1178c2ecf20Sopenharmony_ci	u64 mtc_freq_bits;
1188c2ecf20Sopenharmony_ci	u32 tsc_ctc_ratio_n;
1198c2ecf20Sopenharmony_ci	u32 tsc_ctc_ratio_d;
1208c2ecf20Sopenharmony_ci	u64 cyc_bit;
1218c2ecf20Sopenharmony_ci	u64 noretcomp_bit;
1228c2ecf20Sopenharmony_ci	unsigned max_non_turbo_ratio;
1238c2ecf20Sopenharmony_ci	unsigned cbr2khz;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	unsigned long num_events;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	char *filter;
1288c2ecf20Sopenharmony_ci	struct addr_filters filts;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	struct range *time_ranges;
1318c2ecf20Sopenharmony_ci	unsigned int range_cnt;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	struct ip_callchain *chain;
1348c2ecf20Sopenharmony_ci	struct branch_stack *br_stack;
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cienum switch_state {
1388c2ecf20Sopenharmony_ci	INTEL_PT_SS_NOT_TRACING,
1398c2ecf20Sopenharmony_ci	INTEL_PT_SS_UNKNOWN,
1408c2ecf20Sopenharmony_ci	INTEL_PT_SS_TRACING,
1418c2ecf20Sopenharmony_ci	INTEL_PT_SS_EXPECTING_SWITCH_EVENT,
1428c2ecf20Sopenharmony_ci	INTEL_PT_SS_EXPECTING_SWITCH_IP,
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistruct intel_pt_queue {
1468c2ecf20Sopenharmony_ci	struct intel_pt *pt;
1478c2ecf20Sopenharmony_ci	unsigned int queue_nr;
1488c2ecf20Sopenharmony_ci	struct auxtrace_buffer *buffer;
1498c2ecf20Sopenharmony_ci	struct auxtrace_buffer *old_buffer;
1508c2ecf20Sopenharmony_ci	void *decoder;
1518c2ecf20Sopenharmony_ci	const struct intel_pt_state *state;
1528c2ecf20Sopenharmony_ci	struct ip_callchain *chain;
1538c2ecf20Sopenharmony_ci	struct branch_stack *last_branch;
1548c2ecf20Sopenharmony_ci	union perf_event *event_buf;
1558c2ecf20Sopenharmony_ci	bool on_heap;
1568c2ecf20Sopenharmony_ci	bool stop;
1578c2ecf20Sopenharmony_ci	bool step_through_buffers;
1588c2ecf20Sopenharmony_ci	bool use_buffer_pid_tid;
1598c2ecf20Sopenharmony_ci	bool sync_switch;
1608c2ecf20Sopenharmony_ci	pid_t pid, tid;
1618c2ecf20Sopenharmony_ci	int cpu;
1628c2ecf20Sopenharmony_ci	int switch_state;
1638c2ecf20Sopenharmony_ci	pid_t next_tid;
1648c2ecf20Sopenharmony_ci	struct thread *thread;
1658c2ecf20Sopenharmony_ci	bool exclude_kernel;
1668c2ecf20Sopenharmony_ci	bool have_sample;
1678c2ecf20Sopenharmony_ci	u64 time;
1688c2ecf20Sopenharmony_ci	u64 timestamp;
1698c2ecf20Sopenharmony_ci	u64 sel_timestamp;
1708c2ecf20Sopenharmony_ci	bool sel_start;
1718c2ecf20Sopenharmony_ci	unsigned int sel_idx;
1728c2ecf20Sopenharmony_ci	u32 flags;
1738c2ecf20Sopenharmony_ci	u16 insn_len;
1748c2ecf20Sopenharmony_ci	u64 last_insn_cnt;
1758c2ecf20Sopenharmony_ci	u64 ipc_insn_cnt;
1768c2ecf20Sopenharmony_ci	u64 ipc_cyc_cnt;
1778c2ecf20Sopenharmony_ci	u64 last_in_insn_cnt;
1788c2ecf20Sopenharmony_ci	u64 last_in_cyc_cnt;
1798c2ecf20Sopenharmony_ci	u64 last_br_insn_cnt;
1808c2ecf20Sopenharmony_ci	u64 last_br_cyc_cnt;
1818c2ecf20Sopenharmony_ci	unsigned int cbr_seen;
1828c2ecf20Sopenharmony_ci	char insn[INTEL_PT_INSN_BUF_SZ];
1838c2ecf20Sopenharmony_ci};
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic void intel_pt_dump(struct intel_pt *pt __maybe_unused,
1868c2ecf20Sopenharmony_ci			  unsigned char *buf, size_t len)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	struct intel_pt_pkt packet;
1898c2ecf20Sopenharmony_ci	size_t pos = 0;
1908c2ecf20Sopenharmony_ci	int ret, pkt_len, i;
1918c2ecf20Sopenharmony_ci	char desc[INTEL_PT_PKT_DESC_MAX];
1928c2ecf20Sopenharmony_ci	const char *color = PERF_COLOR_BLUE;
1938c2ecf20Sopenharmony_ci	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	color_fprintf(stdout, color,
1968c2ecf20Sopenharmony_ci		      ". ... Intel Processor Trace data: size %zu bytes\n",
1978c2ecf20Sopenharmony_ci		      len);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	while (len) {
2008c2ecf20Sopenharmony_ci		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
2018c2ecf20Sopenharmony_ci		if (ret > 0)
2028c2ecf20Sopenharmony_ci			pkt_len = ret;
2038c2ecf20Sopenharmony_ci		else
2048c2ecf20Sopenharmony_ci			pkt_len = 1;
2058c2ecf20Sopenharmony_ci		printf(".");
2068c2ecf20Sopenharmony_ci		color_fprintf(stdout, color, "  %08x: ", pos);
2078c2ecf20Sopenharmony_ci		for (i = 0; i < pkt_len; i++)
2088c2ecf20Sopenharmony_ci			color_fprintf(stdout, color, " %02x", buf[i]);
2098c2ecf20Sopenharmony_ci		for (; i < 16; i++)
2108c2ecf20Sopenharmony_ci			color_fprintf(stdout, color, "   ");
2118c2ecf20Sopenharmony_ci		if (ret > 0) {
2128c2ecf20Sopenharmony_ci			ret = intel_pt_pkt_desc(&packet, desc,
2138c2ecf20Sopenharmony_ci						INTEL_PT_PKT_DESC_MAX);
2148c2ecf20Sopenharmony_ci			if (ret > 0)
2158c2ecf20Sopenharmony_ci				color_fprintf(stdout, color, " %s\n", desc);
2168c2ecf20Sopenharmony_ci		} else {
2178c2ecf20Sopenharmony_ci			color_fprintf(stdout, color, " Bad packet!\n");
2188c2ecf20Sopenharmony_ci		}
2198c2ecf20Sopenharmony_ci		pos += pkt_len;
2208c2ecf20Sopenharmony_ci		buf += pkt_len;
2218c2ecf20Sopenharmony_ci		len -= pkt_len;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic void intel_pt_dump_event(struct intel_pt *pt, unsigned char *buf,
2268c2ecf20Sopenharmony_ci				size_t len)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	printf(".\n");
2298c2ecf20Sopenharmony_ci	intel_pt_dump(pt, buf, len);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic void intel_pt_log_event(union perf_event *event)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	FILE *f = intel_pt_log_fp();
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (!intel_pt_enable_logging || !f)
2378c2ecf20Sopenharmony_ci		return;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	perf_event__fprintf(event, NULL, f);
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_cistatic void intel_pt_dump_sample(struct perf_session *session,
2438c2ecf20Sopenharmony_ci				 struct perf_sample *sample)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
2468c2ecf20Sopenharmony_ci					   auxtrace);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	printf("\n");
2498c2ecf20Sopenharmony_ci	intel_pt_dump(pt, sample->aux_sample.data, sample->aux_sample.size);
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic bool intel_pt_log_events(struct intel_pt *pt, u64 tm)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct perf_time_interval *range = pt->synth_opts.ptime_range;
2558c2ecf20Sopenharmony_ci	int n = pt->synth_opts.range_num;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	if (pt->synth_opts.log_plus_flags & AUXTRACE_LOG_FLG_ALL_PERF_EVTS)
2588c2ecf20Sopenharmony_ci		return true;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (pt->synth_opts.log_minus_flags & AUXTRACE_LOG_FLG_ALL_PERF_EVTS)
2618c2ecf20Sopenharmony_ci		return false;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/* perf_time__ranges_skip_sample does not work if time is zero */
2648c2ecf20Sopenharmony_ci	if (!tm)
2658c2ecf20Sopenharmony_ci		tm = 1;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	return !n || !perf_time__ranges_skip_sample(range, n, tm);
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic int intel_pt_do_fix_overlap(struct intel_pt *pt, struct auxtrace_buffer *a,
2718c2ecf20Sopenharmony_ci				   struct auxtrace_buffer *b)
2728c2ecf20Sopenharmony_ci{
2738c2ecf20Sopenharmony_ci	bool consecutive = false;
2748c2ecf20Sopenharmony_ci	void *start;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	start = intel_pt_find_overlap(a->data, a->size, b->data, b->size,
2778c2ecf20Sopenharmony_ci				      pt->have_tsc, &consecutive);
2788c2ecf20Sopenharmony_ci	if (!start)
2798c2ecf20Sopenharmony_ci		return -EINVAL;
2808c2ecf20Sopenharmony_ci	b->use_size = b->data + b->size - start;
2818c2ecf20Sopenharmony_ci	b->use_data = start;
2828c2ecf20Sopenharmony_ci	if (b->use_size && consecutive)
2838c2ecf20Sopenharmony_ci		b->consecutive = true;
2848c2ecf20Sopenharmony_ci	return 0;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic int intel_pt_get_buffer(struct intel_pt_queue *ptq,
2888c2ecf20Sopenharmony_ci			       struct auxtrace_buffer *buffer,
2898c2ecf20Sopenharmony_ci			       struct auxtrace_buffer *old_buffer,
2908c2ecf20Sopenharmony_ci			       struct intel_pt_buffer *b)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	bool might_overlap;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (!buffer->data) {
2958c2ecf20Sopenharmony_ci		int fd = perf_data__fd(ptq->pt->session->data);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci		buffer->data = auxtrace_buffer__get_data(buffer, fd);
2988c2ecf20Sopenharmony_ci		if (!buffer->data)
2998c2ecf20Sopenharmony_ci			return -ENOMEM;
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	might_overlap = ptq->pt->snapshot_mode || ptq->pt->sampling_mode;
3038c2ecf20Sopenharmony_ci	if (might_overlap && !buffer->consecutive && old_buffer &&
3048c2ecf20Sopenharmony_ci	    intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
3058c2ecf20Sopenharmony_ci		return -ENOMEM;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	if (buffer->use_data) {
3088c2ecf20Sopenharmony_ci		b->len = buffer->use_size;
3098c2ecf20Sopenharmony_ci		b->buf = buffer->use_data;
3108c2ecf20Sopenharmony_ci	} else {
3118c2ecf20Sopenharmony_ci		b->len = buffer->size;
3128c2ecf20Sopenharmony_ci		b->buf = buffer->data;
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci	b->ref_timestamp = buffer->reference;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (!old_buffer || (might_overlap && !buffer->consecutive)) {
3178c2ecf20Sopenharmony_ci		b->consecutive = false;
3188c2ecf20Sopenharmony_ci		b->trace_nr = buffer->buffer_nr + 1;
3198c2ecf20Sopenharmony_ci	} else {
3208c2ecf20Sopenharmony_ci		b->consecutive = true;
3218c2ecf20Sopenharmony_ci	}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	return 0;
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci/* Do not drop buffers with references - refer intel_pt_get_trace() */
3278c2ecf20Sopenharmony_cistatic void intel_pt_lookahead_drop_buffer(struct intel_pt_queue *ptq,
3288c2ecf20Sopenharmony_ci					   struct auxtrace_buffer *buffer)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	if (!buffer || buffer == ptq->buffer || buffer == ptq->old_buffer)
3318c2ecf20Sopenharmony_ci		return;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	auxtrace_buffer__drop_data(buffer);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci/* Must be serialized with respect to intel_pt_get_trace() */
3378c2ecf20Sopenharmony_cistatic int intel_pt_lookahead(void *data, intel_pt_lookahead_cb_t cb,
3388c2ecf20Sopenharmony_ci			      void *cb_data)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = data;
3418c2ecf20Sopenharmony_ci	struct auxtrace_buffer *buffer = ptq->buffer;
3428c2ecf20Sopenharmony_ci	struct auxtrace_buffer *old_buffer = ptq->old_buffer;
3438c2ecf20Sopenharmony_ci	struct auxtrace_queue *queue;
3448c2ecf20Sopenharmony_ci	int err = 0;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	while (1) {
3498c2ecf20Sopenharmony_ci		struct intel_pt_buffer b = { .len = 0 };
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		buffer = auxtrace_buffer__next(queue, buffer);
3528c2ecf20Sopenharmony_ci		if (!buffer)
3538c2ecf20Sopenharmony_ci			break;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		err = intel_pt_get_buffer(ptq, buffer, old_buffer, &b);
3568c2ecf20Sopenharmony_ci		if (err)
3578c2ecf20Sopenharmony_ci			break;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci		if (b.len) {
3608c2ecf20Sopenharmony_ci			intel_pt_lookahead_drop_buffer(ptq, old_buffer);
3618c2ecf20Sopenharmony_ci			old_buffer = buffer;
3628c2ecf20Sopenharmony_ci		} else {
3638c2ecf20Sopenharmony_ci			intel_pt_lookahead_drop_buffer(ptq, buffer);
3648c2ecf20Sopenharmony_ci			continue;
3658c2ecf20Sopenharmony_ci		}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		err = cb(&b, cb_data);
3688c2ecf20Sopenharmony_ci		if (err)
3698c2ecf20Sopenharmony_ci			break;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (buffer != old_buffer)
3738c2ecf20Sopenharmony_ci		intel_pt_lookahead_drop_buffer(ptq, buffer);
3748c2ecf20Sopenharmony_ci	intel_pt_lookahead_drop_buffer(ptq, old_buffer);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return err;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci/*
3808c2ecf20Sopenharmony_ci * This function assumes data is processed sequentially only.
3818c2ecf20Sopenharmony_ci * Must be serialized with respect to intel_pt_lookahead()
3828c2ecf20Sopenharmony_ci */
3838c2ecf20Sopenharmony_cistatic int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = data;
3868c2ecf20Sopenharmony_ci	struct auxtrace_buffer *buffer = ptq->buffer;
3878c2ecf20Sopenharmony_ci	struct auxtrace_buffer *old_buffer = ptq->old_buffer;
3888c2ecf20Sopenharmony_ci	struct auxtrace_queue *queue;
3898c2ecf20Sopenharmony_ci	int err;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	if (ptq->stop) {
3928c2ecf20Sopenharmony_ci		b->len = 0;
3938c2ecf20Sopenharmony_ci		return 0;
3948c2ecf20Sopenharmony_ci	}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	buffer = auxtrace_buffer__next(queue, buffer);
3998c2ecf20Sopenharmony_ci	if (!buffer) {
4008c2ecf20Sopenharmony_ci		if (old_buffer)
4018c2ecf20Sopenharmony_ci			auxtrace_buffer__drop_data(old_buffer);
4028c2ecf20Sopenharmony_ci		b->len = 0;
4038c2ecf20Sopenharmony_ci		return 0;
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	ptq->buffer = buffer;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	err = intel_pt_get_buffer(ptq, buffer, old_buffer, b);
4098c2ecf20Sopenharmony_ci	if (err)
4108c2ecf20Sopenharmony_ci		return err;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	if (ptq->step_through_buffers)
4138c2ecf20Sopenharmony_ci		ptq->stop = true;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (b->len) {
4168c2ecf20Sopenharmony_ci		if (old_buffer)
4178c2ecf20Sopenharmony_ci			auxtrace_buffer__drop_data(old_buffer);
4188c2ecf20Sopenharmony_ci		ptq->old_buffer = buffer;
4198c2ecf20Sopenharmony_ci	} else {
4208c2ecf20Sopenharmony_ci		auxtrace_buffer__drop_data(buffer);
4218c2ecf20Sopenharmony_ci		return intel_pt_get_trace(b, data);
4228c2ecf20Sopenharmony_ci	}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	return 0;
4258c2ecf20Sopenharmony_ci}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_cistruct intel_pt_cache_entry {
4288c2ecf20Sopenharmony_ci	struct auxtrace_cache_entry	entry;
4298c2ecf20Sopenharmony_ci	u64				insn_cnt;
4308c2ecf20Sopenharmony_ci	u64				byte_cnt;
4318c2ecf20Sopenharmony_ci	enum intel_pt_insn_op		op;
4328c2ecf20Sopenharmony_ci	enum intel_pt_insn_branch	branch;
4338c2ecf20Sopenharmony_ci	int				length;
4348c2ecf20Sopenharmony_ci	int32_t				rel;
4358c2ecf20Sopenharmony_ci	char				insn[INTEL_PT_INSN_BUF_SZ];
4368c2ecf20Sopenharmony_ci};
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_cistatic int intel_pt_config_div(const char *var, const char *value, void *data)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	int *d = data;
4418c2ecf20Sopenharmony_ci	long val;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	if (!strcmp(var, "intel-pt.cache-divisor")) {
4448c2ecf20Sopenharmony_ci		val = strtol(value, NULL, 0);
4458c2ecf20Sopenharmony_ci		if (val > 0 && val <= INT_MAX)
4468c2ecf20Sopenharmony_ci			*d = val;
4478c2ecf20Sopenharmony_ci	}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	return 0;
4508c2ecf20Sopenharmony_ci}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cistatic int intel_pt_cache_divisor(void)
4538c2ecf20Sopenharmony_ci{
4548c2ecf20Sopenharmony_ci	static int d;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	if (d)
4578c2ecf20Sopenharmony_ci		return d;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	perf_config(intel_pt_config_div, &d);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	if (!d)
4628c2ecf20Sopenharmony_ci		d = 64;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	return d;
4658c2ecf20Sopenharmony_ci}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_cistatic unsigned int intel_pt_cache_size(struct dso *dso,
4688c2ecf20Sopenharmony_ci					struct machine *machine)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	off_t size;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	size = dso__data_size(dso, machine);
4738c2ecf20Sopenharmony_ci	size /= intel_pt_cache_divisor();
4748c2ecf20Sopenharmony_ci	if (size < 1000)
4758c2ecf20Sopenharmony_ci		return 10;
4768c2ecf20Sopenharmony_ci	if (size > (1 << 21))
4778c2ecf20Sopenharmony_ci		return 21;
4788c2ecf20Sopenharmony_ci	return 32 - __builtin_clz(size);
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_cistatic struct auxtrace_cache *intel_pt_cache(struct dso *dso,
4828c2ecf20Sopenharmony_ci					     struct machine *machine)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct auxtrace_cache *c;
4858c2ecf20Sopenharmony_ci	unsigned int bits;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	if (dso->auxtrace_cache)
4888c2ecf20Sopenharmony_ci		return dso->auxtrace_cache;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	bits = intel_pt_cache_size(dso, machine);
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	/* Ignoring cache creation failure */
4938c2ecf20Sopenharmony_ci	c = auxtrace_cache__new(bits, sizeof(struct intel_pt_cache_entry), 200);
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	dso->auxtrace_cache = c;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	return c;
4988c2ecf20Sopenharmony_ci}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_cistatic int intel_pt_cache_add(struct dso *dso, struct machine *machine,
5018c2ecf20Sopenharmony_ci			      u64 offset, u64 insn_cnt, u64 byte_cnt,
5028c2ecf20Sopenharmony_ci			      struct intel_pt_insn *intel_pt_insn)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct auxtrace_cache *c = intel_pt_cache(dso, machine);
5058c2ecf20Sopenharmony_ci	struct intel_pt_cache_entry *e;
5068c2ecf20Sopenharmony_ci	int err;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	if (!c)
5098c2ecf20Sopenharmony_ci		return -ENOMEM;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	e = auxtrace_cache__alloc_entry(c);
5128c2ecf20Sopenharmony_ci	if (!e)
5138c2ecf20Sopenharmony_ci		return -ENOMEM;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	e->insn_cnt = insn_cnt;
5168c2ecf20Sopenharmony_ci	e->byte_cnt = byte_cnt;
5178c2ecf20Sopenharmony_ci	e->op = intel_pt_insn->op;
5188c2ecf20Sopenharmony_ci	e->branch = intel_pt_insn->branch;
5198c2ecf20Sopenharmony_ci	e->length = intel_pt_insn->length;
5208c2ecf20Sopenharmony_ci	e->rel = intel_pt_insn->rel;
5218c2ecf20Sopenharmony_ci	memcpy(e->insn, intel_pt_insn->buf, INTEL_PT_INSN_BUF_SZ);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	err = auxtrace_cache__add(c, offset, &e->entry);
5248c2ecf20Sopenharmony_ci	if (err)
5258c2ecf20Sopenharmony_ci		auxtrace_cache__free_entry(c, e);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	return err;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic struct intel_pt_cache_entry *
5318c2ecf20Sopenharmony_ciintel_pt_cache_lookup(struct dso *dso, struct machine *machine, u64 offset)
5328c2ecf20Sopenharmony_ci{
5338c2ecf20Sopenharmony_ci	struct auxtrace_cache *c = intel_pt_cache(dso, machine);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	if (!c)
5368c2ecf20Sopenharmony_ci		return NULL;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	return auxtrace_cache__lookup(dso->auxtrace_cache, offset);
5398c2ecf20Sopenharmony_ci}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_cistatic void intel_pt_cache_invalidate(struct dso *dso, struct machine *machine,
5428c2ecf20Sopenharmony_ci				      u64 offset)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	struct auxtrace_cache *c = intel_pt_cache(dso, machine);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	if (!c)
5478c2ecf20Sopenharmony_ci		return;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	auxtrace_cache__remove(dso->auxtrace_cache, offset);
5508c2ecf20Sopenharmony_ci}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cistatic inline u8 intel_pt_cpumode(struct intel_pt *pt, uint64_t ip)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	return ip >= pt->kernel_start ?
5558c2ecf20Sopenharmony_ci	       PERF_RECORD_MISC_KERNEL :
5568c2ecf20Sopenharmony_ci	       PERF_RECORD_MISC_USER;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_cistatic int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
5608c2ecf20Sopenharmony_ci				   uint64_t *insn_cnt_ptr, uint64_t *ip,
5618c2ecf20Sopenharmony_ci				   uint64_t to_ip, uint64_t max_insn_cnt,
5628c2ecf20Sopenharmony_ci				   void *data)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = data;
5658c2ecf20Sopenharmony_ci	struct machine *machine = ptq->pt->machine;
5668c2ecf20Sopenharmony_ci	struct thread *thread;
5678c2ecf20Sopenharmony_ci	struct addr_location al;
5688c2ecf20Sopenharmony_ci	unsigned char buf[INTEL_PT_INSN_BUF_SZ];
5698c2ecf20Sopenharmony_ci	ssize_t len;
5708c2ecf20Sopenharmony_ci	int x86_64;
5718c2ecf20Sopenharmony_ci	u8 cpumode;
5728c2ecf20Sopenharmony_ci	u64 offset, start_offset, start_ip;
5738c2ecf20Sopenharmony_ci	u64 insn_cnt = 0;
5748c2ecf20Sopenharmony_ci	bool one_map = true;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	intel_pt_insn->length = 0;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	if (to_ip && *ip == to_ip)
5798c2ecf20Sopenharmony_ci		goto out_no_cache;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	cpumode = intel_pt_cpumode(ptq->pt, *ip);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	thread = ptq->thread;
5848c2ecf20Sopenharmony_ci	if (!thread) {
5858c2ecf20Sopenharmony_ci		if (cpumode != PERF_RECORD_MISC_KERNEL)
5868c2ecf20Sopenharmony_ci			return -EINVAL;
5878c2ecf20Sopenharmony_ci		thread = ptq->pt->unknown_thread;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	while (1) {
5918c2ecf20Sopenharmony_ci		if (!thread__find_map(thread, cpumode, *ip, &al) || !al.map->dso)
5928c2ecf20Sopenharmony_ci			return -EINVAL;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci		if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
5958c2ecf20Sopenharmony_ci		    dso__data_status_seen(al.map->dso,
5968c2ecf20Sopenharmony_ci					  DSO_DATA_STATUS_SEEN_ITRACE))
5978c2ecf20Sopenharmony_ci			return -ENOENT;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci		offset = al.map->map_ip(al.map, *ip);
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci		if (!to_ip && one_map) {
6028c2ecf20Sopenharmony_ci			struct intel_pt_cache_entry *e;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci			e = intel_pt_cache_lookup(al.map->dso, machine, offset);
6058c2ecf20Sopenharmony_ci			if (e &&
6068c2ecf20Sopenharmony_ci			    (!max_insn_cnt || e->insn_cnt <= max_insn_cnt)) {
6078c2ecf20Sopenharmony_ci				*insn_cnt_ptr = e->insn_cnt;
6088c2ecf20Sopenharmony_ci				*ip += e->byte_cnt;
6098c2ecf20Sopenharmony_ci				intel_pt_insn->op = e->op;
6108c2ecf20Sopenharmony_ci				intel_pt_insn->branch = e->branch;
6118c2ecf20Sopenharmony_ci				intel_pt_insn->length = e->length;
6128c2ecf20Sopenharmony_ci				intel_pt_insn->rel = e->rel;
6138c2ecf20Sopenharmony_ci				memcpy(intel_pt_insn->buf, e->insn,
6148c2ecf20Sopenharmony_ci				       INTEL_PT_INSN_BUF_SZ);
6158c2ecf20Sopenharmony_ci				intel_pt_log_insn_no_data(intel_pt_insn, *ip);
6168c2ecf20Sopenharmony_ci				return 0;
6178c2ecf20Sopenharmony_ci			}
6188c2ecf20Sopenharmony_ci		}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci		start_offset = offset;
6218c2ecf20Sopenharmony_ci		start_ip = *ip;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci		/* Load maps to ensure dso->is_64_bit has been updated */
6248c2ecf20Sopenharmony_ci		map__load(al.map);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci		x86_64 = al.map->dso->is_64_bit;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		while (1) {
6298c2ecf20Sopenharmony_ci			len = dso__data_read_offset(al.map->dso, machine,
6308c2ecf20Sopenharmony_ci						    offset, buf,
6318c2ecf20Sopenharmony_ci						    INTEL_PT_INSN_BUF_SZ);
6328c2ecf20Sopenharmony_ci			if (len <= 0)
6338c2ecf20Sopenharmony_ci				return -EINVAL;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci			if (intel_pt_get_insn(buf, len, x86_64, intel_pt_insn))
6368c2ecf20Sopenharmony_ci				return -EINVAL;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci			intel_pt_log_insn(intel_pt_insn, *ip);
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci			insn_cnt += 1;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci			if (intel_pt_insn->branch != INTEL_PT_BR_NO_BRANCH)
6438c2ecf20Sopenharmony_ci				goto out;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci			if (max_insn_cnt && insn_cnt >= max_insn_cnt)
6468c2ecf20Sopenharmony_ci				goto out_no_cache;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci			*ip += intel_pt_insn->length;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci			if (to_ip && *ip == to_ip) {
6518c2ecf20Sopenharmony_ci				intel_pt_insn->length = 0;
6528c2ecf20Sopenharmony_ci				goto out_no_cache;
6538c2ecf20Sopenharmony_ci			}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci			if (*ip >= al.map->end)
6568c2ecf20Sopenharmony_ci				break;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci			offset += intel_pt_insn->length;
6598c2ecf20Sopenharmony_ci		}
6608c2ecf20Sopenharmony_ci		one_map = false;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ciout:
6638c2ecf20Sopenharmony_ci	*insn_cnt_ptr = insn_cnt;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (!one_map)
6668c2ecf20Sopenharmony_ci		goto out_no_cache;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	/*
6698c2ecf20Sopenharmony_ci	 * Didn't lookup in the 'to_ip' case, so do it now to prevent duplicate
6708c2ecf20Sopenharmony_ci	 * entries.
6718c2ecf20Sopenharmony_ci	 */
6728c2ecf20Sopenharmony_ci	if (to_ip) {
6738c2ecf20Sopenharmony_ci		struct intel_pt_cache_entry *e;
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci		e = intel_pt_cache_lookup(al.map->dso, machine, start_offset);
6768c2ecf20Sopenharmony_ci		if (e)
6778c2ecf20Sopenharmony_ci			return 0;
6788c2ecf20Sopenharmony_ci	}
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	/* Ignore cache errors */
6818c2ecf20Sopenharmony_ci	intel_pt_cache_add(al.map->dso, machine, start_offset, insn_cnt,
6828c2ecf20Sopenharmony_ci			   *ip - start_ip, intel_pt_insn);
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	return 0;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ciout_no_cache:
6878c2ecf20Sopenharmony_ci	*insn_cnt_ptr = insn_cnt;
6888c2ecf20Sopenharmony_ci	return 0;
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
6928c2ecf20Sopenharmony_ci				  uint64_t offset, const char *filename)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct addr_filter *filt;
6958c2ecf20Sopenharmony_ci	bool have_filter   = false;
6968c2ecf20Sopenharmony_ci	bool hit_tracestop = false;
6978c2ecf20Sopenharmony_ci	bool hit_filter    = false;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	list_for_each_entry(filt, &pt->filts.head, list) {
7008c2ecf20Sopenharmony_ci		if (filt->start)
7018c2ecf20Sopenharmony_ci			have_filter = true;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci		if ((filename && !filt->filename) ||
7048c2ecf20Sopenharmony_ci		    (!filename && filt->filename) ||
7058c2ecf20Sopenharmony_ci		    (filename && strcmp(filename, filt->filename)))
7068c2ecf20Sopenharmony_ci			continue;
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci		if (!(offset >= filt->addr && offset < filt->addr + filt->size))
7098c2ecf20Sopenharmony_ci			continue;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
7128c2ecf20Sopenharmony_ci			     ip, offset, filename ? filename : "[kernel]",
7138c2ecf20Sopenharmony_ci			     filt->start ? "filter" : "stop",
7148c2ecf20Sopenharmony_ci			     filt->addr, filt->size);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci		if (filt->start)
7178c2ecf20Sopenharmony_ci			hit_filter = true;
7188c2ecf20Sopenharmony_ci		else
7198c2ecf20Sopenharmony_ci			hit_tracestop = true;
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (!hit_tracestop && !hit_filter)
7238c2ecf20Sopenharmony_ci		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
7248c2ecf20Sopenharmony_ci			     ip, offset, filename ? filename : "[kernel]");
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	return hit_tracestop || (have_filter && !hit_filter);
7278c2ecf20Sopenharmony_ci}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_cistatic int __intel_pt_pgd_ip(uint64_t ip, void *data)
7308c2ecf20Sopenharmony_ci{
7318c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = data;
7328c2ecf20Sopenharmony_ci	struct thread *thread;
7338c2ecf20Sopenharmony_ci	struct addr_location al;
7348c2ecf20Sopenharmony_ci	u8 cpumode;
7358c2ecf20Sopenharmony_ci	u64 offset;
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	if (ip >= ptq->pt->kernel_start)
7388c2ecf20Sopenharmony_ci		return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	cpumode = PERF_RECORD_MISC_USER;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	thread = ptq->thread;
7438c2ecf20Sopenharmony_ci	if (!thread)
7448c2ecf20Sopenharmony_ci		return -EINVAL;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso)
7478c2ecf20Sopenharmony_ci		return -EINVAL;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	offset = al.map->map_ip(al.map, ip);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
7528c2ecf20Sopenharmony_ci				     al.map->dso->long_name);
7538c2ecf20Sopenharmony_ci}
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_cistatic bool intel_pt_pgd_ip(uint64_t ip, void *data)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	return __intel_pt_pgd_ip(ip, data) > 0;
7588c2ecf20Sopenharmony_ci}
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_cistatic bool intel_pt_get_config(struct intel_pt *pt,
7618c2ecf20Sopenharmony_ci				struct perf_event_attr *attr, u64 *config)
7628c2ecf20Sopenharmony_ci{
7638c2ecf20Sopenharmony_ci	if (attr->type == pt->pmu_type) {
7648c2ecf20Sopenharmony_ci		if (config)
7658c2ecf20Sopenharmony_ci			*config = attr->config;
7668c2ecf20Sopenharmony_ci		return true;
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	return false;
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cistatic bool intel_pt_exclude_kernel(struct intel_pt *pt)
7738c2ecf20Sopenharmony_ci{
7748c2ecf20Sopenharmony_ci	struct evsel *evsel;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
7778c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, NULL) &&
7788c2ecf20Sopenharmony_ci		    !evsel->core.attr.exclude_kernel)
7798c2ecf20Sopenharmony_ci			return false;
7808c2ecf20Sopenharmony_ci	}
7818c2ecf20Sopenharmony_ci	return true;
7828c2ecf20Sopenharmony_ci}
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_cistatic bool intel_pt_return_compression(struct intel_pt *pt)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct evsel *evsel;
7878c2ecf20Sopenharmony_ci	u64 config;
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	if (!pt->noretcomp_bit)
7908c2ecf20Sopenharmony_ci		return true;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
7938c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&
7948c2ecf20Sopenharmony_ci		    (config & pt->noretcomp_bit))
7958c2ecf20Sopenharmony_ci			return false;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci	return true;
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic bool intel_pt_branch_enable(struct intel_pt *pt)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct evsel *evsel;
8038c2ecf20Sopenharmony_ci	u64 config;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8068c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config) &&
8078c2ecf20Sopenharmony_ci		    (config & 1) && !(config & 0x2000))
8088c2ecf20Sopenharmony_ci			return false;
8098c2ecf20Sopenharmony_ci	}
8108c2ecf20Sopenharmony_ci	return true;
8118c2ecf20Sopenharmony_ci}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_cistatic unsigned int intel_pt_mtc_period(struct intel_pt *pt)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	struct evsel *evsel;
8168c2ecf20Sopenharmony_ci	unsigned int shift;
8178c2ecf20Sopenharmony_ci	u64 config;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	if (!pt->mtc_freq_bits)
8208c2ecf20Sopenharmony_ci		return 0;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
8238c2ecf20Sopenharmony_ci		config >>= 1;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8268c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config))
8278c2ecf20Sopenharmony_ci			return (config & pt->mtc_freq_bits) >> shift;
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci	return 0;
8308c2ecf20Sopenharmony_ci}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_cistatic bool intel_pt_timeless_decoding(struct intel_pt *pt)
8338c2ecf20Sopenharmony_ci{
8348c2ecf20Sopenharmony_ci	struct evsel *evsel;
8358c2ecf20Sopenharmony_ci	bool timeless_decoding = true;
8368c2ecf20Sopenharmony_ci	u64 config;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (!pt->tsc_bit || !pt->cap_user_time_zero)
8398c2ecf20Sopenharmony_ci		return true;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8428c2ecf20Sopenharmony_ci		if (!(evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
8438c2ecf20Sopenharmony_ci			return true;
8448c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {
8458c2ecf20Sopenharmony_ci			if (config & pt->tsc_bit)
8468c2ecf20Sopenharmony_ci				timeless_decoding = false;
8478c2ecf20Sopenharmony_ci			else
8488c2ecf20Sopenharmony_ci				return true;
8498c2ecf20Sopenharmony_ci		}
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci	return timeless_decoding;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_cistatic bool intel_pt_tracing_kernel(struct intel_pt *pt)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	struct evsel *evsel;
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8598c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, NULL) &&
8608c2ecf20Sopenharmony_ci		    !evsel->core.attr.exclude_kernel)
8618c2ecf20Sopenharmony_ci			return true;
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci	return false;
8648c2ecf20Sopenharmony_ci}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_cistatic bool intel_pt_have_tsc(struct intel_pt *pt)
8678c2ecf20Sopenharmony_ci{
8688c2ecf20Sopenharmony_ci	struct evsel *evsel;
8698c2ecf20Sopenharmony_ci	bool have_tsc = false;
8708c2ecf20Sopenharmony_ci	u64 config;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	if (!pt->tsc_bit)
8738c2ecf20Sopenharmony_ci		return false;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8768c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config)) {
8778c2ecf20Sopenharmony_ci			if (config & pt->tsc_bit)
8788c2ecf20Sopenharmony_ci				have_tsc = true;
8798c2ecf20Sopenharmony_ci			else
8808c2ecf20Sopenharmony_ci				return false;
8818c2ecf20Sopenharmony_ci		}
8828c2ecf20Sopenharmony_ci	}
8838c2ecf20Sopenharmony_ci	return have_tsc;
8848c2ecf20Sopenharmony_ci}
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_cistatic bool intel_pt_sampling_mode(struct intel_pt *pt)
8878c2ecf20Sopenharmony_ci{
8888c2ecf20Sopenharmony_ci	struct evsel *evsel;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
8918c2ecf20Sopenharmony_ci		if ((evsel->core.attr.sample_type & PERF_SAMPLE_AUX) &&
8928c2ecf20Sopenharmony_ci		    evsel->core.attr.aux_sample_size)
8938c2ecf20Sopenharmony_ci			return true;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci	return false;
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_cistatic u64 intel_pt_ctl(struct intel_pt *pt)
8998c2ecf20Sopenharmony_ci{
9008c2ecf20Sopenharmony_ci	struct evsel *evsel;
9018c2ecf20Sopenharmony_ci	u64 config;
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
9048c2ecf20Sopenharmony_ci		if (intel_pt_get_config(pt, &evsel->core.attr, &config))
9058c2ecf20Sopenharmony_ci			return config;
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci	return 0;
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_cistatic u64 intel_pt_ns_to_ticks(const struct intel_pt *pt, u64 ns)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci	u64 quot, rem;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	quot = ns / pt->tc.time_mult;
9158c2ecf20Sopenharmony_ci	rem  = ns % pt->tc.time_mult;
9168c2ecf20Sopenharmony_ci	return (quot << pt->tc.time_shift) + (rem << pt->tc.time_shift) /
9178c2ecf20Sopenharmony_ci		pt->tc.time_mult;
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_cistatic struct ip_callchain *intel_pt_alloc_chain(struct intel_pt *pt)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	size_t sz = sizeof(struct ip_callchain);
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	/* Add 1 to callchain_sz for callchain context */
9258c2ecf20Sopenharmony_ci	sz += (pt->synth_opts.callchain_sz + 1) * sizeof(u64);
9268c2ecf20Sopenharmony_ci	return zalloc(sz);
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_cistatic int intel_pt_callchain_init(struct intel_pt *pt)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	struct evsel *evsel;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
9348c2ecf20Sopenharmony_ci		if (!(evsel->core.attr.sample_type & PERF_SAMPLE_CALLCHAIN))
9358c2ecf20Sopenharmony_ci			evsel->synth_sample_type |= PERF_SAMPLE_CALLCHAIN;
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	pt->chain = intel_pt_alloc_chain(pt);
9398c2ecf20Sopenharmony_ci	if (!pt->chain)
9408c2ecf20Sopenharmony_ci		return -ENOMEM;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	return 0;
9438c2ecf20Sopenharmony_ci}
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_cistatic void intel_pt_add_callchain(struct intel_pt *pt,
9468c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	struct thread *thread = machine__findnew_thread(pt->machine,
9498c2ecf20Sopenharmony_ci							sample->pid,
9508c2ecf20Sopenharmony_ci							sample->tid);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	thread_stack__sample_late(thread, sample->cpu, pt->chain,
9538c2ecf20Sopenharmony_ci				  pt->synth_opts.callchain_sz + 1, sample->ip,
9548c2ecf20Sopenharmony_ci				  pt->kernel_start);
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	sample->callchain = pt->chain;
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_cistatic struct branch_stack *intel_pt_alloc_br_stack(unsigned int entry_cnt)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	size_t sz = sizeof(struct branch_stack);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	sz += entry_cnt * sizeof(struct branch_entry);
9648c2ecf20Sopenharmony_ci	return zalloc(sz);
9658c2ecf20Sopenharmony_ci}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_cistatic int intel_pt_br_stack_init(struct intel_pt *pt)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct evsel *evsel;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
9728c2ecf20Sopenharmony_ci		if (!(evsel->core.attr.sample_type & PERF_SAMPLE_BRANCH_STACK))
9738c2ecf20Sopenharmony_ci			evsel->synth_sample_type |= PERF_SAMPLE_BRANCH_STACK;
9748c2ecf20Sopenharmony_ci	}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	pt->br_stack = intel_pt_alloc_br_stack(pt->br_stack_sz);
9778c2ecf20Sopenharmony_ci	if (!pt->br_stack)
9788c2ecf20Sopenharmony_ci		return -ENOMEM;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci	return 0;
9818c2ecf20Sopenharmony_ci}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_cistatic void intel_pt_add_br_stack(struct intel_pt *pt,
9848c2ecf20Sopenharmony_ci				  struct perf_sample *sample)
9858c2ecf20Sopenharmony_ci{
9868c2ecf20Sopenharmony_ci	struct thread *thread = machine__findnew_thread(pt->machine,
9878c2ecf20Sopenharmony_ci							sample->pid,
9888c2ecf20Sopenharmony_ci							sample->tid);
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	thread_stack__br_sample_late(thread, sample->cpu, pt->br_stack,
9918c2ecf20Sopenharmony_ci				     pt->br_stack_sz, sample->ip,
9928c2ecf20Sopenharmony_ci				     pt->kernel_start);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	sample->branch_stack = pt->br_stack;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci/* INTEL_PT_LBR_0, INTEL_PT_LBR_1 and INTEL_PT_LBR_2 */
9988c2ecf20Sopenharmony_ci#define LBRS_MAX (INTEL_PT_BLK_ITEM_ID_CNT * 3U)
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_cistatic struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
10018c2ecf20Sopenharmony_ci						   unsigned int queue_nr)
10028c2ecf20Sopenharmony_ci{
10038c2ecf20Sopenharmony_ci	struct intel_pt_params params = { .get_trace = 0, };
10048c2ecf20Sopenharmony_ci	struct perf_env *env = pt->machine->env;
10058c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq;
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci	ptq = zalloc(sizeof(struct intel_pt_queue));
10088c2ecf20Sopenharmony_ci	if (!ptq)
10098c2ecf20Sopenharmony_ci		return NULL;
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	if (pt->synth_opts.callchain) {
10128c2ecf20Sopenharmony_ci		ptq->chain = intel_pt_alloc_chain(pt);
10138c2ecf20Sopenharmony_ci		if (!ptq->chain)
10148c2ecf20Sopenharmony_ci			goto out_free;
10158c2ecf20Sopenharmony_ci	}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	if (pt->synth_opts.last_branch || pt->synth_opts.other_events) {
10188c2ecf20Sopenharmony_ci		unsigned int entry_cnt = max(LBRS_MAX, pt->br_stack_sz);
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci		ptq->last_branch = intel_pt_alloc_br_stack(entry_cnt);
10218c2ecf20Sopenharmony_ci		if (!ptq->last_branch)
10228c2ecf20Sopenharmony_ci			goto out_free;
10238c2ecf20Sopenharmony_ci	}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
10268c2ecf20Sopenharmony_ci	if (!ptq->event_buf)
10278c2ecf20Sopenharmony_ci		goto out_free;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	ptq->pt = pt;
10308c2ecf20Sopenharmony_ci	ptq->queue_nr = queue_nr;
10318c2ecf20Sopenharmony_ci	ptq->exclude_kernel = intel_pt_exclude_kernel(pt);
10328c2ecf20Sopenharmony_ci	ptq->pid = -1;
10338c2ecf20Sopenharmony_ci	ptq->tid = -1;
10348c2ecf20Sopenharmony_ci	ptq->cpu = -1;
10358c2ecf20Sopenharmony_ci	ptq->next_tid = -1;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	params.get_trace = intel_pt_get_trace;
10388c2ecf20Sopenharmony_ci	params.walk_insn = intel_pt_walk_next_insn;
10398c2ecf20Sopenharmony_ci	params.lookahead = intel_pt_lookahead;
10408c2ecf20Sopenharmony_ci	params.data = ptq;
10418c2ecf20Sopenharmony_ci	params.return_compression = intel_pt_return_compression(pt);
10428c2ecf20Sopenharmony_ci	params.branch_enable = intel_pt_branch_enable(pt);
10438c2ecf20Sopenharmony_ci	params.ctl = intel_pt_ctl(pt);
10448c2ecf20Sopenharmony_ci	params.max_non_turbo_ratio = pt->max_non_turbo_ratio;
10458c2ecf20Sopenharmony_ci	params.mtc_period = intel_pt_mtc_period(pt);
10468c2ecf20Sopenharmony_ci	params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
10478c2ecf20Sopenharmony_ci	params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
10488c2ecf20Sopenharmony_ci	params.quick = pt->synth_opts.quick;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	if (pt->filts.cnt > 0)
10518c2ecf20Sopenharmony_ci		params.pgd_ip = intel_pt_pgd_ip;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	if (pt->synth_opts.instructions) {
10548c2ecf20Sopenharmony_ci		if (pt->synth_opts.period) {
10558c2ecf20Sopenharmony_ci			switch (pt->synth_opts.period_type) {
10568c2ecf20Sopenharmony_ci			case PERF_ITRACE_PERIOD_INSTRUCTIONS:
10578c2ecf20Sopenharmony_ci				params.period_type =
10588c2ecf20Sopenharmony_ci						INTEL_PT_PERIOD_INSTRUCTIONS;
10598c2ecf20Sopenharmony_ci				params.period = pt->synth_opts.period;
10608c2ecf20Sopenharmony_ci				break;
10618c2ecf20Sopenharmony_ci			case PERF_ITRACE_PERIOD_TICKS:
10628c2ecf20Sopenharmony_ci				params.period_type = INTEL_PT_PERIOD_TICKS;
10638c2ecf20Sopenharmony_ci				params.period = pt->synth_opts.period;
10648c2ecf20Sopenharmony_ci				break;
10658c2ecf20Sopenharmony_ci			case PERF_ITRACE_PERIOD_NANOSECS:
10668c2ecf20Sopenharmony_ci				params.period_type = INTEL_PT_PERIOD_TICKS;
10678c2ecf20Sopenharmony_ci				params.period = intel_pt_ns_to_ticks(pt,
10688c2ecf20Sopenharmony_ci							pt->synth_opts.period);
10698c2ecf20Sopenharmony_ci				break;
10708c2ecf20Sopenharmony_ci			default:
10718c2ecf20Sopenharmony_ci				break;
10728c2ecf20Sopenharmony_ci			}
10738c2ecf20Sopenharmony_ci		}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci		if (!params.period) {
10768c2ecf20Sopenharmony_ci			params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS;
10778c2ecf20Sopenharmony_ci			params.period = 1;
10788c2ecf20Sopenharmony_ci		}
10798c2ecf20Sopenharmony_ci	}
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	if (env->cpuid && !strncmp(env->cpuid, "GenuineIntel,6,92,", 18))
10828c2ecf20Sopenharmony_ci		params.flags |= INTEL_PT_FUP_WITH_NLIP;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	ptq->decoder = intel_pt_decoder_new(&params);
10858c2ecf20Sopenharmony_ci	if (!ptq->decoder)
10868c2ecf20Sopenharmony_ci		goto out_free;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	return ptq;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ciout_free:
10918c2ecf20Sopenharmony_ci	zfree(&ptq->event_buf);
10928c2ecf20Sopenharmony_ci	zfree(&ptq->last_branch);
10938c2ecf20Sopenharmony_ci	zfree(&ptq->chain);
10948c2ecf20Sopenharmony_ci	free(ptq);
10958c2ecf20Sopenharmony_ci	return NULL;
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic void intel_pt_free_queue(void *priv)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = priv;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	if (!ptq)
11038c2ecf20Sopenharmony_ci		return;
11048c2ecf20Sopenharmony_ci	thread__zput(ptq->thread);
11058c2ecf20Sopenharmony_ci	intel_pt_decoder_free(ptq->decoder);
11068c2ecf20Sopenharmony_ci	zfree(&ptq->event_buf);
11078c2ecf20Sopenharmony_ci	zfree(&ptq->last_branch);
11088c2ecf20Sopenharmony_ci	zfree(&ptq->chain);
11098c2ecf20Sopenharmony_ci	free(ptq);
11108c2ecf20Sopenharmony_ci}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_cistatic void intel_pt_set_pid_tid_cpu(struct intel_pt *pt,
11138c2ecf20Sopenharmony_ci				     struct auxtrace_queue *queue)
11148c2ecf20Sopenharmony_ci{
11158c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = queue->priv;
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	if (queue->tid == -1 || pt->have_sched_switch) {
11188c2ecf20Sopenharmony_ci		ptq->tid = machine__get_current_tid(pt->machine, ptq->cpu);
11198c2ecf20Sopenharmony_ci		if (ptq->tid == -1)
11208c2ecf20Sopenharmony_ci			ptq->pid = -1;
11218c2ecf20Sopenharmony_ci		thread__zput(ptq->thread);
11228c2ecf20Sopenharmony_ci	}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	if (!ptq->thread && ptq->tid != -1)
11258c2ecf20Sopenharmony_ci		ptq->thread = machine__find_thread(pt->machine, -1, ptq->tid);
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	if (ptq->thread) {
11288c2ecf20Sopenharmony_ci		ptq->pid = ptq->thread->pid_;
11298c2ecf20Sopenharmony_ci		if (queue->cpu == -1)
11308c2ecf20Sopenharmony_ci			ptq->cpu = ptq->thread->cpu;
11318c2ecf20Sopenharmony_ci	}
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_cistatic void intel_pt_sample_flags(struct intel_pt_queue *ptq)
11358c2ecf20Sopenharmony_ci{
11368c2ecf20Sopenharmony_ci	ptq->insn_len = 0;
11378c2ecf20Sopenharmony_ci	if (ptq->state->flags & INTEL_PT_ABORT_TX) {
11388c2ecf20Sopenharmony_ci		ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT;
11398c2ecf20Sopenharmony_ci	} else if (ptq->state->flags & INTEL_PT_ASYNC) {
11408c2ecf20Sopenharmony_ci		if (ptq->state->to_ip)
11418c2ecf20Sopenharmony_ci			ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
11428c2ecf20Sopenharmony_ci				     PERF_IP_FLAG_ASYNC |
11438c2ecf20Sopenharmony_ci				     PERF_IP_FLAG_INTERRUPT;
11448c2ecf20Sopenharmony_ci		else
11458c2ecf20Sopenharmony_ci			ptq->flags = PERF_IP_FLAG_BRANCH |
11468c2ecf20Sopenharmony_ci				     PERF_IP_FLAG_TRACE_END;
11478c2ecf20Sopenharmony_ci		ptq->insn_len = 0;
11488c2ecf20Sopenharmony_ci	} else {
11498c2ecf20Sopenharmony_ci		if (ptq->state->from_ip)
11508c2ecf20Sopenharmony_ci			ptq->flags = intel_pt_insn_type(ptq->state->insn_op);
11518c2ecf20Sopenharmony_ci		else
11528c2ecf20Sopenharmony_ci			ptq->flags = PERF_IP_FLAG_BRANCH |
11538c2ecf20Sopenharmony_ci				     PERF_IP_FLAG_TRACE_BEGIN;
11548c2ecf20Sopenharmony_ci		if (ptq->state->flags & INTEL_PT_IN_TX)
11558c2ecf20Sopenharmony_ci			ptq->flags |= PERF_IP_FLAG_IN_TX;
11568c2ecf20Sopenharmony_ci		ptq->insn_len = ptq->state->insn_len;
11578c2ecf20Sopenharmony_ci		memcpy(ptq->insn, ptq->state->insn, INTEL_PT_INSN_BUF_SZ);
11588c2ecf20Sopenharmony_ci	}
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	if (ptq->state->type & INTEL_PT_TRACE_BEGIN)
11618c2ecf20Sopenharmony_ci		ptq->flags |= PERF_IP_FLAG_TRACE_BEGIN;
11628c2ecf20Sopenharmony_ci	if (ptq->state->type & INTEL_PT_TRACE_END)
11638c2ecf20Sopenharmony_ci		ptq->flags |= PERF_IP_FLAG_TRACE_END;
11648c2ecf20Sopenharmony_ci}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_cistatic void intel_pt_setup_time_range(struct intel_pt *pt,
11678c2ecf20Sopenharmony_ci				      struct intel_pt_queue *ptq)
11688c2ecf20Sopenharmony_ci{
11698c2ecf20Sopenharmony_ci	if (!pt->range_cnt)
11708c2ecf20Sopenharmony_ci		return;
11718c2ecf20Sopenharmony_ci
11728c2ecf20Sopenharmony_ci	ptq->sel_timestamp = pt->time_ranges[0].start;
11738c2ecf20Sopenharmony_ci	ptq->sel_idx = 0;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	if (ptq->sel_timestamp) {
11768c2ecf20Sopenharmony_ci		ptq->sel_start = true;
11778c2ecf20Sopenharmony_ci	} else {
11788c2ecf20Sopenharmony_ci		ptq->sel_timestamp = pt->time_ranges[0].end;
11798c2ecf20Sopenharmony_ci		ptq->sel_start = false;
11808c2ecf20Sopenharmony_ci	}
11818c2ecf20Sopenharmony_ci}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_cistatic int intel_pt_setup_queue(struct intel_pt *pt,
11848c2ecf20Sopenharmony_ci				struct auxtrace_queue *queue,
11858c2ecf20Sopenharmony_ci				unsigned int queue_nr)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq = queue->priv;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	if (list_empty(&queue->head))
11908c2ecf20Sopenharmony_ci		return 0;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	if (!ptq) {
11938c2ecf20Sopenharmony_ci		ptq = intel_pt_alloc_queue(pt, queue_nr);
11948c2ecf20Sopenharmony_ci		if (!ptq)
11958c2ecf20Sopenharmony_ci			return -ENOMEM;
11968c2ecf20Sopenharmony_ci		queue->priv = ptq;
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci		if (queue->cpu != -1)
11998c2ecf20Sopenharmony_ci			ptq->cpu = queue->cpu;
12008c2ecf20Sopenharmony_ci		ptq->tid = queue->tid;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci		ptq->cbr_seen = UINT_MAX;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci		if (pt->sampling_mode && !pt->snapshot_mode &&
12058c2ecf20Sopenharmony_ci		    pt->timeless_decoding)
12068c2ecf20Sopenharmony_ci			ptq->step_through_buffers = true;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci		ptq->sync_switch = pt->sync_switch;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci		intel_pt_setup_time_range(pt, ptq);
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	if (!ptq->on_heap &&
12148c2ecf20Sopenharmony_ci	    (!ptq->sync_switch ||
12158c2ecf20Sopenharmony_ci	     ptq->switch_state != INTEL_PT_SS_EXPECTING_SWITCH_EVENT)) {
12168c2ecf20Sopenharmony_ci		const struct intel_pt_state *state;
12178c2ecf20Sopenharmony_ci		int ret;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci		if (pt->timeless_decoding)
12208c2ecf20Sopenharmony_ci			return 0;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci		intel_pt_log("queue %u getting timestamp\n", queue_nr);
12238c2ecf20Sopenharmony_ci		intel_pt_log("queue %u decoding cpu %d pid %d tid %d\n",
12248c2ecf20Sopenharmony_ci			     queue_nr, ptq->cpu, ptq->pid, ptq->tid);
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci		if (ptq->sel_start && ptq->sel_timestamp) {
12278c2ecf20Sopenharmony_ci			ret = intel_pt_fast_forward(ptq->decoder,
12288c2ecf20Sopenharmony_ci						    ptq->sel_timestamp);
12298c2ecf20Sopenharmony_ci			if (ret)
12308c2ecf20Sopenharmony_ci				return ret;
12318c2ecf20Sopenharmony_ci		}
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci		while (1) {
12348c2ecf20Sopenharmony_ci			state = intel_pt_decode(ptq->decoder);
12358c2ecf20Sopenharmony_ci			if (state->err) {
12368c2ecf20Sopenharmony_ci				if (state->err == INTEL_PT_ERR_NODATA) {
12378c2ecf20Sopenharmony_ci					intel_pt_log("queue %u has no timestamp\n",
12388c2ecf20Sopenharmony_ci						     queue_nr);
12398c2ecf20Sopenharmony_ci					return 0;
12408c2ecf20Sopenharmony_ci				}
12418c2ecf20Sopenharmony_ci				continue;
12428c2ecf20Sopenharmony_ci			}
12438c2ecf20Sopenharmony_ci			if (state->timestamp)
12448c2ecf20Sopenharmony_ci				break;
12458c2ecf20Sopenharmony_ci		}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci		ptq->timestamp = state->timestamp;
12488c2ecf20Sopenharmony_ci		intel_pt_log("queue %u timestamp 0x%" PRIx64 "\n",
12498c2ecf20Sopenharmony_ci			     queue_nr, ptq->timestamp);
12508c2ecf20Sopenharmony_ci		ptq->state = state;
12518c2ecf20Sopenharmony_ci		ptq->have_sample = true;
12528c2ecf20Sopenharmony_ci		if (ptq->sel_start && ptq->sel_timestamp &&
12538c2ecf20Sopenharmony_ci		    ptq->timestamp < ptq->sel_timestamp)
12548c2ecf20Sopenharmony_ci			ptq->have_sample = false;
12558c2ecf20Sopenharmony_ci		intel_pt_sample_flags(ptq);
12568c2ecf20Sopenharmony_ci		ret = auxtrace_heap__add(&pt->heap, queue_nr, ptq->timestamp);
12578c2ecf20Sopenharmony_ci		if (ret)
12588c2ecf20Sopenharmony_ci			return ret;
12598c2ecf20Sopenharmony_ci		ptq->on_heap = true;
12608c2ecf20Sopenharmony_ci	}
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	return 0;
12638c2ecf20Sopenharmony_ci}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_cistatic int intel_pt_setup_queues(struct intel_pt *pt)
12668c2ecf20Sopenharmony_ci{
12678c2ecf20Sopenharmony_ci	unsigned int i;
12688c2ecf20Sopenharmony_ci	int ret;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	for (i = 0; i < pt->queues.nr_queues; i++) {
12718c2ecf20Sopenharmony_ci		ret = intel_pt_setup_queue(pt, &pt->queues.queue_array[i], i);
12728c2ecf20Sopenharmony_ci		if (ret)
12738c2ecf20Sopenharmony_ci			return ret;
12748c2ecf20Sopenharmony_ci	}
12758c2ecf20Sopenharmony_ci	return 0;
12768c2ecf20Sopenharmony_ci}
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_cistatic inline bool intel_pt_skip_event(struct intel_pt *pt)
12798c2ecf20Sopenharmony_ci{
12808c2ecf20Sopenharmony_ci	return pt->synth_opts.initial_skip &&
12818c2ecf20Sopenharmony_ci	       pt->num_events++ < pt->synth_opts.initial_skip;
12828c2ecf20Sopenharmony_ci}
12838c2ecf20Sopenharmony_ci
12848c2ecf20Sopenharmony_ci/*
12858c2ecf20Sopenharmony_ci * Cannot count CBR as skipped because it won't go away until cbr == cbr_seen.
12868c2ecf20Sopenharmony_ci * Also ensure CBR is first non-skipped event by allowing for 4 more samples
12878c2ecf20Sopenharmony_ci * from this decoder state.
12888c2ecf20Sopenharmony_ci */
12898c2ecf20Sopenharmony_cistatic inline bool intel_pt_skip_cbr_event(struct intel_pt *pt)
12908c2ecf20Sopenharmony_ci{
12918c2ecf20Sopenharmony_ci	return pt->synth_opts.initial_skip &&
12928c2ecf20Sopenharmony_ci	       pt->num_events + 4 < pt->synth_opts.initial_skip;
12938c2ecf20Sopenharmony_ci}
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_cistatic void intel_pt_prep_a_sample(struct intel_pt_queue *ptq,
12968c2ecf20Sopenharmony_ci				   union perf_event *event,
12978c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
12988c2ecf20Sopenharmony_ci{
12998c2ecf20Sopenharmony_ci	event->sample.header.type = PERF_RECORD_SAMPLE;
13008c2ecf20Sopenharmony_ci	event->sample.header.size = sizeof(struct perf_event_header);
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	sample->pid = ptq->pid;
13038c2ecf20Sopenharmony_ci	sample->tid = ptq->tid;
13048c2ecf20Sopenharmony_ci	sample->cpu = ptq->cpu;
13058c2ecf20Sopenharmony_ci	sample->insn_len = ptq->insn_len;
13068c2ecf20Sopenharmony_ci	memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
13078c2ecf20Sopenharmony_ci}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_cistatic void intel_pt_prep_b_sample(struct intel_pt *pt,
13108c2ecf20Sopenharmony_ci				   struct intel_pt_queue *ptq,
13118c2ecf20Sopenharmony_ci				   union perf_event *event,
13128c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
13138c2ecf20Sopenharmony_ci{
13148c2ecf20Sopenharmony_ci	intel_pt_prep_a_sample(ptq, event, sample);
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	if (!pt->timeless_decoding)
13178c2ecf20Sopenharmony_ci		sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	sample->ip = ptq->state->from_ip;
13208c2ecf20Sopenharmony_ci	sample->cpumode = intel_pt_cpumode(pt, sample->ip);
13218c2ecf20Sopenharmony_ci	sample->addr = ptq->state->to_ip;
13228c2ecf20Sopenharmony_ci	sample->period = 1;
13238c2ecf20Sopenharmony_ci	sample->flags = ptq->flags;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	event->sample.header.misc = sample->cpumode;
13268c2ecf20Sopenharmony_ci}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_cistatic int intel_pt_inject_event(union perf_event *event,
13298c2ecf20Sopenharmony_ci				 struct perf_sample *sample, u64 type)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	event->header.size = perf_event__sample_event_size(sample, type, 0);
13328c2ecf20Sopenharmony_ci	return perf_event__synthesize_sample(event, type, 0, sample);
13338c2ecf20Sopenharmony_ci}
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_cistatic inline int intel_pt_opt_inject(struct intel_pt *pt,
13368c2ecf20Sopenharmony_ci				      union perf_event *event,
13378c2ecf20Sopenharmony_ci				      struct perf_sample *sample, u64 type)
13388c2ecf20Sopenharmony_ci{
13398c2ecf20Sopenharmony_ci	if (!pt->synth_opts.inject)
13408c2ecf20Sopenharmony_ci		return 0;
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	return intel_pt_inject_event(event, sample, type);
13438c2ecf20Sopenharmony_ci}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_cistatic int intel_pt_deliver_synth_event(struct intel_pt *pt,
13468c2ecf20Sopenharmony_ci					union perf_event *event,
13478c2ecf20Sopenharmony_ci					struct perf_sample *sample, u64 type)
13488c2ecf20Sopenharmony_ci{
13498c2ecf20Sopenharmony_ci	int ret;
13508c2ecf20Sopenharmony_ci
13518c2ecf20Sopenharmony_ci	ret = intel_pt_opt_inject(pt, event, sample, type);
13528c2ecf20Sopenharmony_ci	if (ret)
13538c2ecf20Sopenharmony_ci		return ret;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	ret = perf_session__deliver_synth_event(pt->session, event, sample);
13568c2ecf20Sopenharmony_ci	if (ret)
13578c2ecf20Sopenharmony_ci		pr_err("Intel PT: failed to deliver event, error %d\n", ret);
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	return ret;
13608c2ecf20Sopenharmony_ci}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_cistatic int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
13638c2ecf20Sopenharmony_ci{
13648c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
13658c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
13668c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
13678c2ecf20Sopenharmony_ci	struct dummy_branch_stack {
13688c2ecf20Sopenharmony_ci		u64			nr;
13698c2ecf20Sopenharmony_ci		u64			hw_idx;
13708c2ecf20Sopenharmony_ci		struct branch_entry	entries;
13718c2ecf20Sopenharmony_ci	} dummy_bs;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
13748c2ecf20Sopenharmony_ci		return 0;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
13778c2ecf20Sopenharmony_ci		return 0;
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	intel_pt_prep_b_sample(pt, ptq, event, &sample);
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci	sample.id = ptq->pt->branches_id;
13828c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->branches_id;
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	/*
13858c2ecf20Sopenharmony_ci	 * perf report cannot handle events without a branch stack when using
13868c2ecf20Sopenharmony_ci	 * SORT_MODE__BRANCH so make a dummy one.
13878c2ecf20Sopenharmony_ci	 */
13888c2ecf20Sopenharmony_ci	if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) {
13898c2ecf20Sopenharmony_ci		dummy_bs = (struct dummy_branch_stack){
13908c2ecf20Sopenharmony_ci			.nr = 1,
13918c2ecf20Sopenharmony_ci			.hw_idx = -1ULL,
13928c2ecf20Sopenharmony_ci			.entries = {
13938c2ecf20Sopenharmony_ci				.from = sample.ip,
13948c2ecf20Sopenharmony_ci				.to = sample.addr,
13958c2ecf20Sopenharmony_ci			},
13968c2ecf20Sopenharmony_ci		};
13978c2ecf20Sopenharmony_ci		sample.branch_stack = (struct branch_stack *)&dummy_bs;
13988c2ecf20Sopenharmony_ci	}
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	if (ptq->state->flags & INTEL_PT_SAMPLE_IPC)
14018c2ecf20Sopenharmony_ci		sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_br_cyc_cnt;
14028c2ecf20Sopenharmony_ci	if (sample.cyc_cnt) {
14038c2ecf20Sopenharmony_ci		sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_br_insn_cnt;
14048c2ecf20Sopenharmony_ci		ptq->last_br_insn_cnt = ptq->ipc_insn_cnt;
14058c2ecf20Sopenharmony_ci		ptq->last_br_cyc_cnt = ptq->ipc_cyc_cnt;
14068c2ecf20Sopenharmony_ci	}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
14098c2ecf20Sopenharmony_ci					    pt->branches_sample_type);
14108c2ecf20Sopenharmony_ci}
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_cistatic void intel_pt_prep_sample(struct intel_pt *pt,
14138c2ecf20Sopenharmony_ci				 struct intel_pt_queue *ptq,
14148c2ecf20Sopenharmony_ci				 union perf_event *event,
14158c2ecf20Sopenharmony_ci				 struct perf_sample *sample)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	intel_pt_prep_b_sample(pt, ptq, event, sample);
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	if (pt->synth_opts.callchain) {
14208c2ecf20Sopenharmony_ci		thread_stack__sample(ptq->thread, ptq->cpu, ptq->chain,
14218c2ecf20Sopenharmony_ci				     pt->synth_opts.callchain_sz + 1,
14228c2ecf20Sopenharmony_ci				     sample->ip, pt->kernel_start);
14238c2ecf20Sopenharmony_ci		sample->callchain = ptq->chain;
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	if (pt->synth_opts.last_branch) {
14278c2ecf20Sopenharmony_ci		thread_stack__br_sample(ptq->thread, ptq->cpu, ptq->last_branch,
14288c2ecf20Sopenharmony_ci					pt->br_stack_sz);
14298c2ecf20Sopenharmony_ci		sample->branch_stack = ptq->last_branch;
14308c2ecf20Sopenharmony_ci	}
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_cistatic int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
14348c2ecf20Sopenharmony_ci{
14358c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
14368c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
14378c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
14408c2ecf20Sopenharmony_ci		return 0;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	intel_pt_prep_sample(pt, ptq, event, &sample);
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	sample.id = ptq->pt->instructions_id;
14458c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->instructions_id;
14468c2ecf20Sopenharmony_ci	if (pt->synth_opts.quick)
14478c2ecf20Sopenharmony_ci		sample.period = 1;
14488c2ecf20Sopenharmony_ci	else
14498c2ecf20Sopenharmony_ci		sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci	if (ptq->state->flags & INTEL_PT_SAMPLE_IPC)
14528c2ecf20Sopenharmony_ci		sample.cyc_cnt = ptq->ipc_cyc_cnt - ptq->last_in_cyc_cnt;
14538c2ecf20Sopenharmony_ci	if (sample.cyc_cnt) {
14548c2ecf20Sopenharmony_ci		sample.insn_cnt = ptq->ipc_insn_cnt - ptq->last_in_insn_cnt;
14558c2ecf20Sopenharmony_ci		ptq->last_in_insn_cnt = ptq->ipc_insn_cnt;
14568c2ecf20Sopenharmony_ci		ptq->last_in_cyc_cnt = ptq->ipc_cyc_cnt;
14578c2ecf20Sopenharmony_ci	}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	ptq->last_insn_cnt = ptq->state->tot_insn_cnt;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
14628c2ecf20Sopenharmony_ci					    pt->instructions_sample_type);
14638c2ecf20Sopenharmony_ci}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_cistatic int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
14688c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
14698c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
14728c2ecf20Sopenharmony_ci		return 0;
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	intel_pt_prep_sample(pt, ptq, event, &sample);
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci	sample.id = ptq->pt->transactions_id;
14778c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->transactions_id;
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
14808c2ecf20Sopenharmony_ci					    pt->transactions_sample_type);
14818c2ecf20Sopenharmony_ci}
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_cistatic void intel_pt_prep_p_sample(struct intel_pt *pt,
14848c2ecf20Sopenharmony_ci				   struct intel_pt_queue *ptq,
14858c2ecf20Sopenharmony_ci				   union perf_event *event,
14868c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
14878c2ecf20Sopenharmony_ci{
14888c2ecf20Sopenharmony_ci	intel_pt_prep_sample(pt, ptq, event, sample);
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci	/*
14918c2ecf20Sopenharmony_ci	 * Zero IP is used to mean "trace start" but that is not the case for
14928c2ecf20Sopenharmony_ci	 * power or PTWRITE events with no IP, so clear the flags.
14938c2ecf20Sopenharmony_ci	 */
14948c2ecf20Sopenharmony_ci	if (!sample->ip)
14958c2ecf20Sopenharmony_ci		sample->flags = 0;
14968c2ecf20Sopenharmony_ci}
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_cistatic int intel_pt_synth_ptwrite_sample(struct intel_pt_queue *ptq)
14998c2ecf20Sopenharmony_ci{
15008c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
15018c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
15028c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
15038c2ecf20Sopenharmony_ci	struct perf_synth_intel_ptwrite raw;
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
15068c2ecf20Sopenharmony_ci		return 0;
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci	sample.id = ptq->pt->ptwrites_id;
15118c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->ptwrites_id;
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	raw.flags = 0;
15148c2ecf20Sopenharmony_ci	raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP);
15158c2ecf20Sopenharmony_ci	raw.payload = cpu_to_le64(ptq->state->ptw_payload);
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
15188c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
15198c2ecf20Sopenharmony_ci
15208c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
15218c2ecf20Sopenharmony_ci					    pt->ptwrites_sample_type);
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_cistatic int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq)
15258c2ecf20Sopenharmony_ci{
15268c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
15278c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
15288c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
15298c2ecf20Sopenharmony_ci	struct perf_synth_intel_cbr raw;
15308c2ecf20Sopenharmony_ci	u32 flags;
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	if (intel_pt_skip_cbr_event(pt))
15338c2ecf20Sopenharmony_ci		return 0;
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	ptq->cbr_seen = ptq->state->cbr;
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	sample.id = ptq->pt->cbr_id;
15408c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->cbr_id;
15418c2ecf20Sopenharmony_ci
15428c2ecf20Sopenharmony_ci	flags = (u16)ptq->state->cbr_payload | (pt->max_non_turbo_ratio << 16);
15438c2ecf20Sopenharmony_ci	raw.flags = cpu_to_le32(flags);
15448c2ecf20Sopenharmony_ci	raw.freq = cpu_to_le32(raw.cbr * pt->cbr2khz);
15458c2ecf20Sopenharmony_ci	raw.reserved3 = 0;
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
15488c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
15518c2ecf20Sopenharmony_ci					    pt->pwr_events_sample_type);
15528c2ecf20Sopenharmony_ci}
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_cistatic int intel_pt_synth_mwait_sample(struct intel_pt_queue *ptq)
15558c2ecf20Sopenharmony_ci{
15568c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
15578c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
15588c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
15598c2ecf20Sopenharmony_ci	struct perf_synth_intel_mwait raw;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
15628c2ecf20Sopenharmony_ci		return 0;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	sample.id = ptq->pt->mwait_id;
15678c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->mwait_id;
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci	raw.reserved = 0;
15708c2ecf20Sopenharmony_ci	raw.payload = cpu_to_le64(ptq->state->mwait_payload);
15718c2ecf20Sopenharmony_ci
15728c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
15738c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
15768c2ecf20Sopenharmony_ci					    pt->pwr_events_sample_type);
15778c2ecf20Sopenharmony_ci}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_cistatic int intel_pt_synth_pwre_sample(struct intel_pt_queue *ptq)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
15828c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
15838c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
15848c2ecf20Sopenharmony_ci	struct perf_synth_intel_pwre raw;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
15878c2ecf20Sopenharmony_ci		return 0;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	sample.id = ptq->pt->pwre_id;
15928c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->pwre_id;
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci	raw.reserved = 0;
15958c2ecf20Sopenharmony_ci	raw.payload = cpu_to_le64(ptq->state->pwre_payload);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
15988c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
15998c2ecf20Sopenharmony_ci
16008c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
16018c2ecf20Sopenharmony_ci					    pt->pwr_events_sample_type);
16028c2ecf20Sopenharmony_ci}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_cistatic int intel_pt_synth_exstop_sample(struct intel_pt_queue *ptq)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
16078c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
16088c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
16098c2ecf20Sopenharmony_ci	struct perf_synth_intel_exstop raw;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
16128c2ecf20Sopenharmony_ci		return 0;
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci	sample.id = ptq->pt->exstop_id;
16178c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->exstop_id;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci	raw.flags = 0;
16208c2ecf20Sopenharmony_ci	raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP);
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
16238c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
16268c2ecf20Sopenharmony_ci					    pt->pwr_events_sample_type);
16278c2ecf20Sopenharmony_ci}
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_cistatic int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
16308c2ecf20Sopenharmony_ci{
16318c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
16328c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
16338c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
16348c2ecf20Sopenharmony_ci	struct perf_synth_intel_pwrx raw;
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
16378c2ecf20Sopenharmony_ci		return 0;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	intel_pt_prep_p_sample(pt, ptq, event, &sample);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	sample.id = ptq->pt->pwrx_id;
16428c2ecf20Sopenharmony_ci	sample.stream_id = ptq->pt->pwrx_id;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	raw.reserved = 0;
16458c2ecf20Sopenharmony_ci	raw.payload = cpu_to_le64(ptq->state->pwrx_payload);
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	sample.raw_size = perf_synth__raw_size(raw);
16488c2ecf20Sopenharmony_ci	sample.raw_data = perf_synth__raw_data(&raw);
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample,
16518c2ecf20Sopenharmony_ci					    pt->pwr_events_sample_type);
16528c2ecf20Sopenharmony_ci}
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci/*
16558c2ecf20Sopenharmony_ci * PEBS gp_regs array indexes plus 1 so that 0 means not present. Refer
16568c2ecf20Sopenharmony_ci * intel_pt_add_gp_regs().
16578c2ecf20Sopenharmony_ci */
16588c2ecf20Sopenharmony_cistatic const int pebs_gp_regs[] = {
16598c2ecf20Sopenharmony_ci	[PERF_REG_X86_FLAGS]	= 1,
16608c2ecf20Sopenharmony_ci	[PERF_REG_X86_IP]	= 2,
16618c2ecf20Sopenharmony_ci	[PERF_REG_X86_AX]	= 3,
16628c2ecf20Sopenharmony_ci	[PERF_REG_X86_CX]	= 4,
16638c2ecf20Sopenharmony_ci	[PERF_REG_X86_DX]	= 5,
16648c2ecf20Sopenharmony_ci	[PERF_REG_X86_BX]	= 6,
16658c2ecf20Sopenharmony_ci	[PERF_REG_X86_SP]	= 7,
16668c2ecf20Sopenharmony_ci	[PERF_REG_X86_BP]	= 8,
16678c2ecf20Sopenharmony_ci	[PERF_REG_X86_SI]	= 9,
16688c2ecf20Sopenharmony_ci	[PERF_REG_X86_DI]	= 10,
16698c2ecf20Sopenharmony_ci	[PERF_REG_X86_R8]	= 11,
16708c2ecf20Sopenharmony_ci	[PERF_REG_X86_R9]	= 12,
16718c2ecf20Sopenharmony_ci	[PERF_REG_X86_R10]	= 13,
16728c2ecf20Sopenharmony_ci	[PERF_REG_X86_R11]	= 14,
16738c2ecf20Sopenharmony_ci	[PERF_REG_X86_R12]	= 15,
16748c2ecf20Sopenharmony_ci	[PERF_REG_X86_R13]	= 16,
16758c2ecf20Sopenharmony_ci	[PERF_REG_X86_R14]	= 17,
16768c2ecf20Sopenharmony_ci	[PERF_REG_X86_R15]	= 18,
16778c2ecf20Sopenharmony_ci};
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_cistatic u64 *intel_pt_add_gp_regs(struct regs_dump *intr_regs, u64 *pos,
16808c2ecf20Sopenharmony_ci				 const struct intel_pt_blk_items *items,
16818c2ecf20Sopenharmony_ci				 u64 regs_mask)
16828c2ecf20Sopenharmony_ci{
16838c2ecf20Sopenharmony_ci	const u64 *gp_regs = items->val[INTEL_PT_GP_REGS_POS];
16848c2ecf20Sopenharmony_ci	u32 mask = items->mask[INTEL_PT_GP_REGS_POS];
16858c2ecf20Sopenharmony_ci	u32 bit;
16868c2ecf20Sopenharmony_ci	int i;
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	for (i = 0, bit = 1; i < PERF_REG_X86_64_MAX; i++, bit <<= 1) {
16898c2ecf20Sopenharmony_ci		/* Get the PEBS gp_regs array index */
16908c2ecf20Sopenharmony_ci		int n = pebs_gp_regs[i] - 1;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci		if (n < 0)
16938c2ecf20Sopenharmony_ci			continue;
16948c2ecf20Sopenharmony_ci		/*
16958c2ecf20Sopenharmony_ci		 * Add only registers that were requested (i.e. 'regs_mask') and
16968c2ecf20Sopenharmony_ci		 * that were provided (i.e. 'mask'), and update the resulting
16978c2ecf20Sopenharmony_ci		 * mask (i.e. 'intr_regs->mask') accordingly.
16988c2ecf20Sopenharmony_ci		 */
16998c2ecf20Sopenharmony_ci		if (mask & 1 << n && regs_mask & bit) {
17008c2ecf20Sopenharmony_ci			intr_regs->mask |= bit;
17018c2ecf20Sopenharmony_ci			*pos++ = gp_regs[n];
17028c2ecf20Sopenharmony_ci		}
17038c2ecf20Sopenharmony_ci	}
17048c2ecf20Sopenharmony_ci
17058c2ecf20Sopenharmony_ci	return pos;
17068c2ecf20Sopenharmony_ci}
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci#ifndef PERF_REG_X86_XMM0
17098c2ecf20Sopenharmony_ci#define PERF_REG_X86_XMM0 32
17108c2ecf20Sopenharmony_ci#endif
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_cistatic void intel_pt_add_xmm(struct regs_dump *intr_regs, u64 *pos,
17138c2ecf20Sopenharmony_ci			     const struct intel_pt_blk_items *items,
17148c2ecf20Sopenharmony_ci			     u64 regs_mask)
17158c2ecf20Sopenharmony_ci{
17168c2ecf20Sopenharmony_ci	u32 mask = items->has_xmm & (regs_mask >> PERF_REG_X86_XMM0);
17178c2ecf20Sopenharmony_ci	const u64 *xmm = items->xmm;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	/*
17208c2ecf20Sopenharmony_ci	 * If there are any XMM registers, then there should be all of them.
17218c2ecf20Sopenharmony_ci	 * Nevertheless, follow the logic to add only registers that were
17228c2ecf20Sopenharmony_ci	 * requested (i.e. 'regs_mask') and that were provided (i.e. 'mask'),
17238c2ecf20Sopenharmony_ci	 * and update the resulting mask (i.e. 'intr_regs->mask') accordingly.
17248c2ecf20Sopenharmony_ci	 */
17258c2ecf20Sopenharmony_ci	intr_regs->mask |= (u64)mask << PERF_REG_X86_XMM0;
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	for (; mask; mask >>= 1, xmm++) {
17288c2ecf20Sopenharmony_ci		if (mask & 1)
17298c2ecf20Sopenharmony_ci			*pos++ = *xmm;
17308c2ecf20Sopenharmony_ci	}
17318c2ecf20Sopenharmony_ci}
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci#define LBR_INFO_MISPRED	(1ULL << 63)
17348c2ecf20Sopenharmony_ci#define LBR_INFO_IN_TX		(1ULL << 62)
17358c2ecf20Sopenharmony_ci#define LBR_INFO_ABORT		(1ULL << 61)
17368c2ecf20Sopenharmony_ci#define LBR_INFO_CYCLES		0xffff
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci/* Refer kernel's intel_pmu_store_pebs_lbrs() */
17398c2ecf20Sopenharmony_cistatic u64 intel_pt_lbr_flags(u64 info)
17408c2ecf20Sopenharmony_ci{
17418c2ecf20Sopenharmony_ci	union {
17428c2ecf20Sopenharmony_ci		struct branch_flags flags;
17438c2ecf20Sopenharmony_ci		u64 result;
17448c2ecf20Sopenharmony_ci	} u;
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci	u.result	  = 0;
17478c2ecf20Sopenharmony_ci	u.flags.mispred	  = !!(info & LBR_INFO_MISPRED);
17488c2ecf20Sopenharmony_ci	u.flags.predicted = !(info & LBR_INFO_MISPRED);
17498c2ecf20Sopenharmony_ci	u.flags.in_tx	  = !!(info & LBR_INFO_IN_TX);
17508c2ecf20Sopenharmony_ci	u.flags.abort	  = !!(info & LBR_INFO_ABORT);
17518c2ecf20Sopenharmony_ci	u.flags.cycles	  = info & LBR_INFO_CYCLES;
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	return u.result;
17548c2ecf20Sopenharmony_ci}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_cistatic void intel_pt_add_lbrs(struct branch_stack *br_stack,
17578c2ecf20Sopenharmony_ci			      const struct intel_pt_blk_items *items)
17588c2ecf20Sopenharmony_ci{
17598c2ecf20Sopenharmony_ci	u64 *to;
17608c2ecf20Sopenharmony_ci	int i;
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	br_stack->nr = 0;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	to = &br_stack->entries[0].from;
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	for (i = INTEL_PT_LBR_0_POS; i <= INTEL_PT_LBR_2_POS; i++) {
17678c2ecf20Sopenharmony_ci		u32 mask = items->mask[i];
17688c2ecf20Sopenharmony_ci		const u64 *from = items->val[i];
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci		for (; mask; mask >>= 3, from += 3) {
17718c2ecf20Sopenharmony_ci			if ((mask & 7) == 7) {
17728c2ecf20Sopenharmony_ci				*to++ = from[0];
17738c2ecf20Sopenharmony_ci				*to++ = from[1];
17748c2ecf20Sopenharmony_ci				*to++ = intel_pt_lbr_flags(from[2]);
17758c2ecf20Sopenharmony_ci				br_stack->nr += 1;
17768c2ecf20Sopenharmony_ci			}
17778c2ecf20Sopenharmony_ci		}
17788c2ecf20Sopenharmony_ci	}
17798c2ecf20Sopenharmony_ci}
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_cistatic int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
17828c2ecf20Sopenharmony_ci{
17838c2ecf20Sopenharmony_ci	const struct intel_pt_blk_items *items = &ptq->state->items;
17848c2ecf20Sopenharmony_ci	struct perf_sample sample = { .ip = 0, };
17858c2ecf20Sopenharmony_ci	union perf_event *event = ptq->event_buf;
17868c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
17878c2ecf20Sopenharmony_ci	struct evsel *evsel = pt->pebs_evsel;
17888c2ecf20Sopenharmony_ci	u64 sample_type = evsel->core.attr.sample_type;
17898c2ecf20Sopenharmony_ci	u64 id = evsel->core.id[0];
17908c2ecf20Sopenharmony_ci	u8 cpumode;
17918c2ecf20Sopenharmony_ci	u64 regs[8 * sizeof(sample.intr_regs.mask)];
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	if (intel_pt_skip_event(pt))
17948c2ecf20Sopenharmony_ci		return 0;
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci	intel_pt_prep_a_sample(ptq, event, &sample);
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	sample.id = id;
17998c2ecf20Sopenharmony_ci	sample.stream_id = id;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	if (!evsel->core.attr.freq)
18028c2ecf20Sopenharmony_ci		sample.period = evsel->core.attr.sample_period;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	/* No support for non-zero CS base */
18058c2ecf20Sopenharmony_ci	if (items->has_ip)
18068c2ecf20Sopenharmony_ci		sample.ip = items->ip;
18078c2ecf20Sopenharmony_ci	else if (items->has_rip)
18088c2ecf20Sopenharmony_ci		sample.ip = items->rip;
18098c2ecf20Sopenharmony_ci	else
18108c2ecf20Sopenharmony_ci		sample.ip = ptq->state->from_ip;
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	/* No support for guest mode at this time */
18138c2ecf20Sopenharmony_ci	cpumode = sample.ip < ptq->pt->kernel_start ?
18148c2ecf20Sopenharmony_ci		  PERF_RECORD_MISC_USER :
18158c2ecf20Sopenharmony_ci		  PERF_RECORD_MISC_KERNEL;
18168c2ecf20Sopenharmony_ci
18178c2ecf20Sopenharmony_ci	event->sample.header.misc = cpumode | PERF_RECORD_MISC_EXACT_IP;
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	sample.cpumode = cpumode;
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_TIME) {
18228c2ecf20Sopenharmony_ci		u64 timestamp = 0;
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci		if (items->has_timestamp)
18258c2ecf20Sopenharmony_ci			timestamp = items->timestamp;
18268c2ecf20Sopenharmony_ci		else if (!pt->timeless_decoding)
18278c2ecf20Sopenharmony_ci			timestamp = ptq->timestamp;
18288c2ecf20Sopenharmony_ci		if (timestamp)
18298c2ecf20Sopenharmony_ci			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
18308c2ecf20Sopenharmony_ci	}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_CALLCHAIN &&
18338c2ecf20Sopenharmony_ci	    pt->synth_opts.callchain) {
18348c2ecf20Sopenharmony_ci		thread_stack__sample(ptq->thread, ptq->cpu, ptq->chain,
18358c2ecf20Sopenharmony_ci				     pt->synth_opts.callchain_sz, sample.ip,
18368c2ecf20Sopenharmony_ci				     pt->kernel_start);
18378c2ecf20Sopenharmony_ci		sample.callchain = ptq->chain;
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_REGS_INTR &&
18418c2ecf20Sopenharmony_ci	    (items->mask[INTEL_PT_GP_REGS_POS] ||
18428c2ecf20Sopenharmony_ci	     items->mask[INTEL_PT_XMM_POS])) {
18438c2ecf20Sopenharmony_ci		u64 regs_mask = evsel->core.attr.sample_regs_intr;
18448c2ecf20Sopenharmony_ci		u64 *pos;
18458c2ecf20Sopenharmony_ci
18468c2ecf20Sopenharmony_ci		sample.intr_regs.abi = items->is_32_bit ?
18478c2ecf20Sopenharmony_ci				       PERF_SAMPLE_REGS_ABI_32 :
18488c2ecf20Sopenharmony_ci				       PERF_SAMPLE_REGS_ABI_64;
18498c2ecf20Sopenharmony_ci		sample.intr_regs.regs = regs;
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci		pos = intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci		intel_pt_add_xmm(&sample.intr_regs, pos, items, regs_mask);
18548c2ecf20Sopenharmony_ci	}
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
18578c2ecf20Sopenharmony_ci		if (items->mask[INTEL_PT_LBR_0_POS] ||
18588c2ecf20Sopenharmony_ci		    items->mask[INTEL_PT_LBR_1_POS] ||
18598c2ecf20Sopenharmony_ci		    items->mask[INTEL_PT_LBR_2_POS]) {
18608c2ecf20Sopenharmony_ci			intel_pt_add_lbrs(ptq->last_branch, items);
18618c2ecf20Sopenharmony_ci		} else if (pt->synth_opts.last_branch) {
18628c2ecf20Sopenharmony_ci			thread_stack__br_sample(ptq->thread, ptq->cpu,
18638c2ecf20Sopenharmony_ci						ptq->last_branch,
18648c2ecf20Sopenharmony_ci						pt->br_stack_sz);
18658c2ecf20Sopenharmony_ci		} else {
18668c2ecf20Sopenharmony_ci			ptq->last_branch->nr = 0;
18678c2ecf20Sopenharmony_ci		}
18688c2ecf20Sopenharmony_ci		sample.branch_stack = ptq->last_branch;
18698c2ecf20Sopenharmony_ci	}
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_ADDR && items->has_mem_access_address)
18728c2ecf20Sopenharmony_ci		sample.addr = items->mem_access_address;
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_WEIGHT) {
18758c2ecf20Sopenharmony_ci		/*
18768c2ecf20Sopenharmony_ci		 * Refer kernel's setup_pebs_adaptive_sample_data() and
18778c2ecf20Sopenharmony_ci		 * intel_hsw_weight().
18788c2ecf20Sopenharmony_ci		 */
18798c2ecf20Sopenharmony_ci		if (items->has_mem_access_latency)
18808c2ecf20Sopenharmony_ci			sample.weight = items->mem_access_latency;
18818c2ecf20Sopenharmony_ci		if (!sample.weight && items->has_tsx_aux_info) {
18828c2ecf20Sopenharmony_ci			/* Cycles last block */
18838c2ecf20Sopenharmony_ci			sample.weight = (u32)items->tsx_aux_info;
18848c2ecf20Sopenharmony_ci		}
18858c2ecf20Sopenharmony_ci	}
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	if (sample_type & PERF_SAMPLE_TRANSACTION && items->has_tsx_aux_info) {
18888c2ecf20Sopenharmony_ci		u64 ax = items->has_rax ? items->rax : 0;
18898c2ecf20Sopenharmony_ci		/* Refer kernel's intel_hsw_transaction() */
18908c2ecf20Sopenharmony_ci		u64 txn = (u8)(items->tsx_aux_info >> 32);
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci		/* For RTM XABORTs also log the abort code from AX */
18938c2ecf20Sopenharmony_ci		if (txn & PERF_TXN_TRANSACTION && ax & 1)
18948c2ecf20Sopenharmony_ci			txn |= ((ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
18958c2ecf20Sopenharmony_ci		sample.transaction = txn;
18968c2ecf20Sopenharmony_ci	}
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci	return intel_pt_deliver_synth_event(pt, event, &sample, sample_type);
18998c2ecf20Sopenharmony_ci}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_cistatic int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,
19028c2ecf20Sopenharmony_ci				pid_t pid, pid_t tid, u64 ip, u64 timestamp)
19038c2ecf20Sopenharmony_ci{
19048c2ecf20Sopenharmony_ci	union perf_event event;
19058c2ecf20Sopenharmony_ci	char msg[MAX_AUXTRACE_ERROR_MSG];
19068c2ecf20Sopenharmony_ci	int err;
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci	if (pt->synth_opts.error_minus_flags) {
19098c2ecf20Sopenharmony_ci		if (code == INTEL_PT_ERR_OVR &&
19108c2ecf20Sopenharmony_ci		    pt->synth_opts.error_minus_flags & AUXTRACE_ERR_FLG_OVERFLOW)
19118c2ecf20Sopenharmony_ci			return 0;
19128c2ecf20Sopenharmony_ci		if (code == INTEL_PT_ERR_LOST &&
19138c2ecf20Sopenharmony_ci		    pt->synth_opts.error_minus_flags & AUXTRACE_ERR_FLG_DATA_LOST)
19148c2ecf20Sopenharmony_ci			return 0;
19158c2ecf20Sopenharmony_ci	}
19168c2ecf20Sopenharmony_ci
19178c2ecf20Sopenharmony_ci	intel_pt__strerror(code, msg, MAX_AUXTRACE_ERROR_MSG);
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci	auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE,
19208c2ecf20Sopenharmony_ci			     code, cpu, pid, tid, ip, msg, timestamp);
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	err = perf_session__deliver_synth_event(pt->session, &event, NULL);
19238c2ecf20Sopenharmony_ci	if (err)
19248c2ecf20Sopenharmony_ci		pr_err("Intel Processor Trace: failed to deliver error event, error %d\n",
19258c2ecf20Sopenharmony_ci		       err);
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	return err;
19288c2ecf20Sopenharmony_ci}
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_cistatic int intel_ptq_synth_error(struct intel_pt_queue *ptq,
19318c2ecf20Sopenharmony_ci				 const struct intel_pt_state *state)
19328c2ecf20Sopenharmony_ci{
19338c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
19348c2ecf20Sopenharmony_ci	u64 tm = ptq->timestamp;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	tm = pt->timeless_decoding ? 0 : tsc_to_perf_time(tm, &pt->tc);
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci	return intel_pt_synth_error(pt, state->err, ptq->cpu, ptq->pid,
19398c2ecf20Sopenharmony_ci				    ptq->tid, state->from_ip, tm);
19408c2ecf20Sopenharmony_ci}
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_cistatic int intel_pt_next_tid(struct intel_pt *pt, struct intel_pt_queue *ptq)
19438c2ecf20Sopenharmony_ci{
19448c2ecf20Sopenharmony_ci	struct auxtrace_queue *queue;
19458c2ecf20Sopenharmony_ci	pid_t tid = ptq->next_tid;
19468c2ecf20Sopenharmony_ci	int err;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci	if (tid == -1)
19498c2ecf20Sopenharmony_ci		return 0;
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	intel_pt_log("switch: cpu %d tid %d\n", ptq->cpu, tid);
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci	err = machine__set_current_tid(pt->machine, ptq->cpu, -1, tid);
19548c2ecf20Sopenharmony_ci
19558c2ecf20Sopenharmony_ci	queue = &pt->queues.queue_array[ptq->queue_nr];
19568c2ecf20Sopenharmony_ci	intel_pt_set_pid_tid_cpu(pt, queue);
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	ptq->next_tid = -1;
19598c2ecf20Sopenharmony_ci
19608c2ecf20Sopenharmony_ci	return err;
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_cistatic inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip)
19648c2ecf20Sopenharmony_ci{
19658c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	return ip == pt->switch_ip &&
19688c2ecf20Sopenharmony_ci	       (ptq->flags & PERF_IP_FLAG_BRANCH) &&
19698c2ecf20Sopenharmony_ci	       !(ptq->flags & (PERF_IP_FLAG_CONDITIONAL | PERF_IP_FLAG_ASYNC |
19708c2ecf20Sopenharmony_ci			       PERF_IP_FLAG_INTERRUPT | PERF_IP_FLAG_TX_ABORT));
19718c2ecf20Sopenharmony_ci}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci#define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \
19748c2ecf20Sopenharmony_ci			  INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT)
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_cistatic int intel_pt_sample(struct intel_pt_queue *ptq)
19778c2ecf20Sopenharmony_ci{
19788c2ecf20Sopenharmony_ci	const struct intel_pt_state *state = ptq->state;
19798c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
19808c2ecf20Sopenharmony_ci	int err;
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci	if (!ptq->have_sample)
19838c2ecf20Sopenharmony_ci		return 0;
19848c2ecf20Sopenharmony_ci
19858c2ecf20Sopenharmony_ci	ptq->have_sample = false;
19868c2ecf20Sopenharmony_ci
19878c2ecf20Sopenharmony_ci	ptq->ipc_insn_cnt = ptq->state->tot_insn_cnt;
19888c2ecf20Sopenharmony_ci	ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	/*
19918c2ecf20Sopenharmony_ci	 * Do PEBS first to allow for the possibility that the PEBS timestamp
19928c2ecf20Sopenharmony_ci	 * precedes the current timestamp.
19938c2ecf20Sopenharmony_ci	 */
19948c2ecf20Sopenharmony_ci	if (pt->sample_pebs && state->type & INTEL_PT_BLK_ITEMS) {
19958c2ecf20Sopenharmony_ci		err = intel_pt_synth_pebs_sample(ptq);
19968c2ecf20Sopenharmony_ci		if (err)
19978c2ecf20Sopenharmony_ci			return err;
19988c2ecf20Sopenharmony_ci	}
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci	if (pt->sample_pwr_events) {
20018c2ecf20Sopenharmony_ci		if (ptq->state->cbr != ptq->cbr_seen) {
20028c2ecf20Sopenharmony_ci			err = intel_pt_synth_cbr_sample(ptq);
20038c2ecf20Sopenharmony_ci			if (err)
20048c2ecf20Sopenharmony_ci				return err;
20058c2ecf20Sopenharmony_ci		}
20068c2ecf20Sopenharmony_ci		if (state->type & INTEL_PT_PWR_EVT) {
20078c2ecf20Sopenharmony_ci			if (state->type & INTEL_PT_MWAIT_OP) {
20088c2ecf20Sopenharmony_ci				err = intel_pt_synth_mwait_sample(ptq);
20098c2ecf20Sopenharmony_ci				if (err)
20108c2ecf20Sopenharmony_ci					return err;
20118c2ecf20Sopenharmony_ci			}
20128c2ecf20Sopenharmony_ci			if (state->type & INTEL_PT_PWR_ENTRY) {
20138c2ecf20Sopenharmony_ci				err = intel_pt_synth_pwre_sample(ptq);
20148c2ecf20Sopenharmony_ci				if (err)
20158c2ecf20Sopenharmony_ci					return err;
20168c2ecf20Sopenharmony_ci			}
20178c2ecf20Sopenharmony_ci			if (state->type & INTEL_PT_EX_STOP) {
20188c2ecf20Sopenharmony_ci				err = intel_pt_synth_exstop_sample(ptq);
20198c2ecf20Sopenharmony_ci				if (err)
20208c2ecf20Sopenharmony_ci					return err;
20218c2ecf20Sopenharmony_ci			}
20228c2ecf20Sopenharmony_ci			if (state->type & INTEL_PT_PWR_EXIT) {
20238c2ecf20Sopenharmony_ci				err = intel_pt_synth_pwrx_sample(ptq);
20248c2ecf20Sopenharmony_ci				if (err)
20258c2ecf20Sopenharmony_ci					return err;
20268c2ecf20Sopenharmony_ci			}
20278c2ecf20Sopenharmony_ci		}
20288c2ecf20Sopenharmony_ci	}
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	if (pt->sample_instructions && (state->type & INTEL_PT_INSTRUCTION)) {
20318c2ecf20Sopenharmony_ci		err = intel_pt_synth_instruction_sample(ptq);
20328c2ecf20Sopenharmony_ci		if (err)
20338c2ecf20Sopenharmony_ci			return err;
20348c2ecf20Sopenharmony_ci	}
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	if (pt->sample_transactions && (state->type & INTEL_PT_TRANSACTION)) {
20378c2ecf20Sopenharmony_ci		err = intel_pt_synth_transaction_sample(ptq);
20388c2ecf20Sopenharmony_ci		if (err)
20398c2ecf20Sopenharmony_ci			return err;
20408c2ecf20Sopenharmony_ci	}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci	if (pt->sample_ptwrites && (state->type & INTEL_PT_PTW)) {
20438c2ecf20Sopenharmony_ci		err = intel_pt_synth_ptwrite_sample(ptq);
20448c2ecf20Sopenharmony_ci		if (err)
20458c2ecf20Sopenharmony_ci			return err;
20468c2ecf20Sopenharmony_ci	}
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci	if (!(state->type & INTEL_PT_BRANCH))
20498c2ecf20Sopenharmony_ci		return 0;
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci	if (pt->use_thread_stack) {
20528c2ecf20Sopenharmony_ci		thread_stack__event(ptq->thread, ptq->cpu, ptq->flags,
20538c2ecf20Sopenharmony_ci				    state->from_ip, state->to_ip, ptq->insn_len,
20548c2ecf20Sopenharmony_ci				    state->trace_nr, pt->callstack,
20558c2ecf20Sopenharmony_ci				    pt->br_stack_sz_plus,
20568c2ecf20Sopenharmony_ci				    pt->mispred_all);
20578c2ecf20Sopenharmony_ci	} else {
20588c2ecf20Sopenharmony_ci		thread_stack__set_trace_nr(ptq->thread, ptq->cpu, state->trace_nr);
20598c2ecf20Sopenharmony_ci	}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci	if (pt->sample_branches) {
20628c2ecf20Sopenharmony_ci		err = intel_pt_synth_branch_sample(ptq);
20638c2ecf20Sopenharmony_ci		if (err)
20648c2ecf20Sopenharmony_ci			return err;
20658c2ecf20Sopenharmony_ci	}
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	if (!ptq->sync_switch)
20688c2ecf20Sopenharmony_ci		return 0;
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci	if (intel_pt_is_switch_ip(ptq, state->to_ip)) {
20718c2ecf20Sopenharmony_ci		switch (ptq->switch_state) {
20728c2ecf20Sopenharmony_ci		case INTEL_PT_SS_NOT_TRACING:
20738c2ecf20Sopenharmony_ci		case INTEL_PT_SS_UNKNOWN:
20748c2ecf20Sopenharmony_ci		case INTEL_PT_SS_EXPECTING_SWITCH_IP:
20758c2ecf20Sopenharmony_ci			err = intel_pt_next_tid(pt, ptq);
20768c2ecf20Sopenharmony_ci			if (err)
20778c2ecf20Sopenharmony_ci				return err;
20788c2ecf20Sopenharmony_ci			ptq->switch_state = INTEL_PT_SS_TRACING;
20798c2ecf20Sopenharmony_ci			break;
20808c2ecf20Sopenharmony_ci		default:
20818c2ecf20Sopenharmony_ci			ptq->switch_state = INTEL_PT_SS_EXPECTING_SWITCH_EVENT;
20828c2ecf20Sopenharmony_ci			return 1;
20838c2ecf20Sopenharmony_ci		}
20848c2ecf20Sopenharmony_ci	} else if (!state->to_ip) {
20858c2ecf20Sopenharmony_ci		ptq->switch_state = INTEL_PT_SS_NOT_TRACING;
20868c2ecf20Sopenharmony_ci	} else if (ptq->switch_state == INTEL_PT_SS_NOT_TRACING) {
20878c2ecf20Sopenharmony_ci		ptq->switch_state = INTEL_PT_SS_UNKNOWN;
20888c2ecf20Sopenharmony_ci	} else if (ptq->switch_state == INTEL_PT_SS_UNKNOWN &&
20898c2ecf20Sopenharmony_ci		   state->to_ip == pt->ptss_ip &&
20908c2ecf20Sopenharmony_ci		   (ptq->flags & PERF_IP_FLAG_CALL)) {
20918c2ecf20Sopenharmony_ci		ptq->switch_state = INTEL_PT_SS_TRACING;
20928c2ecf20Sopenharmony_ci	}
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	return 0;
20958c2ecf20Sopenharmony_ci}
20968c2ecf20Sopenharmony_ci
20978c2ecf20Sopenharmony_cistatic u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
20988c2ecf20Sopenharmony_ci{
20998c2ecf20Sopenharmony_ci	struct machine *machine = pt->machine;
21008c2ecf20Sopenharmony_ci	struct map *map;
21018c2ecf20Sopenharmony_ci	struct symbol *sym, *start;
21028c2ecf20Sopenharmony_ci	u64 ip, switch_ip = 0;
21038c2ecf20Sopenharmony_ci	const char *ptss;
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	if (ptss_ip)
21068c2ecf20Sopenharmony_ci		*ptss_ip = 0;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	map = machine__kernel_map(machine);
21098c2ecf20Sopenharmony_ci	if (!map)
21108c2ecf20Sopenharmony_ci		return 0;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci	if (map__load(map))
21138c2ecf20Sopenharmony_ci		return 0;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	start = dso__first_symbol(map->dso);
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci	for (sym = start; sym; sym = dso__next_symbol(sym)) {
21188c2ecf20Sopenharmony_ci		if (sym->binding == STB_GLOBAL &&
21198c2ecf20Sopenharmony_ci		    !strcmp(sym->name, "__switch_to")) {
21208c2ecf20Sopenharmony_ci			ip = map->unmap_ip(map, sym->start);
21218c2ecf20Sopenharmony_ci			if (ip >= map->start && ip < map->end) {
21228c2ecf20Sopenharmony_ci				switch_ip = ip;
21238c2ecf20Sopenharmony_ci				break;
21248c2ecf20Sopenharmony_ci			}
21258c2ecf20Sopenharmony_ci		}
21268c2ecf20Sopenharmony_ci	}
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	if (!switch_ip || !ptss_ip)
21298c2ecf20Sopenharmony_ci		return 0;
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	if (pt->have_sched_switch == 1)
21328c2ecf20Sopenharmony_ci		ptss = "perf_trace_sched_switch";
21338c2ecf20Sopenharmony_ci	else
21348c2ecf20Sopenharmony_ci		ptss = "__perf_event_task_sched_out";
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci	for (sym = start; sym; sym = dso__next_symbol(sym)) {
21378c2ecf20Sopenharmony_ci		if (!strcmp(sym->name, ptss)) {
21388c2ecf20Sopenharmony_ci			ip = map->unmap_ip(map, sym->start);
21398c2ecf20Sopenharmony_ci			if (ip >= map->start && ip < map->end) {
21408c2ecf20Sopenharmony_ci				*ptss_ip = ip;
21418c2ecf20Sopenharmony_ci				break;
21428c2ecf20Sopenharmony_ci			}
21438c2ecf20Sopenharmony_ci		}
21448c2ecf20Sopenharmony_ci	}
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	return switch_ip;
21478c2ecf20Sopenharmony_ci}
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_cistatic void intel_pt_enable_sync_switch(struct intel_pt *pt)
21508c2ecf20Sopenharmony_ci{
21518c2ecf20Sopenharmony_ci	unsigned int i;
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci	pt->sync_switch = true;
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	for (i = 0; i < pt->queues.nr_queues; i++) {
21568c2ecf20Sopenharmony_ci		struct auxtrace_queue *queue = &pt->queues.queue_array[i];
21578c2ecf20Sopenharmony_ci		struct intel_pt_queue *ptq = queue->priv;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci		if (ptq)
21608c2ecf20Sopenharmony_ci			ptq->sync_switch = true;
21618c2ecf20Sopenharmony_ci	}
21628c2ecf20Sopenharmony_ci}
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci/*
21658c2ecf20Sopenharmony_ci * To filter against time ranges, it is only necessary to look at the next start
21668c2ecf20Sopenharmony_ci * or end time.
21678c2ecf20Sopenharmony_ci */
21688c2ecf20Sopenharmony_cistatic bool intel_pt_next_time(struct intel_pt_queue *ptq)
21698c2ecf20Sopenharmony_ci{
21708c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci	if (ptq->sel_start) {
21738c2ecf20Sopenharmony_ci		/* Next time is an end time */
21748c2ecf20Sopenharmony_ci		ptq->sel_start = false;
21758c2ecf20Sopenharmony_ci		ptq->sel_timestamp = pt->time_ranges[ptq->sel_idx].end;
21768c2ecf20Sopenharmony_ci		return true;
21778c2ecf20Sopenharmony_ci	} else if (ptq->sel_idx + 1 < pt->range_cnt) {
21788c2ecf20Sopenharmony_ci		/* Next time is a start time */
21798c2ecf20Sopenharmony_ci		ptq->sel_start = true;
21808c2ecf20Sopenharmony_ci		ptq->sel_idx += 1;
21818c2ecf20Sopenharmony_ci		ptq->sel_timestamp = pt->time_ranges[ptq->sel_idx].start;
21828c2ecf20Sopenharmony_ci		return true;
21838c2ecf20Sopenharmony_ci	}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	/* No next time */
21868c2ecf20Sopenharmony_ci	return false;
21878c2ecf20Sopenharmony_ci}
21888c2ecf20Sopenharmony_ci
21898c2ecf20Sopenharmony_cistatic int intel_pt_time_filter(struct intel_pt_queue *ptq, u64 *ff_timestamp)
21908c2ecf20Sopenharmony_ci{
21918c2ecf20Sopenharmony_ci	int err;
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	while (1) {
21948c2ecf20Sopenharmony_ci		if (ptq->sel_start) {
21958c2ecf20Sopenharmony_ci			if (ptq->timestamp >= ptq->sel_timestamp) {
21968c2ecf20Sopenharmony_ci				/* After start time, so consider next time */
21978c2ecf20Sopenharmony_ci				intel_pt_next_time(ptq);
21988c2ecf20Sopenharmony_ci				if (!ptq->sel_timestamp) {
21998c2ecf20Sopenharmony_ci					/* No end time */
22008c2ecf20Sopenharmony_ci					return 0;
22018c2ecf20Sopenharmony_ci				}
22028c2ecf20Sopenharmony_ci				/* Check against end time */
22038c2ecf20Sopenharmony_ci				continue;
22048c2ecf20Sopenharmony_ci			}
22058c2ecf20Sopenharmony_ci			/* Before start time, so fast forward */
22068c2ecf20Sopenharmony_ci			ptq->have_sample = false;
22078c2ecf20Sopenharmony_ci			if (ptq->sel_timestamp > *ff_timestamp) {
22088c2ecf20Sopenharmony_ci				if (ptq->sync_switch) {
22098c2ecf20Sopenharmony_ci					intel_pt_next_tid(ptq->pt, ptq);
22108c2ecf20Sopenharmony_ci					ptq->switch_state = INTEL_PT_SS_UNKNOWN;
22118c2ecf20Sopenharmony_ci				}
22128c2ecf20Sopenharmony_ci				*ff_timestamp = ptq->sel_timestamp;
22138c2ecf20Sopenharmony_ci				err = intel_pt_fast_forward(ptq->decoder,
22148c2ecf20Sopenharmony_ci							    ptq->sel_timestamp);
22158c2ecf20Sopenharmony_ci				if (err)
22168c2ecf20Sopenharmony_ci					return err;
22178c2ecf20Sopenharmony_ci			}
22188c2ecf20Sopenharmony_ci			return 0;
22198c2ecf20Sopenharmony_ci		} else if (ptq->timestamp > ptq->sel_timestamp) {
22208c2ecf20Sopenharmony_ci			/* After end time, so consider next time */
22218c2ecf20Sopenharmony_ci			if (!intel_pt_next_time(ptq)) {
22228c2ecf20Sopenharmony_ci				/* No next time range, so stop decoding */
22238c2ecf20Sopenharmony_ci				ptq->have_sample = false;
22248c2ecf20Sopenharmony_ci				ptq->switch_state = INTEL_PT_SS_NOT_TRACING;
22258c2ecf20Sopenharmony_ci				return 1;
22268c2ecf20Sopenharmony_ci			}
22278c2ecf20Sopenharmony_ci			/* Check against next start time */
22288c2ecf20Sopenharmony_ci			continue;
22298c2ecf20Sopenharmony_ci		} else {
22308c2ecf20Sopenharmony_ci			/* Before end time */
22318c2ecf20Sopenharmony_ci			return 0;
22328c2ecf20Sopenharmony_ci		}
22338c2ecf20Sopenharmony_ci	}
22348c2ecf20Sopenharmony_ci}
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_cistatic int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
22378c2ecf20Sopenharmony_ci{
22388c2ecf20Sopenharmony_ci	const struct intel_pt_state *state = ptq->state;
22398c2ecf20Sopenharmony_ci	struct intel_pt *pt = ptq->pt;
22408c2ecf20Sopenharmony_ci	u64 ff_timestamp = 0;
22418c2ecf20Sopenharmony_ci	int err;
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	if (!pt->kernel_start) {
22448c2ecf20Sopenharmony_ci		pt->kernel_start = machine__kernel_start(pt->machine);
22458c2ecf20Sopenharmony_ci		if (pt->per_cpu_mmaps &&
22468c2ecf20Sopenharmony_ci		    (pt->have_sched_switch == 1 || pt->have_sched_switch == 3) &&
22478c2ecf20Sopenharmony_ci		    !pt->timeless_decoding && intel_pt_tracing_kernel(pt) &&
22488c2ecf20Sopenharmony_ci		    !pt->sampling_mode) {
22498c2ecf20Sopenharmony_ci			pt->switch_ip = intel_pt_switch_ip(pt, &pt->ptss_ip);
22508c2ecf20Sopenharmony_ci			if (pt->switch_ip) {
22518c2ecf20Sopenharmony_ci				intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n",
22528c2ecf20Sopenharmony_ci					     pt->switch_ip, pt->ptss_ip);
22538c2ecf20Sopenharmony_ci				intel_pt_enable_sync_switch(pt);
22548c2ecf20Sopenharmony_ci			}
22558c2ecf20Sopenharmony_ci		}
22568c2ecf20Sopenharmony_ci	}
22578c2ecf20Sopenharmony_ci
22588c2ecf20Sopenharmony_ci	intel_pt_log("queue %u decoding cpu %d pid %d tid %d\n",
22598c2ecf20Sopenharmony_ci		     ptq->queue_nr, ptq->cpu, ptq->pid, ptq->tid);
22608c2ecf20Sopenharmony_ci	while (1) {
22618c2ecf20Sopenharmony_ci		err = intel_pt_sample(ptq);
22628c2ecf20Sopenharmony_ci		if (err)
22638c2ecf20Sopenharmony_ci			return err;
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci		state = intel_pt_decode(ptq->decoder);
22668c2ecf20Sopenharmony_ci		if (state->err) {
22678c2ecf20Sopenharmony_ci			if (state->err == INTEL_PT_ERR_NODATA)
22688c2ecf20Sopenharmony_ci				return 1;
22698c2ecf20Sopenharmony_ci			if (ptq->sync_switch &&
22708c2ecf20Sopenharmony_ci			    state->from_ip >= pt->kernel_start) {
22718c2ecf20Sopenharmony_ci				ptq->sync_switch = false;
22728c2ecf20Sopenharmony_ci				intel_pt_next_tid(pt, ptq);
22738c2ecf20Sopenharmony_ci			}
22748c2ecf20Sopenharmony_ci			ptq->timestamp = state->est_timestamp;
22758c2ecf20Sopenharmony_ci			if (pt->synth_opts.errors) {
22768c2ecf20Sopenharmony_ci				err = intel_ptq_synth_error(ptq, state);
22778c2ecf20Sopenharmony_ci				if (err)
22788c2ecf20Sopenharmony_ci					return err;
22798c2ecf20Sopenharmony_ci			}
22808c2ecf20Sopenharmony_ci			continue;
22818c2ecf20Sopenharmony_ci		}
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci		ptq->state = state;
22848c2ecf20Sopenharmony_ci		ptq->have_sample = true;
22858c2ecf20Sopenharmony_ci		intel_pt_sample_flags(ptq);
22868c2ecf20Sopenharmony_ci
22878c2ecf20Sopenharmony_ci		/* Use estimated TSC upon return to user space */
22888c2ecf20Sopenharmony_ci		if (pt->est_tsc &&
22898c2ecf20Sopenharmony_ci		    (state->from_ip >= pt->kernel_start || !state->from_ip) &&
22908c2ecf20Sopenharmony_ci		    state->to_ip && state->to_ip < pt->kernel_start) {
22918c2ecf20Sopenharmony_ci			intel_pt_log("TSC %"PRIx64" est. TSC %"PRIx64"\n",
22928c2ecf20Sopenharmony_ci				     state->timestamp, state->est_timestamp);
22938c2ecf20Sopenharmony_ci			ptq->timestamp = state->est_timestamp;
22948c2ecf20Sopenharmony_ci		/* Use estimated TSC in unknown switch state */
22958c2ecf20Sopenharmony_ci		} else if (ptq->sync_switch &&
22968c2ecf20Sopenharmony_ci			   ptq->switch_state == INTEL_PT_SS_UNKNOWN &&
22978c2ecf20Sopenharmony_ci			   intel_pt_is_switch_ip(ptq, state->to_ip) &&
22988c2ecf20Sopenharmony_ci			   ptq->next_tid == -1) {
22998c2ecf20Sopenharmony_ci			intel_pt_log("TSC %"PRIx64" est. TSC %"PRIx64"\n",
23008c2ecf20Sopenharmony_ci				     state->timestamp, state->est_timestamp);
23018c2ecf20Sopenharmony_ci			ptq->timestamp = state->est_timestamp;
23028c2ecf20Sopenharmony_ci		} else if (state->timestamp > ptq->timestamp) {
23038c2ecf20Sopenharmony_ci			ptq->timestamp = state->timestamp;
23048c2ecf20Sopenharmony_ci		}
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci		if (ptq->sel_timestamp) {
23078c2ecf20Sopenharmony_ci			err = intel_pt_time_filter(ptq, &ff_timestamp);
23088c2ecf20Sopenharmony_ci			if (err)
23098c2ecf20Sopenharmony_ci				return err;
23108c2ecf20Sopenharmony_ci		}
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_ci		if (!pt->timeless_decoding && ptq->timestamp >= *timestamp) {
23138c2ecf20Sopenharmony_ci			*timestamp = ptq->timestamp;
23148c2ecf20Sopenharmony_ci			return 0;
23158c2ecf20Sopenharmony_ci		}
23168c2ecf20Sopenharmony_ci	}
23178c2ecf20Sopenharmony_ci	return 0;
23188c2ecf20Sopenharmony_ci}
23198c2ecf20Sopenharmony_ci
23208c2ecf20Sopenharmony_cistatic inline int intel_pt_update_queues(struct intel_pt *pt)
23218c2ecf20Sopenharmony_ci{
23228c2ecf20Sopenharmony_ci	if (pt->queues.new_data) {
23238c2ecf20Sopenharmony_ci		pt->queues.new_data = false;
23248c2ecf20Sopenharmony_ci		return intel_pt_setup_queues(pt);
23258c2ecf20Sopenharmony_ci	}
23268c2ecf20Sopenharmony_ci	return 0;
23278c2ecf20Sopenharmony_ci}
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_cistatic int intel_pt_process_queues(struct intel_pt *pt, u64 timestamp)
23308c2ecf20Sopenharmony_ci{
23318c2ecf20Sopenharmony_ci	unsigned int queue_nr;
23328c2ecf20Sopenharmony_ci	u64 ts;
23338c2ecf20Sopenharmony_ci	int ret;
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci	while (1) {
23368c2ecf20Sopenharmony_ci		struct auxtrace_queue *queue;
23378c2ecf20Sopenharmony_ci		struct intel_pt_queue *ptq;
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci		if (!pt->heap.heap_cnt)
23408c2ecf20Sopenharmony_ci			return 0;
23418c2ecf20Sopenharmony_ci
23428c2ecf20Sopenharmony_ci		if (pt->heap.heap_array[0].ordinal >= timestamp)
23438c2ecf20Sopenharmony_ci			return 0;
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci		queue_nr = pt->heap.heap_array[0].queue_nr;
23468c2ecf20Sopenharmony_ci		queue = &pt->queues.queue_array[queue_nr];
23478c2ecf20Sopenharmony_ci		ptq = queue->priv;
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci		intel_pt_log("queue %u processing 0x%" PRIx64 " to 0x%" PRIx64 "\n",
23508c2ecf20Sopenharmony_ci			     queue_nr, pt->heap.heap_array[0].ordinal,
23518c2ecf20Sopenharmony_ci			     timestamp);
23528c2ecf20Sopenharmony_ci
23538c2ecf20Sopenharmony_ci		auxtrace_heap__pop(&pt->heap);
23548c2ecf20Sopenharmony_ci
23558c2ecf20Sopenharmony_ci		if (pt->heap.heap_cnt) {
23568c2ecf20Sopenharmony_ci			ts = pt->heap.heap_array[0].ordinal + 1;
23578c2ecf20Sopenharmony_ci			if (ts > timestamp)
23588c2ecf20Sopenharmony_ci				ts = timestamp;
23598c2ecf20Sopenharmony_ci		} else {
23608c2ecf20Sopenharmony_ci			ts = timestamp;
23618c2ecf20Sopenharmony_ci		}
23628c2ecf20Sopenharmony_ci
23638c2ecf20Sopenharmony_ci		intel_pt_set_pid_tid_cpu(pt, queue);
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci		ret = intel_pt_run_decoder(ptq, &ts);
23668c2ecf20Sopenharmony_ci
23678c2ecf20Sopenharmony_ci		if (ret < 0) {
23688c2ecf20Sopenharmony_ci			auxtrace_heap__add(&pt->heap, queue_nr, ts);
23698c2ecf20Sopenharmony_ci			return ret;
23708c2ecf20Sopenharmony_ci		}
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci		if (!ret) {
23738c2ecf20Sopenharmony_ci			ret = auxtrace_heap__add(&pt->heap, queue_nr, ts);
23748c2ecf20Sopenharmony_ci			if (ret < 0)
23758c2ecf20Sopenharmony_ci				return ret;
23768c2ecf20Sopenharmony_ci		} else {
23778c2ecf20Sopenharmony_ci			ptq->on_heap = false;
23788c2ecf20Sopenharmony_ci		}
23798c2ecf20Sopenharmony_ci	}
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci	return 0;
23828c2ecf20Sopenharmony_ci}
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_cistatic int intel_pt_process_timeless_queues(struct intel_pt *pt, pid_t tid,
23858c2ecf20Sopenharmony_ci					    u64 time_)
23868c2ecf20Sopenharmony_ci{
23878c2ecf20Sopenharmony_ci	struct auxtrace_queues *queues = &pt->queues;
23888c2ecf20Sopenharmony_ci	unsigned int i;
23898c2ecf20Sopenharmony_ci	u64 ts = 0;
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	for (i = 0; i < queues->nr_queues; i++) {
23928c2ecf20Sopenharmony_ci		struct auxtrace_queue *queue = &pt->queues.queue_array[i];
23938c2ecf20Sopenharmony_ci		struct intel_pt_queue *ptq = queue->priv;
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci		if (ptq && (tid == -1 || ptq->tid == tid)) {
23968c2ecf20Sopenharmony_ci			ptq->time = time_;
23978c2ecf20Sopenharmony_ci			intel_pt_set_pid_tid_cpu(pt, queue);
23988c2ecf20Sopenharmony_ci			intel_pt_run_decoder(ptq, &ts);
23998c2ecf20Sopenharmony_ci		}
24008c2ecf20Sopenharmony_ci	}
24018c2ecf20Sopenharmony_ci	return 0;
24028c2ecf20Sopenharmony_ci}
24038c2ecf20Sopenharmony_ci
24048c2ecf20Sopenharmony_cistatic void intel_pt_sample_set_pid_tid_cpu(struct intel_pt_queue *ptq,
24058c2ecf20Sopenharmony_ci					    struct auxtrace_queue *queue,
24068c2ecf20Sopenharmony_ci					    struct perf_sample *sample)
24078c2ecf20Sopenharmony_ci{
24088c2ecf20Sopenharmony_ci	struct machine *m = ptq->pt->machine;
24098c2ecf20Sopenharmony_ci
24108c2ecf20Sopenharmony_ci	ptq->pid = sample->pid;
24118c2ecf20Sopenharmony_ci	ptq->tid = sample->tid;
24128c2ecf20Sopenharmony_ci	ptq->cpu = queue->cpu;
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	intel_pt_log("queue %u cpu %d pid %d tid %d\n",
24158c2ecf20Sopenharmony_ci		     ptq->queue_nr, ptq->cpu, ptq->pid, ptq->tid);
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	thread__zput(ptq->thread);
24188c2ecf20Sopenharmony_ci
24198c2ecf20Sopenharmony_ci	if (ptq->tid == -1)
24208c2ecf20Sopenharmony_ci		return;
24218c2ecf20Sopenharmony_ci
24228c2ecf20Sopenharmony_ci	if (ptq->pid == -1) {
24238c2ecf20Sopenharmony_ci		ptq->thread = machine__find_thread(m, -1, ptq->tid);
24248c2ecf20Sopenharmony_ci		if (ptq->thread)
24258c2ecf20Sopenharmony_ci			ptq->pid = ptq->thread->pid_;
24268c2ecf20Sopenharmony_ci		return;
24278c2ecf20Sopenharmony_ci	}
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	ptq->thread = machine__findnew_thread(m, ptq->pid, ptq->tid);
24308c2ecf20Sopenharmony_ci}
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_cistatic int intel_pt_process_timeless_sample(struct intel_pt *pt,
24338c2ecf20Sopenharmony_ci					    struct perf_sample *sample)
24348c2ecf20Sopenharmony_ci{
24358c2ecf20Sopenharmony_ci	struct auxtrace_queue *queue;
24368c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq;
24378c2ecf20Sopenharmony_ci	u64 ts = 0;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	queue = auxtrace_queues__sample_queue(&pt->queues, sample, pt->session);
24408c2ecf20Sopenharmony_ci	if (!queue)
24418c2ecf20Sopenharmony_ci		return -EINVAL;
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci	ptq = queue->priv;
24448c2ecf20Sopenharmony_ci	if (!ptq)
24458c2ecf20Sopenharmony_ci		return 0;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci	ptq->stop = false;
24488c2ecf20Sopenharmony_ci	ptq->time = sample->time;
24498c2ecf20Sopenharmony_ci	intel_pt_sample_set_pid_tid_cpu(ptq, queue, sample);
24508c2ecf20Sopenharmony_ci	intel_pt_run_decoder(ptq, &ts);
24518c2ecf20Sopenharmony_ci	return 0;
24528c2ecf20Sopenharmony_ci}
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_cistatic int intel_pt_lost(struct intel_pt *pt, struct perf_sample *sample)
24558c2ecf20Sopenharmony_ci{
24568c2ecf20Sopenharmony_ci	return intel_pt_synth_error(pt, INTEL_PT_ERR_LOST, sample->cpu,
24578c2ecf20Sopenharmony_ci				    sample->pid, sample->tid, 0, sample->time);
24588c2ecf20Sopenharmony_ci}
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_cistatic struct intel_pt_queue *intel_pt_cpu_to_ptq(struct intel_pt *pt, int cpu)
24618c2ecf20Sopenharmony_ci{
24628c2ecf20Sopenharmony_ci	unsigned i, j;
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	if (cpu < 0 || !pt->queues.nr_queues)
24658c2ecf20Sopenharmony_ci		return NULL;
24668c2ecf20Sopenharmony_ci
24678c2ecf20Sopenharmony_ci	if ((unsigned)cpu >= pt->queues.nr_queues)
24688c2ecf20Sopenharmony_ci		i = pt->queues.nr_queues - 1;
24698c2ecf20Sopenharmony_ci	else
24708c2ecf20Sopenharmony_ci		i = cpu;
24718c2ecf20Sopenharmony_ci
24728c2ecf20Sopenharmony_ci	if (pt->queues.queue_array[i].cpu == cpu)
24738c2ecf20Sopenharmony_ci		return pt->queues.queue_array[i].priv;
24748c2ecf20Sopenharmony_ci
24758c2ecf20Sopenharmony_ci	for (j = 0; i > 0; j++) {
24768c2ecf20Sopenharmony_ci		if (pt->queues.queue_array[--i].cpu == cpu)
24778c2ecf20Sopenharmony_ci			return pt->queues.queue_array[i].priv;
24788c2ecf20Sopenharmony_ci	}
24798c2ecf20Sopenharmony_ci
24808c2ecf20Sopenharmony_ci	for (; j < pt->queues.nr_queues; j++) {
24818c2ecf20Sopenharmony_ci		if (pt->queues.queue_array[j].cpu == cpu)
24828c2ecf20Sopenharmony_ci			return pt->queues.queue_array[j].priv;
24838c2ecf20Sopenharmony_ci	}
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	return NULL;
24868c2ecf20Sopenharmony_ci}
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_cistatic int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid,
24898c2ecf20Sopenharmony_ci				u64 timestamp)
24908c2ecf20Sopenharmony_ci{
24918c2ecf20Sopenharmony_ci	struct intel_pt_queue *ptq;
24928c2ecf20Sopenharmony_ci	int err;
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	if (!pt->sync_switch)
24958c2ecf20Sopenharmony_ci		return 1;
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_ci	ptq = intel_pt_cpu_to_ptq(pt, cpu);
24988c2ecf20Sopenharmony_ci	if (!ptq || !ptq->sync_switch)
24998c2ecf20Sopenharmony_ci		return 1;
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	switch (ptq->switch_state) {
25028c2ecf20Sopenharmony_ci	case INTEL_PT_SS_NOT_TRACING:
25038c2ecf20Sopenharmony_ci		break;
25048c2ecf20Sopenharmony_ci	case INTEL_PT_SS_UNKNOWN:
25058c2ecf20Sopenharmony_ci	case INTEL_PT_SS_TRACING:
25068c2ecf20Sopenharmony_ci		ptq->next_tid = tid;
25078c2ecf20Sopenharmony_ci		ptq->switch_state = INTEL_PT_SS_EXPECTING_SWITCH_IP;
25088c2ecf20Sopenharmony_ci		return 0;
25098c2ecf20Sopenharmony_ci	case INTEL_PT_SS_EXPECTING_SWITCH_EVENT:
25108c2ecf20Sopenharmony_ci		if (!ptq->on_heap) {
25118c2ecf20Sopenharmony_ci			ptq->timestamp = perf_time_to_tsc(timestamp,
25128c2ecf20Sopenharmony_ci							  &pt->tc);
25138c2ecf20Sopenharmony_ci			err = auxtrace_heap__add(&pt->heap, ptq->queue_nr,
25148c2ecf20Sopenharmony_ci						 ptq->timestamp);
25158c2ecf20Sopenharmony_ci			if (err)
25168c2ecf20Sopenharmony_ci				return err;
25178c2ecf20Sopenharmony_ci			ptq->on_heap = true;
25188c2ecf20Sopenharmony_ci		}
25198c2ecf20Sopenharmony_ci		ptq->switch_state = INTEL_PT_SS_TRACING;
25208c2ecf20Sopenharmony_ci		break;
25218c2ecf20Sopenharmony_ci	case INTEL_PT_SS_EXPECTING_SWITCH_IP:
25228c2ecf20Sopenharmony_ci		intel_pt_log("ERROR: cpu %d expecting switch ip\n", cpu);
25238c2ecf20Sopenharmony_ci		break;
25248c2ecf20Sopenharmony_ci	default:
25258c2ecf20Sopenharmony_ci		break;
25268c2ecf20Sopenharmony_ci	}
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	ptq->next_tid = -1;
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_ci	return 1;
25318c2ecf20Sopenharmony_ci}
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_cistatic int intel_pt_process_switch(struct intel_pt *pt,
25348c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
25358c2ecf20Sopenharmony_ci{
25368c2ecf20Sopenharmony_ci	struct evsel *evsel;
25378c2ecf20Sopenharmony_ci	pid_t tid;
25388c2ecf20Sopenharmony_ci	int cpu, ret;
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci	evsel = perf_evlist__id2evsel(pt->session->evlist, sample->id);
25418c2ecf20Sopenharmony_ci	if (evsel != pt->switch_evsel)
25428c2ecf20Sopenharmony_ci		return 0;
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ci	tid = evsel__intval(evsel, sample, "next_pid");
25458c2ecf20Sopenharmony_ci	cpu = sample->cpu;
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_ci	intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n",
25488c2ecf20Sopenharmony_ci		     cpu, tid, sample->time, perf_time_to_tsc(sample->time,
25498c2ecf20Sopenharmony_ci		     &pt->tc));
25508c2ecf20Sopenharmony_ci
25518c2ecf20Sopenharmony_ci	ret = intel_pt_sync_switch(pt, cpu, tid, sample->time);
25528c2ecf20Sopenharmony_ci	if (ret <= 0)
25538c2ecf20Sopenharmony_ci		return ret;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	return machine__set_current_tid(pt->machine, cpu, -1, tid);
25568c2ecf20Sopenharmony_ci}
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_cistatic int intel_pt_context_switch_in(struct intel_pt *pt,
25598c2ecf20Sopenharmony_ci				      struct perf_sample *sample)
25608c2ecf20Sopenharmony_ci{
25618c2ecf20Sopenharmony_ci	pid_t pid = sample->pid;
25628c2ecf20Sopenharmony_ci	pid_t tid = sample->tid;
25638c2ecf20Sopenharmony_ci	int cpu = sample->cpu;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	if (pt->sync_switch) {
25668c2ecf20Sopenharmony_ci		struct intel_pt_queue *ptq;
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci		ptq = intel_pt_cpu_to_ptq(pt, cpu);
25698c2ecf20Sopenharmony_ci		if (ptq && ptq->sync_switch) {
25708c2ecf20Sopenharmony_ci			ptq->next_tid = -1;
25718c2ecf20Sopenharmony_ci			switch (ptq->switch_state) {
25728c2ecf20Sopenharmony_ci			case INTEL_PT_SS_NOT_TRACING:
25738c2ecf20Sopenharmony_ci			case INTEL_PT_SS_UNKNOWN:
25748c2ecf20Sopenharmony_ci			case INTEL_PT_SS_TRACING:
25758c2ecf20Sopenharmony_ci				break;
25768c2ecf20Sopenharmony_ci			case INTEL_PT_SS_EXPECTING_SWITCH_EVENT:
25778c2ecf20Sopenharmony_ci			case INTEL_PT_SS_EXPECTING_SWITCH_IP:
25788c2ecf20Sopenharmony_ci				ptq->switch_state = INTEL_PT_SS_TRACING;
25798c2ecf20Sopenharmony_ci				break;
25808c2ecf20Sopenharmony_ci			default:
25818c2ecf20Sopenharmony_ci				break;
25828c2ecf20Sopenharmony_ci			}
25838c2ecf20Sopenharmony_ci		}
25848c2ecf20Sopenharmony_ci	}
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci	/*
25878c2ecf20Sopenharmony_ci	 * If the current tid has not been updated yet, ensure it is now that
25888c2ecf20Sopenharmony_ci	 * a "switch in" event has occurred.
25898c2ecf20Sopenharmony_ci	 */
25908c2ecf20Sopenharmony_ci	if (machine__get_current_tid(pt->machine, cpu) == tid)
25918c2ecf20Sopenharmony_ci		return 0;
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci	return machine__set_current_tid(pt->machine, cpu, pid, tid);
25948c2ecf20Sopenharmony_ci}
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_cistatic int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event,
25978c2ecf20Sopenharmony_ci				   struct perf_sample *sample)
25988c2ecf20Sopenharmony_ci{
25998c2ecf20Sopenharmony_ci	bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
26008c2ecf20Sopenharmony_ci	pid_t pid, tid;
26018c2ecf20Sopenharmony_ci	int cpu, ret;
26028c2ecf20Sopenharmony_ci
26038c2ecf20Sopenharmony_ci	cpu = sample->cpu;
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci	if (pt->have_sched_switch == 3) {
26068c2ecf20Sopenharmony_ci		if (!out)
26078c2ecf20Sopenharmony_ci			return intel_pt_context_switch_in(pt, sample);
26088c2ecf20Sopenharmony_ci		if (event->header.type != PERF_RECORD_SWITCH_CPU_WIDE) {
26098c2ecf20Sopenharmony_ci			pr_err("Expecting CPU-wide context switch event\n");
26108c2ecf20Sopenharmony_ci			return -EINVAL;
26118c2ecf20Sopenharmony_ci		}
26128c2ecf20Sopenharmony_ci		pid = event->context_switch.next_prev_pid;
26138c2ecf20Sopenharmony_ci		tid = event->context_switch.next_prev_tid;
26148c2ecf20Sopenharmony_ci	} else {
26158c2ecf20Sopenharmony_ci		if (out)
26168c2ecf20Sopenharmony_ci			return 0;
26178c2ecf20Sopenharmony_ci		pid = sample->pid;
26188c2ecf20Sopenharmony_ci		tid = sample->tid;
26198c2ecf20Sopenharmony_ci	}
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci	if (tid == -1)
26228c2ecf20Sopenharmony_ci		intel_pt_log("context_switch event has no tid\n");
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	ret = intel_pt_sync_switch(pt, cpu, tid, sample->time);
26258c2ecf20Sopenharmony_ci	if (ret <= 0)
26268c2ecf20Sopenharmony_ci		return ret;
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_ci	return machine__set_current_tid(pt->machine, cpu, pid, tid);
26298c2ecf20Sopenharmony_ci}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_cistatic int intel_pt_process_itrace_start(struct intel_pt *pt,
26328c2ecf20Sopenharmony_ci					 union perf_event *event,
26338c2ecf20Sopenharmony_ci					 struct perf_sample *sample)
26348c2ecf20Sopenharmony_ci{
26358c2ecf20Sopenharmony_ci	if (!pt->per_cpu_mmaps)
26368c2ecf20Sopenharmony_ci		return 0;
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci	intel_pt_log("itrace_start: cpu %d pid %d tid %d time %"PRIu64" tsc %#"PRIx64"\n",
26398c2ecf20Sopenharmony_ci		     sample->cpu, event->itrace_start.pid,
26408c2ecf20Sopenharmony_ci		     event->itrace_start.tid, sample->time,
26418c2ecf20Sopenharmony_ci		     perf_time_to_tsc(sample->time, &pt->tc));
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci	return machine__set_current_tid(pt->machine, sample->cpu,
26448c2ecf20Sopenharmony_ci					event->itrace_start.pid,
26458c2ecf20Sopenharmony_ci					event->itrace_start.tid);
26468c2ecf20Sopenharmony_ci}
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_cistatic int intel_pt_find_map(struct thread *thread, u8 cpumode, u64 addr,
26498c2ecf20Sopenharmony_ci			     struct addr_location *al)
26508c2ecf20Sopenharmony_ci{
26518c2ecf20Sopenharmony_ci	if (!al->map || addr < al->map->start || addr >= al->map->end) {
26528c2ecf20Sopenharmony_ci		if (!thread__find_map(thread, cpumode, addr, al))
26538c2ecf20Sopenharmony_ci			return -1;
26548c2ecf20Sopenharmony_ci	}
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	return 0;
26578c2ecf20Sopenharmony_ci}
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci/* Invalidate all instruction cache entries that overlap the text poke */
26608c2ecf20Sopenharmony_cistatic int intel_pt_text_poke(struct intel_pt *pt, union perf_event *event)
26618c2ecf20Sopenharmony_ci{
26628c2ecf20Sopenharmony_ci	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
26638c2ecf20Sopenharmony_ci	u64 addr = event->text_poke.addr + event->text_poke.new_len - 1;
26648c2ecf20Sopenharmony_ci	/* Assume text poke begins in a basic block no more than 4096 bytes */
26658c2ecf20Sopenharmony_ci	int cnt = 4096 + event->text_poke.new_len;
26668c2ecf20Sopenharmony_ci	struct thread *thread = pt->unknown_thread;
26678c2ecf20Sopenharmony_ci	struct addr_location al = { .map = NULL };
26688c2ecf20Sopenharmony_ci	struct machine *machine = pt->machine;
26698c2ecf20Sopenharmony_ci	struct intel_pt_cache_entry *e;
26708c2ecf20Sopenharmony_ci	u64 offset;
26718c2ecf20Sopenharmony_ci
26728c2ecf20Sopenharmony_ci	if (!event->text_poke.new_len)
26738c2ecf20Sopenharmony_ci		return 0;
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	for (; cnt; cnt--, addr--) {
26768c2ecf20Sopenharmony_ci		if (intel_pt_find_map(thread, cpumode, addr, &al)) {
26778c2ecf20Sopenharmony_ci			if (addr < event->text_poke.addr)
26788c2ecf20Sopenharmony_ci				return 0;
26798c2ecf20Sopenharmony_ci			continue;
26808c2ecf20Sopenharmony_ci		}
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci		if (!al.map->dso || !al.map->dso->auxtrace_cache)
26838c2ecf20Sopenharmony_ci			continue;
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci		offset = al.map->map_ip(al.map, addr);
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci		e = intel_pt_cache_lookup(al.map->dso, machine, offset);
26888c2ecf20Sopenharmony_ci		if (!e)
26898c2ecf20Sopenharmony_ci			continue;
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_ci		if (addr + e->byte_cnt + e->length <= event->text_poke.addr) {
26928c2ecf20Sopenharmony_ci			/*
26938c2ecf20Sopenharmony_ci			 * No overlap. Working backwards there cannot be another
26948c2ecf20Sopenharmony_ci			 * basic block that overlaps the text poke if there is a
26958c2ecf20Sopenharmony_ci			 * branch instruction before the text poke address.
26968c2ecf20Sopenharmony_ci			 */
26978c2ecf20Sopenharmony_ci			if (e->branch != INTEL_PT_BR_NO_BRANCH)
26988c2ecf20Sopenharmony_ci				return 0;
26998c2ecf20Sopenharmony_ci		} else {
27008c2ecf20Sopenharmony_ci			intel_pt_cache_invalidate(al.map->dso, machine, offset);
27018c2ecf20Sopenharmony_ci			intel_pt_log("Invalidated instruction cache for %s at %#"PRIx64"\n",
27028c2ecf20Sopenharmony_ci				     al.map->dso->long_name, addr);
27038c2ecf20Sopenharmony_ci		}
27048c2ecf20Sopenharmony_ci	}
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_ci	return 0;
27078c2ecf20Sopenharmony_ci}
27088c2ecf20Sopenharmony_ci
27098c2ecf20Sopenharmony_cistatic int intel_pt_process_event(struct perf_session *session,
27108c2ecf20Sopenharmony_ci				  union perf_event *event,
27118c2ecf20Sopenharmony_ci				  struct perf_sample *sample,
27128c2ecf20Sopenharmony_ci				  struct perf_tool *tool)
27138c2ecf20Sopenharmony_ci{
27148c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
27158c2ecf20Sopenharmony_ci					   auxtrace);
27168c2ecf20Sopenharmony_ci	u64 timestamp;
27178c2ecf20Sopenharmony_ci	int err = 0;
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	if (dump_trace)
27208c2ecf20Sopenharmony_ci		return 0;
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	if (!tool->ordered_events) {
27238c2ecf20Sopenharmony_ci		pr_err("Intel Processor Trace requires ordered events\n");
27248c2ecf20Sopenharmony_ci		return -EINVAL;
27258c2ecf20Sopenharmony_ci	}
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci	if (sample->time && sample->time != (u64)-1)
27288c2ecf20Sopenharmony_ci		timestamp = perf_time_to_tsc(sample->time, &pt->tc);
27298c2ecf20Sopenharmony_ci	else
27308c2ecf20Sopenharmony_ci		timestamp = 0;
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	if (timestamp || pt->timeless_decoding) {
27338c2ecf20Sopenharmony_ci		err = intel_pt_update_queues(pt);
27348c2ecf20Sopenharmony_ci		if (err)
27358c2ecf20Sopenharmony_ci			return err;
27368c2ecf20Sopenharmony_ci	}
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci	if (pt->timeless_decoding) {
27398c2ecf20Sopenharmony_ci		if (pt->sampling_mode) {
27408c2ecf20Sopenharmony_ci			if (sample->aux_sample.size)
27418c2ecf20Sopenharmony_ci				err = intel_pt_process_timeless_sample(pt,
27428c2ecf20Sopenharmony_ci								       sample);
27438c2ecf20Sopenharmony_ci		} else if (event->header.type == PERF_RECORD_EXIT) {
27448c2ecf20Sopenharmony_ci			err = intel_pt_process_timeless_queues(pt,
27458c2ecf20Sopenharmony_ci							       event->fork.tid,
27468c2ecf20Sopenharmony_ci							       sample->time);
27478c2ecf20Sopenharmony_ci		}
27488c2ecf20Sopenharmony_ci	} else if (timestamp) {
27498c2ecf20Sopenharmony_ci		err = intel_pt_process_queues(pt, timestamp);
27508c2ecf20Sopenharmony_ci	}
27518c2ecf20Sopenharmony_ci	if (err)
27528c2ecf20Sopenharmony_ci		return err;
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_SAMPLE) {
27558c2ecf20Sopenharmony_ci		if (pt->synth_opts.add_callchain && !sample->callchain)
27568c2ecf20Sopenharmony_ci			intel_pt_add_callchain(pt, sample);
27578c2ecf20Sopenharmony_ci		if (pt->synth_opts.add_last_branch && !sample->branch_stack)
27588c2ecf20Sopenharmony_ci			intel_pt_add_br_stack(pt, sample);
27598c2ecf20Sopenharmony_ci	}
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_AUX &&
27628c2ecf20Sopenharmony_ci	    (event->aux.flags & PERF_AUX_FLAG_TRUNCATED) &&
27638c2ecf20Sopenharmony_ci	    pt->synth_opts.errors) {
27648c2ecf20Sopenharmony_ci		err = intel_pt_lost(pt, sample);
27658c2ecf20Sopenharmony_ci		if (err)
27668c2ecf20Sopenharmony_ci			return err;
27678c2ecf20Sopenharmony_ci	}
27688c2ecf20Sopenharmony_ci
27698c2ecf20Sopenharmony_ci	if (pt->switch_evsel && event->header.type == PERF_RECORD_SAMPLE)
27708c2ecf20Sopenharmony_ci		err = intel_pt_process_switch(pt, sample);
27718c2ecf20Sopenharmony_ci	else if (event->header.type == PERF_RECORD_ITRACE_START)
27728c2ecf20Sopenharmony_ci		err = intel_pt_process_itrace_start(pt, event, sample);
27738c2ecf20Sopenharmony_ci	else if (event->header.type == PERF_RECORD_SWITCH ||
27748c2ecf20Sopenharmony_ci		 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)
27758c2ecf20Sopenharmony_ci		err = intel_pt_context_switch(pt, event, sample);
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_ci	if (!err && event->header.type == PERF_RECORD_TEXT_POKE)
27788c2ecf20Sopenharmony_ci		err = intel_pt_text_poke(pt, event);
27798c2ecf20Sopenharmony_ci
27808c2ecf20Sopenharmony_ci	if (intel_pt_enable_logging && intel_pt_log_events(pt, sample->time)) {
27818c2ecf20Sopenharmony_ci		intel_pt_log("event %u: cpu %d time %"PRIu64" tsc %#"PRIx64" ",
27828c2ecf20Sopenharmony_ci			     event->header.type, sample->cpu, sample->time, timestamp);
27838c2ecf20Sopenharmony_ci		intel_pt_log_event(event);
27848c2ecf20Sopenharmony_ci	}
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	return err;
27878c2ecf20Sopenharmony_ci}
27888c2ecf20Sopenharmony_ci
27898c2ecf20Sopenharmony_cistatic int intel_pt_flush(struct perf_session *session, struct perf_tool *tool)
27908c2ecf20Sopenharmony_ci{
27918c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
27928c2ecf20Sopenharmony_ci					   auxtrace);
27938c2ecf20Sopenharmony_ci	int ret;
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	if (dump_trace)
27968c2ecf20Sopenharmony_ci		return 0;
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci	if (!tool->ordered_events)
27998c2ecf20Sopenharmony_ci		return -EINVAL;
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	ret = intel_pt_update_queues(pt);
28028c2ecf20Sopenharmony_ci	if (ret < 0)
28038c2ecf20Sopenharmony_ci		return ret;
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_ci	if (pt->timeless_decoding)
28068c2ecf20Sopenharmony_ci		return intel_pt_process_timeless_queues(pt, -1,
28078c2ecf20Sopenharmony_ci							MAX_TIMESTAMP - 1);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci	return intel_pt_process_queues(pt, MAX_TIMESTAMP);
28108c2ecf20Sopenharmony_ci}
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_cistatic void intel_pt_free_events(struct perf_session *session)
28138c2ecf20Sopenharmony_ci{
28148c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
28158c2ecf20Sopenharmony_ci					   auxtrace);
28168c2ecf20Sopenharmony_ci	struct auxtrace_queues *queues = &pt->queues;
28178c2ecf20Sopenharmony_ci	unsigned int i;
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci	for (i = 0; i < queues->nr_queues; i++) {
28208c2ecf20Sopenharmony_ci		intel_pt_free_queue(queues->queue_array[i].priv);
28218c2ecf20Sopenharmony_ci		queues->queue_array[i].priv = NULL;
28228c2ecf20Sopenharmony_ci	}
28238c2ecf20Sopenharmony_ci	intel_pt_log_disable();
28248c2ecf20Sopenharmony_ci	auxtrace_queues__free(queues);
28258c2ecf20Sopenharmony_ci}
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_cistatic void intel_pt_free(struct perf_session *session)
28288c2ecf20Sopenharmony_ci{
28298c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
28308c2ecf20Sopenharmony_ci					   auxtrace);
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci	auxtrace_heap__free(&pt->heap);
28338c2ecf20Sopenharmony_ci	intel_pt_free_events(session);
28348c2ecf20Sopenharmony_ci	session->auxtrace = NULL;
28358c2ecf20Sopenharmony_ci	thread__put(pt->unknown_thread);
28368c2ecf20Sopenharmony_ci	addr_filters__exit(&pt->filts);
28378c2ecf20Sopenharmony_ci	zfree(&pt->chain);
28388c2ecf20Sopenharmony_ci	zfree(&pt->filter);
28398c2ecf20Sopenharmony_ci	zfree(&pt->time_ranges);
28408c2ecf20Sopenharmony_ci	free(pt);
28418c2ecf20Sopenharmony_ci}
28428c2ecf20Sopenharmony_ci
28438c2ecf20Sopenharmony_cistatic bool intel_pt_evsel_is_auxtrace(struct perf_session *session,
28448c2ecf20Sopenharmony_ci				       struct evsel *evsel)
28458c2ecf20Sopenharmony_ci{
28468c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
28478c2ecf20Sopenharmony_ci					   auxtrace);
28488c2ecf20Sopenharmony_ci
28498c2ecf20Sopenharmony_ci	return evsel->core.attr.type == pt->pmu_type;
28508c2ecf20Sopenharmony_ci}
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_cistatic int intel_pt_process_auxtrace_event(struct perf_session *session,
28538c2ecf20Sopenharmony_ci					   union perf_event *event,
28548c2ecf20Sopenharmony_ci					   struct perf_tool *tool __maybe_unused)
28558c2ecf20Sopenharmony_ci{
28568c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
28578c2ecf20Sopenharmony_ci					   auxtrace);
28588c2ecf20Sopenharmony_ci
28598c2ecf20Sopenharmony_ci	if (!pt->data_queued) {
28608c2ecf20Sopenharmony_ci		struct auxtrace_buffer *buffer;
28618c2ecf20Sopenharmony_ci		off_t data_offset;
28628c2ecf20Sopenharmony_ci		int fd = perf_data__fd(session->data);
28638c2ecf20Sopenharmony_ci		int err;
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci		if (perf_data__is_pipe(session->data)) {
28668c2ecf20Sopenharmony_ci			data_offset = 0;
28678c2ecf20Sopenharmony_ci		} else {
28688c2ecf20Sopenharmony_ci			data_offset = lseek(fd, 0, SEEK_CUR);
28698c2ecf20Sopenharmony_ci			if (data_offset == -1)
28708c2ecf20Sopenharmony_ci				return -errno;
28718c2ecf20Sopenharmony_ci		}
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci		err = auxtrace_queues__add_event(&pt->queues, session, event,
28748c2ecf20Sopenharmony_ci						 data_offset, &buffer);
28758c2ecf20Sopenharmony_ci		if (err)
28768c2ecf20Sopenharmony_ci			return err;
28778c2ecf20Sopenharmony_ci
28788c2ecf20Sopenharmony_ci		/* Dump here now we have copied a piped trace out of the pipe */
28798c2ecf20Sopenharmony_ci		if (dump_trace) {
28808c2ecf20Sopenharmony_ci			if (auxtrace_buffer__get_data(buffer, fd)) {
28818c2ecf20Sopenharmony_ci				intel_pt_dump_event(pt, buffer->data,
28828c2ecf20Sopenharmony_ci						    buffer->size);
28838c2ecf20Sopenharmony_ci				auxtrace_buffer__put_data(buffer);
28848c2ecf20Sopenharmony_ci			}
28858c2ecf20Sopenharmony_ci		}
28868c2ecf20Sopenharmony_ci	}
28878c2ecf20Sopenharmony_ci
28888c2ecf20Sopenharmony_ci	return 0;
28898c2ecf20Sopenharmony_ci}
28908c2ecf20Sopenharmony_ci
28918c2ecf20Sopenharmony_cistatic int intel_pt_queue_data(struct perf_session *session,
28928c2ecf20Sopenharmony_ci			       struct perf_sample *sample,
28938c2ecf20Sopenharmony_ci			       union perf_event *event, u64 data_offset)
28948c2ecf20Sopenharmony_ci{
28958c2ecf20Sopenharmony_ci	struct intel_pt *pt = container_of(session->auxtrace, struct intel_pt,
28968c2ecf20Sopenharmony_ci					   auxtrace);
28978c2ecf20Sopenharmony_ci	u64 timestamp;
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci	if (event) {
29008c2ecf20Sopenharmony_ci		return auxtrace_queues__add_event(&pt->queues, session, event,
29018c2ecf20Sopenharmony_ci						  data_offset, NULL);
29028c2ecf20Sopenharmony_ci	}
29038c2ecf20Sopenharmony_ci
29048c2ecf20Sopenharmony_ci	if (sample->time && sample->time != (u64)-1)
29058c2ecf20Sopenharmony_ci		timestamp = perf_time_to_tsc(sample->time, &pt->tc);
29068c2ecf20Sopenharmony_ci	else
29078c2ecf20Sopenharmony_ci		timestamp = 0;
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	return auxtrace_queues__add_sample(&pt->queues, session, sample,
29108c2ecf20Sopenharmony_ci					   data_offset, timestamp);
29118c2ecf20Sopenharmony_ci}
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_cistruct intel_pt_synth {
29148c2ecf20Sopenharmony_ci	struct perf_tool dummy_tool;
29158c2ecf20Sopenharmony_ci	struct perf_session *session;
29168c2ecf20Sopenharmony_ci};
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_cistatic int intel_pt_event_synth(struct perf_tool *tool,
29198c2ecf20Sopenharmony_ci				union perf_event *event,
29208c2ecf20Sopenharmony_ci				struct perf_sample *sample __maybe_unused,
29218c2ecf20Sopenharmony_ci				struct machine *machine __maybe_unused)
29228c2ecf20Sopenharmony_ci{
29238c2ecf20Sopenharmony_ci	struct intel_pt_synth *intel_pt_synth =
29248c2ecf20Sopenharmony_ci			container_of(tool, struct intel_pt_synth, dummy_tool);
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	return perf_session__deliver_synth_event(intel_pt_synth->session, event,
29278c2ecf20Sopenharmony_ci						 NULL);
29288c2ecf20Sopenharmony_ci}
29298c2ecf20Sopenharmony_ci
29308c2ecf20Sopenharmony_cistatic int intel_pt_synth_event(struct perf_session *session, const char *name,
29318c2ecf20Sopenharmony_ci				struct perf_event_attr *attr, u64 id)
29328c2ecf20Sopenharmony_ci{
29338c2ecf20Sopenharmony_ci	struct intel_pt_synth intel_pt_synth;
29348c2ecf20Sopenharmony_ci	int err;
29358c2ecf20Sopenharmony_ci
29368c2ecf20Sopenharmony_ci	pr_debug("Synthesizing '%s' event with id %" PRIu64 " sample type %#" PRIx64 "\n",
29378c2ecf20Sopenharmony_ci		 name, id, (u64)attr->sample_type);
29388c2ecf20Sopenharmony_ci
29398c2ecf20Sopenharmony_ci	memset(&intel_pt_synth, 0, sizeof(struct intel_pt_synth));
29408c2ecf20Sopenharmony_ci	intel_pt_synth.session = session;
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_ci	err = perf_event__synthesize_attr(&intel_pt_synth.dummy_tool, attr, 1,
29438c2ecf20Sopenharmony_ci					  &id, intel_pt_event_synth);
29448c2ecf20Sopenharmony_ci	if (err)
29458c2ecf20Sopenharmony_ci		pr_err("%s: failed to synthesize '%s' event type\n",
29468c2ecf20Sopenharmony_ci		       __func__, name);
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_ci	return err;
29498c2ecf20Sopenharmony_ci}
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_cistatic void intel_pt_set_event_name(struct evlist *evlist, u64 id,
29528c2ecf20Sopenharmony_ci				    const char *name)
29538c2ecf20Sopenharmony_ci{
29548c2ecf20Sopenharmony_ci	struct evsel *evsel;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
29578c2ecf20Sopenharmony_ci		if (evsel->core.id && evsel->core.id[0] == id) {
29588c2ecf20Sopenharmony_ci			if (evsel->name)
29598c2ecf20Sopenharmony_ci				zfree(&evsel->name);
29608c2ecf20Sopenharmony_ci			evsel->name = strdup(name);
29618c2ecf20Sopenharmony_ci			break;
29628c2ecf20Sopenharmony_ci		}
29638c2ecf20Sopenharmony_ci	}
29648c2ecf20Sopenharmony_ci}
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_cistatic struct evsel *intel_pt_evsel(struct intel_pt *pt,
29678c2ecf20Sopenharmony_ci					 struct evlist *evlist)
29688c2ecf20Sopenharmony_ci{
29698c2ecf20Sopenharmony_ci	struct evsel *evsel;
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
29728c2ecf20Sopenharmony_ci		if (evsel->core.attr.type == pt->pmu_type && evsel->core.ids)
29738c2ecf20Sopenharmony_ci			return evsel;
29748c2ecf20Sopenharmony_ci	}
29758c2ecf20Sopenharmony_ci
29768c2ecf20Sopenharmony_ci	return NULL;
29778c2ecf20Sopenharmony_ci}
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_cistatic int intel_pt_synth_events(struct intel_pt *pt,
29808c2ecf20Sopenharmony_ci				 struct perf_session *session)
29818c2ecf20Sopenharmony_ci{
29828c2ecf20Sopenharmony_ci	struct evlist *evlist = session->evlist;
29838c2ecf20Sopenharmony_ci	struct evsel *evsel = intel_pt_evsel(pt, evlist);
29848c2ecf20Sopenharmony_ci	struct perf_event_attr attr;
29858c2ecf20Sopenharmony_ci	u64 id;
29868c2ecf20Sopenharmony_ci	int err;
29878c2ecf20Sopenharmony_ci
29888c2ecf20Sopenharmony_ci	if (!evsel) {
29898c2ecf20Sopenharmony_ci		pr_debug("There are no selected events with Intel Processor Trace data\n");
29908c2ecf20Sopenharmony_ci		return 0;
29918c2ecf20Sopenharmony_ci	}
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_ci	memset(&attr, 0, sizeof(struct perf_event_attr));
29948c2ecf20Sopenharmony_ci	attr.size = sizeof(struct perf_event_attr);
29958c2ecf20Sopenharmony_ci	attr.type = PERF_TYPE_HARDWARE;
29968c2ecf20Sopenharmony_ci	attr.sample_type = evsel->core.attr.sample_type & PERF_SAMPLE_MASK;
29978c2ecf20Sopenharmony_ci	attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
29988c2ecf20Sopenharmony_ci			    PERF_SAMPLE_PERIOD;
29998c2ecf20Sopenharmony_ci	if (pt->timeless_decoding)
30008c2ecf20Sopenharmony_ci		attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
30018c2ecf20Sopenharmony_ci	else
30028c2ecf20Sopenharmony_ci		attr.sample_type |= PERF_SAMPLE_TIME;
30038c2ecf20Sopenharmony_ci	if (!pt->per_cpu_mmaps)
30048c2ecf20Sopenharmony_ci		attr.sample_type &= ~(u64)PERF_SAMPLE_CPU;
30058c2ecf20Sopenharmony_ci	attr.exclude_user = evsel->core.attr.exclude_user;
30068c2ecf20Sopenharmony_ci	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
30078c2ecf20Sopenharmony_ci	attr.exclude_hv = evsel->core.attr.exclude_hv;
30088c2ecf20Sopenharmony_ci	attr.exclude_host = evsel->core.attr.exclude_host;
30098c2ecf20Sopenharmony_ci	attr.exclude_guest = evsel->core.attr.exclude_guest;
30108c2ecf20Sopenharmony_ci	attr.sample_id_all = evsel->core.attr.sample_id_all;
30118c2ecf20Sopenharmony_ci	attr.read_format = evsel->core.attr.read_format;
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci	id = evsel->core.id[0] + 1000000000;
30148c2ecf20Sopenharmony_ci	if (!id)
30158c2ecf20Sopenharmony_ci		id = 1;
30168c2ecf20Sopenharmony_ci
30178c2ecf20Sopenharmony_ci	if (pt->synth_opts.branches) {
30188c2ecf20Sopenharmony_ci		attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
30198c2ecf20Sopenharmony_ci		attr.sample_period = 1;
30208c2ecf20Sopenharmony_ci		attr.sample_type |= PERF_SAMPLE_ADDR;
30218c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "branches", &attr, id);
30228c2ecf20Sopenharmony_ci		if (err)
30238c2ecf20Sopenharmony_ci			return err;
30248c2ecf20Sopenharmony_ci		pt->sample_branches = true;
30258c2ecf20Sopenharmony_ci		pt->branches_sample_type = attr.sample_type;
30268c2ecf20Sopenharmony_ci		pt->branches_id = id;
30278c2ecf20Sopenharmony_ci		id += 1;
30288c2ecf20Sopenharmony_ci		attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR;
30298c2ecf20Sopenharmony_ci	}
30308c2ecf20Sopenharmony_ci
30318c2ecf20Sopenharmony_ci	if (pt->synth_opts.callchain)
30328c2ecf20Sopenharmony_ci		attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
30338c2ecf20Sopenharmony_ci	if (pt->synth_opts.last_branch) {
30348c2ecf20Sopenharmony_ci		attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
30358c2ecf20Sopenharmony_ci		/*
30368c2ecf20Sopenharmony_ci		 * We don't use the hardware index, but the sample generation
30378c2ecf20Sopenharmony_ci		 * code uses the new format branch_stack with this field,
30388c2ecf20Sopenharmony_ci		 * so the event attributes must indicate that it's present.
30398c2ecf20Sopenharmony_ci		 */
30408c2ecf20Sopenharmony_ci		attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
30418c2ecf20Sopenharmony_ci	}
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ci	if (pt->synth_opts.instructions) {
30448c2ecf20Sopenharmony_ci		attr.config = PERF_COUNT_HW_INSTRUCTIONS;
30458c2ecf20Sopenharmony_ci		if (pt->synth_opts.period_type == PERF_ITRACE_PERIOD_NANOSECS)
30468c2ecf20Sopenharmony_ci			attr.sample_period =
30478c2ecf20Sopenharmony_ci				intel_pt_ns_to_ticks(pt, pt->synth_opts.period);
30488c2ecf20Sopenharmony_ci		else
30498c2ecf20Sopenharmony_ci			attr.sample_period = pt->synth_opts.period;
30508c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "instructions", &attr, id);
30518c2ecf20Sopenharmony_ci		if (err)
30528c2ecf20Sopenharmony_ci			return err;
30538c2ecf20Sopenharmony_ci		pt->sample_instructions = true;
30548c2ecf20Sopenharmony_ci		pt->instructions_sample_type = attr.sample_type;
30558c2ecf20Sopenharmony_ci		pt->instructions_id = id;
30568c2ecf20Sopenharmony_ci		id += 1;
30578c2ecf20Sopenharmony_ci	}
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	attr.sample_type &= ~(u64)PERF_SAMPLE_PERIOD;
30608c2ecf20Sopenharmony_ci	attr.sample_period = 1;
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	if (pt->synth_opts.transactions) {
30638c2ecf20Sopenharmony_ci		attr.config = PERF_COUNT_HW_INSTRUCTIONS;
30648c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "transactions", &attr, id);
30658c2ecf20Sopenharmony_ci		if (err)
30668c2ecf20Sopenharmony_ci			return err;
30678c2ecf20Sopenharmony_ci		pt->sample_transactions = true;
30688c2ecf20Sopenharmony_ci		pt->transactions_sample_type = attr.sample_type;
30698c2ecf20Sopenharmony_ci		pt->transactions_id = id;
30708c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "transactions");
30718c2ecf20Sopenharmony_ci		id += 1;
30728c2ecf20Sopenharmony_ci	}
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_ci	attr.type = PERF_TYPE_SYNTH;
30758c2ecf20Sopenharmony_ci	attr.sample_type |= PERF_SAMPLE_RAW;
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	if (pt->synth_opts.ptwrites) {
30788c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_PTWRITE;
30798c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "ptwrite", &attr, id);
30808c2ecf20Sopenharmony_ci		if (err)
30818c2ecf20Sopenharmony_ci			return err;
30828c2ecf20Sopenharmony_ci		pt->sample_ptwrites = true;
30838c2ecf20Sopenharmony_ci		pt->ptwrites_sample_type = attr.sample_type;
30848c2ecf20Sopenharmony_ci		pt->ptwrites_id = id;
30858c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "ptwrite");
30868c2ecf20Sopenharmony_ci		id += 1;
30878c2ecf20Sopenharmony_ci	}
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci	if (pt->synth_opts.pwr_events) {
30908c2ecf20Sopenharmony_ci		pt->sample_pwr_events = true;
30918c2ecf20Sopenharmony_ci		pt->pwr_events_sample_type = attr.sample_type;
30928c2ecf20Sopenharmony_ci
30938c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_CBR;
30948c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "cbr", &attr, id);
30958c2ecf20Sopenharmony_ci		if (err)
30968c2ecf20Sopenharmony_ci			return err;
30978c2ecf20Sopenharmony_ci		pt->cbr_id = id;
30988c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "cbr");
30998c2ecf20Sopenharmony_ci		id += 1;
31008c2ecf20Sopenharmony_ci	}
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci	if (pt->synth_opts.pwr_events && (evsel->core.attr.config & 0x10)) {
31038c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_MWAIT;
31048c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "mwait", &attr, id);
31058c2ecf20Sopenharmony_ci		if (err)
31068c2ecf20Sopenharmony_ci			return err;
31078c2ecf20Sopenharmony_ci		pt->mwait_id = id;
31088c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "mwait");
31098c2ecf20Sopenharmony_ci		id += 1;
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_PWRE;
31128c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "pwre", &attr, id);
31138c2ecf20Sopenharmony_ci		if (err)
31148c2ecf20Sopenharmony_ci			return err;
31158c2ecf20Sopenharmony_ci		pt->pwre_id = id;
31168c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "pwre");
31178c2ecf20Sopenharmony_ci		id += 1;
31188c2ecf20Sopenharmony_ci
31198c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_EXSTOP;
31208c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "exstop", &attr, id);
31218c2ecf20Sopenharmony_ci		if (err)
31228c2ecf20Sopenharmony_ci			return err;
31238c2ecf20Sopenharmony_ci		pt->exstop_id = id;
31248c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "exstop");
31258c2ecf20Sopenharmony_ci		id += 1;
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ci		attr.config = PERF_SYNTH_INTEL_PWRX;
31288c2ecf20Sopenharmony_ci		err = intel_pt_synth_event(session, "pwrx", &attr, id);
31298c2ecf20Sopenharmony_ci		if (err)
31308c2ecf20Sopenharmony_ci			return err;
31318c2ecf20Sopenharmony_ci		pt->pwrx_id = id;
31328c2ecf20Sopenharmony_ci		intel_pt_set_event_name(evlist, id, "pwrx");
31338c2ecf20Sopenharmony_ci		id += 1;
31348c2ecf20Sopenharmony_ci	}
31358c2ecf20Sopenharmony_ci
31368c2ecf20Sopenharmony_ci	return 0;
31378c2ecf20Sopenharmony_ci}
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_cistatic void intel_pt_setup_pebs_events(struct intel_pt *pt)
31408c2ecf20Sopenharmony_ci{
31418c2ecf20Sopenharmony_ci	struct evsel *evsel;
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_ci	if (!pt->synth_opts.other_events)
31448c2ecf20Sopenharmony_ci		return;
31458c2ecf20Sopenharmony_ci
31468c2ecf20Sopenharmony_ci	evlist__for_each_entry(pt->session->evlist, evsel) {
31478c2ecf20Sopenharmony_ci		if (evsel->core.attr.aux_output && evsel->core.id) {
31488c2ecf20Sopenharmony_ci			pt->sample_pebs = true;
31498c2ecf20Sopenharmony_ci			pt->pebs_evsel = evsel;
31508c2ecf20Sopenharmony_ci			return;
31518c2ecf20Sopenharmony_ci		}
31528c2ecf20Sopenharmony_ci	}
31538c2ecf20Sopenharmony_ci}
31548c2ecf20Sopenharmony_ci
31558c2ecf20Sopenharmony_cistatic struct evsel *intel_pt_find_sched_switch(struct evlist *evlist)
31568c2ecf20Sopenharmony_ci{
31578c2ecf20Sopenharmony_ci	struct evsel *evsel;
31588c2ecf20Sopenharmony_ci
31598c2ecf20Sopenharmony_ci	evlist__for_each_entry_reverse(evlist, evsel) {
31608c2ecf20Sopenharmony_ci		const char *name = evsel__name(evsel);
31618c2ecf20Sopenharmony_ci
31628c2ecf20Sopenharmony_ci		if (!strcmp(name, "sched:sched_switch"))
31638c2ecf20Sopenharmony_ci			return evsel;
31648c2ecf20Sopenharmony_ci	}
31658c2ecf20Sopenharmony_ci
31668c2ecf20Sopenharmony_ci	return NULL;
31678c2ecf20Sopenharmony_ci}
31688c2ecf20Sopenharmony_ci
31698c2ecf20Sopenharmony_cistatic bool intel_pt_find_switch(struct evlist *evlist)
31708c2ecf20Sopenharmony_ci{
31718c2ecf20Sopenharmony_ci	struct evsel *evsel;
31728c2ecf20Sopenharmony_ci
31738c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
31748c2ecf20Sopenharmony_ci		if (evsel->core.attr.context_switch)
31758c2ecf20Sopenharmony_ci			return true;
31768c2ecf20Sopenharmony_ci	}
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	return false;
31798c2ecf20Sopenharmony_ci}
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_cistatic int intel_pt_perf_config(const char *var, const char *value, void *data)
31828c2ecf20Sopenharmony_ci{
31838c2ecf20Sopenharmony_ci	struct intel_pt *pt = data;
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci	if (!strcmp(var, "intel-pt.mispred-all"))
31868c2ecf20Sopenharmony_ci		pt->mispred_all = perf_config_bool(var, value);
31878c2ecf20Sopenharmony_ci
31888c2ecf20Sopenharmony_ci	return 0;
31898c2ecf20Sopenharmony_ci}
31908c2ecf20Sopenharmony_ci
31918c2ecf20Sopenharmony_ci/* Find least TSC which converts to ns or later */
31928c2ecf20Sopenharmony_cistatic u64 intel_pt_tsc_start(u64 ns, struct intel_pt *pt)
31938c2ecf20Sopenharmony_ci{
31948c2ecf20Sopenharmony_ci	u64 tsc, tm;
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci	tsc = perf_time_to_tsc(ns, &pt->tc);
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	while (1) {
31998c2ecf20Sopenharmony_ci		tm = tsc_to_perf_time(tsc, &pt->tc);
32008c2ecf20Sopenharmony_ci		if (tm < ns)
32018c2ecf20Sopenharmony_ci			break;
32028c2ecf20Sopenharmony_ci		tsc -= 1;
32038c2ecf20Sopenharmony_ci	}
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	while (tm < ns)
32068c2ecf20Sopenharmony_ci		tm = tsc_to_perf_time(++tsc, &pt->tc);
32078c2ecf20Sopenharmony_ci
32088c2ecf20Sopenharmony_ci	return tsc;
32098c2ecf20Sopenharmony_ci}
32108c2ecf20Sopenharmony_ci
32118c2ecf20Sopenharmony_ci/* Find greatest TSC which converts to ns or earlier */
32128c2ecf20Sopenharmony_cistatic u64 intel_pt_tsc_end(u64 ns, struct intel_pt *pt)
32138c2ecf20Sopenharmony_ci{
32148c2ecf20Sopenharmony_ci	u64 tsc, tm;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	tsc = perf_time_to_tsc(ns, &pt->tc);
32178c2ecf20Sopenharmony_ci
32188c2ecf20Sopenharmony_ci	while (1) {
32198c2ecf20Sopenharmony_ci		tm = tsc_to_perf_time(tsc, &pt->tc);
32208c2ecf20Sopenharmony_ci		if (tm > ns)
32218c2ecf20Sopenharmony_ci			break;
32228c2ecf20Sopenharmony_ci		tsc += 1;
32238c2ecf20Sopenharmony_ci	}
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	while (tm > ns)
32268c2ecf20Sopenharmony_ci		tm = tsc_to_perf_time(--tsc, &pt->tc);
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	return tsc;
32298c2ecf20Sopenharmony_ci}
32308c2ecf20Sopenharmony_ci
32318c2ecf20Sopenharmony_cistatic int intel_pt_setup_time_ranges(struct intel_pt *pt,
32328c2ecf20Sopenharmony_ci				      struct itrace_synth_opts *opts)
32338c2ecf20Sopenharmony_ci{
32348c2ecf20Sopenharmony_ci	struct perf_time_interval *p = opts->ptime_range;
32358c2ecf20Sopenharmony_ci	int n = opts->range_num;
32368c2ecf20Sopenharmony_ci	int i;
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci	if (!n || !p || pt->timeless_decoding)
32398c2ecf20Sopenharmony_ci		return 0;
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	pt->time_ranges = calloc(n, sizeof(struct range));
32428c2ecf20Sopenharmony_ci	if (!pt->time_ranges)
32438c2ecf20Sopenharmony_ci		return -ENOMEM;
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_ci	pt->range_cnt = n;
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_ci	intel_pt_log("%s: %u range(s)\n", __func__, n);
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
32508c2ecf20Sopenharmony_ci		struct range *r = &pt->time_ranges[i];
32518c2ecf20Sopenharmony_ci		u64 ts = p[i].start;
32528c2ecf20Sopenharmony_ci		u64 te = p[i].end;
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci		/*
32558c2ecf20Sopenharmony_ci		 * Take care to ensure the TSC range matches the perf-time range
32568c2ecf20Sopenharmony_ci		 * when converted back to perf-time.
32578c2ecf20Sopenharmony_ci		 */
32588c2ecf20Sopenharmony_ci		r->start = ts ? intel_pt_tsc_start(ts, pt) : 0;
32598c2ecf20Sopenharmony_ci		r->end   = te ? intel_pt_tsc_end(te, pt) : 0;
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci		intel_pt_log("range %d: perf time interval: %"PRIu64" to %"PRIu64"\n",
32628c2ecf20Sopenharmony_ci			     i, ts, te);
32638c2ecf20Sopenharmony_ci		intel_pt_log("range %d: TSC time interval: %#"PRIx64" to %#"PRIx64"\n",
32648c2ecf20Sopenharmony_ci			     i, r->start, r->end);
32658c2ecf20Sopenharmony_ci	}
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_ci	return 0;
32688c2ecf20Sopenharmony_ci}
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_cistatic const char * const intel_pt_info_fmts[] = {
32718c2ecf20Sopenharmony_ci	[INTEL_PT_PMU_TYPE]		= "  PMU Type            %"PRId64"\n",
32728c2ecf20Sopenharmony_ci	[INTEL_PT_TIME_SHIFT]		= "  Time Shift          %"PRIu64"\n",
32738c2ecf20Sopenharmony_ci	[INTEL_PT_TIME_MULT]		= "  Time Muliplier      %"PRIu64"\n",
32748c2ecf20Sopenharmony_ci	[INTEL_PT_TIME_ZERO]		= "  Time Zero           %"PRIu64"\n",
32758c2ecf20Sopenharmony_ci	[INTEL_PT_CAP_USER_TIME_ZERO]	= "  Cap Time Zero       %"PRId64"\n",
32768c2ecf20Sopenharmony_ci	[INTEL_PT_TSC_BIT]		= "  TSC bit             %#"PRIx64"\n",
32778c2ecf20Sopenharmony_ci	[INTEL_PT_NORETCOMP_BIT]	= "  NoRETComp bit       %#"PRIx64"\n",
32788c2ecf20Sopenharmony_ci	[INTEL_PT_HAVE_SCHED_SWITCH]	= "  Have sched_switch   %"PRId64"\n",
32798c2ecf20Sopenharmony_ci	[INTEL_PT_SNAPSHOT_MODE]	= "  Snapshot mode       %"PRId64"\n",
32808c2ecf20Sopenharmony_ci	[INTEL_PT_PER_CPU_MMAPS]	= "  Per-cpu maps        %"PRId64"\n",
32818c2ecf20Sopenharmony_ci	[INTEL_PT_MTC_BIT]		= "  MTC bit             %#"PRIx64"\n",
32828c2ecf20Sopenharmony_ci	[INTEL_PT_MTC_FREQ_BITS]	= "  MTC freq bits       %#"PRIx64"\n",
32838c2ecf20Sopenharmony_ci	[INTEL_PT_TSC_CTC_N]		= "  TSC:CTC numerator   %"PRIu64"\n",
32848c2ecf20Sopenharmony_ci	[INTEL_PT_TSC_CTC_D]		= "  TSC:CTC denominator %"PRIu64"\n",
32858c2ecf20Sopenharmony_ci	[INTEL_PT_CYC_BIT]		= "  CYC bit             %#"PRIx64"\n",
32868c2ecf20Sopenharmony_ci	[INTEL_PT_MAX_NONTURBO_RATIO]	= "  Max non-turbo ratio %"PRIu64"\n",
32878c2ecf20Sopenharmony_ci	[INTEL_PT_FILTER_STR_LEN]	= "  Filter string len.  %"PRIu64"\n",
32888c2ecf20Sopenharmony_ci};
32898c2ecf20Sopenharmony_ci
32908c2ecf20Sopenharmony_cistatic void intel_pt_print_info(__u64 *arr, int start, int finish)
32918c2ecf20Sopenharmony_ci{
32928c2ecf20Sopenharmony_ci	int i;
32938c2ecf20Sopenharmony_ci
32948c2ecf20Sopenharmony_ci	if (!dump_trace)
32958c2ecf20Sopenharmony_ci		return;
32968c2ecf20Sopenharmony_ci
32978c2ecf20Sopenharmony_ci	for (i = start; i <= finish; i++) {
32988c2ecf20Sopenharmony_ci		const char *fmt = intel_pt_info_fmts[i];
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci		if (fmt)
33018c2ecf20Sopenharmony_ci			fprintf(stdout, fmt, arr[i]);
33028c2ecf20Sopenharmony_ci	}
33038c2ecf20Sopenharmony_ci}
33048c2ecf20Sopenharmony_ci
33058c2ecf20Sopenharmony_cistatic void intel_pt_print_info_str(const char *name, const char *str)
33068c2ecf20Sopenharmony_ci{
33078c2ecf20Sopenharmony_ci	if (!dump_trace)
33088c2ecf20Sopenharmony_ci		return;
33098c2ecf20Sopenharmony_ci
33108c2ecf20Sopenharmony_ci	fprintf(stdout, "  %-20s%s\n", name, str ? str : "");
33118c2ecf20Sopenharmony_ci}
33128c2ecf20Sopenharmony_ci
33138c2ecf20Sopenharmony_cistatic bool intel_pt_has(struct perf_record_auxtrace_info *auxtrace_info, int pos)
33148c2ecf20Sopenharmony_ci{
33158c2ecf20Sopenharmony_ci	return auxtrace_info->header.size >=
33168c2ecf20Sopenharmony_ci		sizeof(struct perf_record_auxtrace_info) + (sizeof(u64) * (pos + 1));
33178c2ecf20Sopenharmony_ci}
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ciint intel_pt_process_auxtrace_info(union perf_event *event,
33208c2ecf20Sopenharmony_ci				   struct perf_session *session)
33218c2ecf20Sopenharmony_ci{
33228c2ecf20Sopenharmony_ci	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
33238c2ecf20Sopenharmony_ci	size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
33248c2ecf20Sopenharmony_ci	struct intel_pt *pt;
33258c2ecf20Sopenharmony_ci	void *info_end;
33268c2ecf20Sopenharmony_ci	__u64 *info;
33278c2ecf20Sopenharmony_ci	int err;
33288c2ecf20Sopenharmony_ci
33298c2ecf20Sopenharmony_ci	if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
33308c2ecf20Sopenharmony_ci					min_sz)
33318c2ecf20Sopenharmony_ci		return -EINVAL;
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	pt = zalloc(sizeof(struct intel_pt));
33348c2ecf20Sopenharmony_ci	if (!pt)
33358c2ecf20Sopenharmony_ci		return -ENOMEM;
33368c2ecf20Sopenharmony_ci
33378c2ecf20Sopenharmony_ci	addr_filters__init(&pt->filts);
33388c2ecf20Sopenharmony_ci
33398c2ecf20Sopenharmony_ci	err = perf_config(intel_pt_perf_config, pt);
33408c2ecf20Sopenharmony_ci	if (err)
33418c2ecf20Sopenharmony_ci		goto err_free;
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	err = auxtrace_queues__init(&pt->queues);
33448c2ecf20Sopenharmony_ci	if (err)
33458c2ecf20Sopenharmony_ci		goto err_free;
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	intel_pt_log_set_name(INTEL_PT_PMU_NAME);
33488c2ecf20Sopenharmony_ci
33498c2ecf20Sopenharmony_ci	pt->session = session;
33508c2ecf20Sopenharmony_ci	pt->machine = &session->machines.host; /* No kvm support */
33518c2ecf20Sopenharmony_ci	pt->auxtrace_type = auxtrace_info->type;
33528c2ecf20Sopenharmony_ci	pt->pmu_type = auxtrace_info->priv[INTEL_PT_PMU_TYPE];
33538c2ecf20Sopenharmony_ci	pt->tc.time_shift = auxtrace_info->priv[INTEL_PT_TIME_SHIFT];
33548c2ecf20Sopenharmony_ci	pt->tc.time_mult = auxtrace_info->priv[INTEL_PT_TIME_MULT];
33558c2ecf20Sopenharmony_ci	pt->tc.time_zero = auxtrace_info->priv[INTEL_PT_TIME_ZERO];
33568c2ecf20Sopenharmony_ci	pt->cap_user_time_zero = auxtrace_info->priv[INTEL_PT_CAP_USER_TIME_ZERO];
33578c2ecf20Sopenharmony_ci	pt->tsc_bit = auxtrace_info->priv[INTEL_PT_TSC_BIT];
33588c2ecf20Sopenharmony_ci	pt->noretcomp_bit = auxtrace_info->priv[INTEL_PT_NORETCOMP_BIT];
33598c2ecf20Sopenharmony_ci	pt->have_sched_switch = auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH];
33608c2ecf20Sopenharmony_ci	pt->snapshot_mode = auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE];
33618c2ecf20Sopenharmony_ci	pt->per_cpu_mmaps = auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS];
33628c2ecf20Sopenharmony_ci	intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
33638c2ecf20Sopenharmony_ci			    INTEL_PT_PER_CPU_MMAPS);
33648c2ecf20Sopenharmony_ci
33658c2ecf20Sopenharmony_ci	if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
33668c2ecf20Sopenharmony_ci		pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
33678c2ecf20Sopenharmony_ci		pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
33688c2ecf20Sopenharmony_ci		pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
33698c2ecf20Sopenharmony_ci		pt->tsc_ctc_ratio_d = auxtrace_info->priv[INTEL_PT_TSC_CTC_D];
33708c2ecf20Sopenharmony_ci		pt->cyc_bit = auxtrace_info->priv[INTEL_PT_CYC_BIT];
33718c2ecf20Sopenharmony_ci		intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_MTC_BIT,
33728c2ecf20Sopenharmony_ci				    INTEL_PT_CYC_BIT);
33738c2ecf20Sopenharmony_ci	}
33748c2ecf20Sopenharmony_ci
33758c2ecf20Sopenharmony_ci	if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
33768c2ecf20Sopenharmony_ci		pt->max_non_turbo_ratio =
33778c2ecf20Sopenharmony_ci			auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
33788c2ecf20Sopenharmony_ci		intel_pt_print_info(&auxtrace_info->priv[0],
33798c2ecf20Sopenharmony_ci				    INTEL_PT_MAX_NONTURBO_RATIO,
33808c2ecf20Sopenharmony_ci				    INTEL_PT_MAX_NONTURBO_RATIO);
33818c2ecf20Sopenharmony_ci	}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
33848c2ecf20Sopenharmony_ci	info_end = (void *)info + auxtrace_info->header.size;
33858c2ecf20Sopenharmony_ci
33868c2ecf20Sopenharmony_ci	if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
33878c2ecf20Sopenharmony_ci		size_t len;
33888c2ecf20Sopenharmony_ci
33898c2ecf20Sopenharmony_ci		len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
33908c2ecf20Sopenharmony_ci		intel_pt_print_info(&auxtrace_info->priv[0],
33918c2ecf20Sopenharmony_ci				    INTEL_PT_FILTER_STR_LEN,
33928c2ecf20Sopenharmony_ci				    INTEL_PT_FILTER_STR_LEN);
33938c2ecf20Sopenharmony_ci		if (len) {
33948c2ecf20Sopenharmony_ci			const char *filter = (const char *)info;
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci			len = roundup(len + 1, 8);
33978c2ecf20Sopenharmony_ci			info += len >> 3;
33988c2ecf20Sopenharmony_ci			if ((void *)info > info_end) {
33998c2ecf20Sopenharmony_ci				pr_err("%s: bad filter string length\n", __func__);
34008c2ecf20Sopenharmony_ci				err = -EINVAL;
34018c2ecf20Sopenharmony_ci				goto err_free_queues;
34028c2ecf20Sopenharmony_ci			}
34038c2ecf20Sopenharmony_ci			pt->filter = memdup(filter, len);
34048c2ecf20Sopenharmony_ci			if (!pt->filter) {
34058c2ecf20Sopenharmony_ci				err = -ENOMEM;
34068c2ecf20Sopenharmony_ci				goto err_free_queues;
34078c2ecf20Sopenharmony_ci			}
34088c2ecf20Sopenharmony_ci			if (session->header.needs_swap)
34098c2ecf20Sopenharmony_ci				mem_bswap_64(pt->filter, len);
34108c2ecf20Sopenharmony_ci			if (pt->filter[len - 1]) {
34118c2ecf20Sopenharmony_ci				pr_err("%s: filter string not null terminated\n", __func__);
34128c2ecf20Sopenharmony_ci				err = -EINVAL;
34138c2ecf20Sopenharmony_ci				goto err_free_queues;
34148c2ecf20Sopenharmony_ci			}
34158c2ecf20Sopenharmony_ci			err = addr_filters__parse_bare_filter(&pt->filts,
34168c2ecf20Sopenharmony_ci							      filter);
34178c2ecf20Sopenharmony_ci			if (err)
34188c2ecf20Sopenharmony_ci				goto err_free_queues;
34198c2ecf20Sopenharmony_ci		}
34208c2ecf20Sopenharmony_ci		intel_pt_print_info_str("Filter string", pt->filter);
34218c2ecf20Sopenharmony_ci	}
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci	pt->timeless_decoding = intel_pt_timeless_decoding(pt);
34248c2ecf20Sopenharmony_ci	if (pt->timeless_decoding && !pt->tc.time_mult)
34258c2ecf20Sopenharmony_ci		pt->tc.time_mult = 1;
34268c2ecf20Sopenharmony_ci	pt->have_tsc = intel_pt_have_tsc(pt);
34278c2ecf20Sopenharmony_ci	pt->sampling_mode = intel_pt_sampling_mode(pt);
34288c2ecf20Sopenharmony_ci	pt->est_tsc = !pt->timeless_decoding;
34298c2ecf20Sopenharmony_ci
34308c2ecf20Sopenharmony_ci	pt->unknown_thread = thread__new(999999999, 999999999);
34318c2ecf20Sopenharmony_ci	if (!pt->unknown_thread) {
34328c2ecf20Sopenharmony_ci		err = -ENOMEM;
34338c2ecf20Sopenharmony_ci		goto err_free_queues;
34348c2ecf20Sopenharmony_ci	}
34358c2ecf20Sopenharmony_ci
34368c2ecf20Sopenharmony_ci	/*
34378c2ecf20Sopenharmony_ci	 * Since this thread will not be kept in any rbtree not in a
34388c2ecf20Sopenharmony_ci	 * list, initialize its list node so that at thread__put() the
34398c2ecf20Sopenharmony_ci	 * current thread lifetime assuption is kept and we don't segfault
34408c2ecf20Sopenharmony_ci	 * at list_del_init().
34418c2ecf20Sopenharmony_ci	 */
34428c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&pt->unknown_thread->node);
34438c2ecf20Sopenharmony_ci
34448c2ecf20Sopenharmony_ci	err = thread__set_comm(pt->unknown_thread, "unknown", 0);
34458c2ecf20Sopenharmony_ci	if (err)
34468c2ecf20Sopenharmony_ci		goto err_delete_thread;
34478c2ecf20Sopenharmony_ci	if (thread__init_maps(pt->unknown_thread, pt->machine)) {
34488c2ecf20Sopenharmony_ci		err = -ENOMEM;
34498c2ecf20Sopenharmony_ci		goto err_delete_thread;
34508c2ecf20Sopenharmony_ci	}
34518c2ecf20Sopenharmony_ci
34528c2ecf20Sopenharmony_ci	pt->auxtrace.process_event = intel_pt_process_event;
34538c2ecf20Sopenharmony_ci	pt->auxtrace.process_auxtrace_event = intel_pt_process_auxtrace_event;
34548c2ecf20Sopenharmony_ci	pt->auxtrace.queue_data = intel_pt_queue_data;
34558c2ecf20Sopenharmony_ci	pt->auxtrace.dump_auxtrace_sample = intel_pt_dump_sample;
34568c2ecf20Sopenharmony_ci	pt->auxtrace.flush_events = intel_pt_flush;
34578c2ecf20Sopenharmony_ci	pt->auxtrace.free_events = intel_pt_free_events;
34588c2ecf20Sopenharmony_ci	pt->auxtrace.free = intel_pt_free;
34598c2ecf20Sopenharmony_ci	pt->auxtrace.evsel_is_auxtrace = intel_pt_evsel_is_auxtrace;
34608c2ecf20Sopenharmony_ci	session->auxtrace = &pt->auxtrace;
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_ci	if (dump_trace)
34638c2ecf20Sopenharmony_ci		return 0;
34648c2ecf20Sopenharmony_ci
34658c2ecf20Sopenharmony_ci	if (pt->have_sched_switch == 1) {
34668c2ecf20Sopenharmony_ci		pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
34678c2ecf20Sopenharmony_ci		if (!pt->switch_evsel) {
34688c2ecf20Sopenharmony_ci			pr_err("%s: missing sched_switch event\n", __func__);
34698c2ecf20Sopenharmony_ci			err = -EINVAL;
34708c2ecf20Sopenharmony_ci			goto err_delete_thread;
34718c2ecf20Sopenharmony_ci		}
34728c2ecf20Sopenharmony_ci	} else if (pt->have_sched_switch == 2 &&
34738c2ecf20Sopenharmony_ci		   !intel_pt_find_switch(session->evlist)) {
34748c2ecf20Sopenharmony_ci		pr_err("%s: missing context_switch attribute flag\n", __func__);
34758c2ecf20Sopenharmony_ci		err = -EINVAL;
34768c2ecf20Sopenharmony_ci		goto err_delete_thread;
34778c2ecf20Sopenharmony_ci	}
34788c2ecf20Sopenharmony_ci
34798c2ecf20Sopenharmony_ci	if (session->itrace_synth_opts->set) {
34808c2ecf20Sopenharmony_ci		pt->synth_opts = *session->itrace_synth_opts;
34818c2ecf20Sopenharmony_ci	} else {
34828c2ecf20Sopenharmony_ci		itrace_synth_opts__set_default(&pt->synth_opts,
34838c2ecf20Sopenharmony_ci				session->itrace_synth_opts->default_no_sample);
34848c2ecf20Sopenharmony_ci		if (!session->itrace_synth_opts->default_no_sample &&
34858c2ecf20Sopenharmony_ci		    !session->itrace_synth_opts->inject) {
34868c2ecf20Sopenharmony_ci			pt->synth_opts.branches = false;
34878c2ecf20Sopenharmony_ci			pt->synth_opts.callchain = true;
34888c2ecf20Sopenharmony_ci			pt->synth_opts.add_callchain = true;
34898c2ecf20Sopenharmony_ci		}
34908c2ecf20Sopenharmony_ci		pt->synth_opts.thread_stack =
34918c2ecf20Sopenharmony_ci				session->itrace_synth_opts->thread_stack;
34928c2ecf20Sopenharmony_ci	}
34938c2ecf20Sopenharmony_ci
34948c2ecf20Sopenharmony_ci	if (pt->synth_opts.log)
34958c2ecf20Sopenharmony_ci		intel_pt_log_enable();
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci	/* Maximum non-turbo ratio is TSC freq / 100 MHz */
34988c2ecf20Sopenharmony_ci	if (pt->tc.time_mult) {
34998c2ecf20Sopenharmony_ci		u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci		if (!pt->max_non_turbo_ratio)
35028c2ecf20Sopenharmony_ci			pt->max_non_turbo_ratio =
35038c2ecf20Sopenharmony_ci					(tsc_freq + 50000000) / 100000000;
35048c2ecf20Sopenharmony_ci		intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
35058c2ecf20Sopenharmony_ci		intel_pt_log("Maximum non-turbo ratio %u\n",
35068c2ecf20Sopenharmony_ci			     pt->max_non_turbo_ratio);
35078c2ecf20Sopenharmony_ci		pt->cbr2khz = tsc_freq / pt->max_non_turbo_ratio / 1000;
35088c2ecf20Sopenharmony_ci	}
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_ci	err = intel_pt_setup_time_ranges(pt, session->itrace_synth_opts);
35118c2ecf20Sopenharmony_ci	if (err)
35128c2ecf20Sopenharmony_ci		goto err_delete_thread;
35138c2ecf20Sopenharmony_ci
35148c2ecf20Sopenharmony_ci	if (pt->synth_opts.calls)
35158c2ecf20Sopenharmony_ci		pt->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
35168c2ecf20Sopenharmony_ci				       PERF_IP_FLAG_TRACE_END;
35178c2ecf20Sopenharmony_ci	if (pt->synth_opts.returns)
35188c2ecf20Sopenharmony_ci		pt->branches_filter |= PERF_IP_FLAG_RETURN |
35198c2ecf20Sopenharmony_ci				       PERF_IP_FLAG_TRACE_BEGIN;
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	if ((pt->synth_opts.callchain || pt->synth_opts.add_callchain) &&
35228c2ecf20Sopenharmony_ci	    !symbol_conf.use_callchain) {
35238c2ecf20Sopenharmony_ci		symbol_conf.use_callchain = true;
35248c2ecf20Sopenharmony_ci		if (callchain_register_param(&callchain_param) < 0) {
35258c2ecf20Sopenharmony_ci			symbol_conf.use_callchain = false;
35268c2ecf20Sopenharmony_ci			pt->synth_opts.callchain = false;
35278c2ecf20Sopenharmony_ci			pt->synth_opts.add_callchain = false;
35288c2ecf20Sopenharmony_ci		}
35298c2ecf20Sopenharmony_ci	}
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci	if (pt->synth_opts.add_callchain) {
35328c2ecf20Sopenharmony_ci		err = intel_pt_callchain_init(pt);
35338c2ecf20Sopenharmony_ci		if (err)
35348c2ecf20Sopenharmony_ci			goto err_delete_thread;
35358c2ecf20Sopenharmony_ci	}
35368c2ecf20Sopenharmony_ci
35378c2ecf20Sopenharmony_ci	if (pt->synth_opts.last_branch || pt->synth_opts.add_last_branch) {
35388c2ecf20Sopenharmony_ci		pt->br_stack_sz = pt->synth_opts.last_branch_sz;
35398c2ecf20Sopenharmony_ci		pt->br_stack_sz_plus = pt->br_stack_sz;
35408c2ecf20Sopenharmony_ci	}
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_ci	if (pt->synth_opts.add_last_branch) {
35438c2ecf20Sopenharmony_ci		err = intel_pt_br_stack_init(pt);
35448c2ecf20Sopenharmony_ci		if (err)
35458c2ecf20Sopenharmony_ci			goto err_delete_thread;
35468c2ecf20Sopenharmony_ci		/*
35478c2ecf20Sopenharmony_ci		 * Additional branch stack size to cater for tracing from the
35488c2ecf20Sopenharmony_ci		 * actual sample ip to where the sample time is recorded.
35498c2ecf20Sopenharmony_ci		 * Measured at about 200 branches, but generously set to 1024.
35508c2ecf20Sopenharmony_ci		 * If kernel space is not being traced, then add just 1 for the
35518c2ecf20Sopenharmony_ci		 * branch to kernel space.
35528c2ecf20Sopenharmony_ci		 */
35538c2ecf20Sopenharmony_ci		if (intel_pt_tracing_kernel(pt))
35548c2ecf20Sopenharmony_ci			pt->br_stack_sz_plus += 1024;
35558c2ecf20Sopenharmony_ci		else
35568c2ecf20Sopenharmony_ci			pt->br_stack_sz_plus += 1;
35578c2ecf20Sopenharmony_ci	}
35588c2ecf20Sopenharmony_ci
35598c2ecf20Sopenharmony_ci	pt->use_thread_stack = pt->synth_opts.callchain ||
35608c2ecf20Sopenharmony_ci			       pt->synth_opts.add_callchain ||
35618c2ecf20Sopenharmony_ci			       pt->synth_opts.thread_stack ||
35628c2ecf20Sopenharmony_ci			       pt->synth_opts.last_branch ||
35638c2ecf20Sopenharmony_ci			       pt->synth_opts.add_last_branch;
35648c2ecf20Sopenharmony_ci
35658c2ecf20Sopenharmony_ci	pt->callstack = pt->synth_opts.callchain ||
35668c2ecf20Sopenharmony_ci			pt->synth_opts.add_callchain ||
35678c2ecf20Sopenharmony_ci			pt->synth_opts.thread_stack;
35688c2ecf20Sopenharmony_ci
35698c2ecf20Sopenharmony_ci	err = intel_pt_synth_events(pt, session);
35708c2ecf20Sopenharmony_ci	if (err)
35718c2ecf20Sopenharmony_ci		goto err_delete_thread;
35728c2ecf20Sopenharmony_ci
35738c2ecf20Sopenharmony_ci	intel_pt_setup_pebs_events(pt);
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_ci	if (pt->sampling_mode || list_empty(&session->auxtrace_index))
35768c2ecf20Sopenharmony_ci		err = auxtrace_queue_data(session, true, true);
35778c2ecf20Sopenharmony_ci	else
35788c2ecf20Sopenharmony_ci		err = auxtrace_queues__process_index(&pt->queues, session);
35798c2ecf20Sopenharmony_ci	if (err)
35808c2ecf20Sopenharmony_ci		goto err_delete_thread;
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	if (pt->queues.populated)
35838c2ecf20Sopenharmony_ci		pt->data_queued = true;
35848c2ecf20Sopenharmony_ci
35858c2ecf20Sopenharmony_ci	if (pt->timeless_decoding)
35868c2ecf20Sopenharmony_ci		pr_debug2("Intel PT decoding without timestamps\n");
35878c2ecf20Sopenharmony_ci
35888c2ecf20Sopenharmony_ci	return 0;
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_cierr_delete_thread:
35918c2ecf20Sopenharmony_ci	zfree(&pt->chain);
35928c2ecf20Sopenharmony_ci	thread__zput(pt->unknown_thread);
35938c2ecf20Sopenharmony_cierr_free_queues:
35948c2ecf20Sopenharmony_ci	intel_pt_log_disable();
35958c2ecf20Sopenharmony_ci	auxtrace_queues__free(&pt->queues);
35968c2ecf20Sopenharmony_ci	session->auxtrace = NULL;
35978c2ecf20Sopenharmony_cierr_free:
35988c2ecf20Sopenharmony_ci	addr_filters__exit(&pt->filts);
35998c2ecf20Sopenharmony_ci	zfree(&pt->filter);
36008c2ecf20Sopenharmony_ci	zfree(&pt->time_ranges);
36018c2ecf20Sopenharmony_ci	free(pt);
36028c2ecf20Sopenharmony_ci	return err;
36038c2ecf20Sopenharmony_ci}
3604