Fuchsia-local, checked in copy of intel-pt.h.

Change-Id: Ieb930f70ac3aea332a7a44b69054c514d68b4f6d
diff --git a/libipt/include/intel-pt.h b/libipt/include/intel-pt.h
new file mode 100644
index 0000000..846fa6d
--- /dev/null
+++ b/libipt/include/intel-pt.h
@@ -0,0 +1,2451 @@
+/*
+ * Copyright (c) 2013-2017, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INTEL_PT_H
+#define INTEL_PT_H
+
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Intel(R) Processor Trace (Intel PT) decoder library.
+ *
+ * This file is logically structured into the following sections:
+ *
+ * - Version
+ * - Opcodes
+ * - Errors
+ * - Configuration
+ * - Packet encoder / decoder
+ * - Query decoder
+ * - Traced image
+ * - Instruction flow decoder
+ * - Block decoder
+ */
+
+
+
+struct pt_encoder;
+struct pt_packet_decoder;
+struct pt_query_decoder;
+struct pt_insn_decoder;
+struct pt_block_decoder;
+
+
+
+/* A macro to mark functions as exported. */
+#ifndef pt_export
+#  if defined(__GNUC__)
+#    define pt_export __attribute__((visibility("default")))
+#  elif defined(_MSC_VER)
+#    define pt_export __declspec(dllimport)
+#  else
+#    error "unknown compiler"
+#  endif
+#endif
+
+
+
+/* Version. */
+
+
+/** The header version. */
+#define LIBIPT_VERSION_MAJOR 1
+#define LIBIPT_VERSION_MINOR 6
+
+#define LIBIPT_VERSION ((LIBIPT_VERSION_MAJOR << 8) + LIBIPT_VERSION_MINOR)
+
+
+/** The library version. */
+struct pt_version {
+	/** Major version number. */
+	uint8_t major;
+
+	/** Minor version number. */
+	uint8_t minor;
+
+	/** Reserved bits. */
+	uint16_t reserved;
+
+	/** Build number. */
+	uint32_t build;
+
+	/** Version extension. */
+	const char *ext;
+};
+
+
+/** Return the library version. */
+extern pt_export struct pt_version pt_library_version();
+
+
+
+/* Opcodes. */
+
+
+
+/** A one byte opcode. */
+enum pt_opcode {
+	pt_opc_pad		= 0x00,
+	pt_opc_ext		= 0x02,
+	pt_opc_psb		= pt_opc_ext,
+	pt_opc_tip		= 0x0d,
+	pt_opc_tnt_8		= 0x00,
+	pt_opc_tip_pge		= 0x11,
+	pt_opc_tip_pgd		= 0x01,
+	pt_opc_fup		= 0x1d,
+	pt_opc_mode		= 0x99,
+	pt_opc_tsc		= 0x19,
+	pt_opc_mtc		= 0x59,
+	pt_opc_cyc		= 0x03,
+
+	/* A free opcode to trigger a decode fault. */
+	pt_opc_bad		= 0xd9
+};
+
+/** A one byte extension code for ext opcodes. */
+enum pt_ext_code {
+	pt_ext_psb		= 0x82,
+	pt_ext_tnt_64		= 0xa3,
+	pt_ext_pip		= 0x43,
+	pt_ext_ovf		= 0xf3,
+	pt_ext_psbend		= 0x23,
+	pt_ext_cbr		= 0x03,
+	pt_ext_tma		= 0x73,
+	pt_ext_stop		= 0x83,
+	pt_ext_vmcs		= 0xc8,
+	pt_ext_ext2		= 0xc3,
+
+	pt_ext_bad		= 0x04
+};
+
+/** A one byte extension 2 code for ext2 extension opcodes. */
+enum pt_ext2_code {
+	pt_ext2_mnt		= 0x88,
+
+	pt_ext2_bad		= 0x00
+};
+
+/** A one byte opcode mask. */
+enum pt_opcode_mask {
+	pt_opm_tip		= 0x1f,
+	pt_opm_tnt_8		= 0x01,
+	pt_opm_tnt_8_shr	= 1,
+	pt_opm_fup		= pt_opm_tip,
+
+	/* The bit mask for the compression bits in the opcode. */
+	pt_opm_ipc		= 0xe0,
+
+	/* The shift right value for ipc bits. */
+	pt_opm_ipc_shr		= 5,
+
+	/* The bit mask for the compression bits after shifting. */
+	pt_opm_ipc_shr_mask	= 0x7,
+
+	/* Shift counts and masks for decoding the cyc packet. */
+	pt_opm_cyc              = 0x03,
+	pt_opm_cyc_ext          = 0x04,
+	pt_opm_cyc_bits         = 0xf8,
+	pt_opm_cyc_shr          = 3,
+	pt_opm_cycx_ext         = 0x01,
+	pt_opm_cycx_shr         = 1
+};
+
+/** The size of the various opcodes in bytes. */
+enum pt_opcode_size {
+	pt_opcs_pad		= 1,
+	pt_opcs_tip		= 1,
+	pt_opcs_tip_pge		= 1,
+	pt_opcs_tip_pgd		= 1,
+	pt_opcs_fup		= 1,
+	pt_opcs_tnt_8		= 1,
+	pt_opcs_mode		= 1,
+	pt_opcs_tsc		= 1,
+	pt_opcs_mtc		= 1,
+	pt_opcs_cyc		= 1,
+	pt_opcs_psb		= 2,
+	pt_opcs_psbend		= 2,
+	pt_opcs_ovf		= 2,
+	pt_opcs_pip		= 2,
+	pt_opcs_tnt_64		= 2,
+	pt_opcs_cbr		= 2,
+	pt_opcs_tma		= 2,
+	pt_opcs_stop		= 2,
+	pt_opcs_vmcs		= 2,
+	pt_opcs_mnt		= 3
+};
+
+/** The psb magic payload.
+ *
+ * The payload is a repeating 2-byte pattern.
+ */
+enum pt_psb_pattern {
+	/* The high and low bytes in the pattern. */
+	pt_psb_hi		= pt_opc_psb,
+	pt_psb_lo		= pt_ext_psb,
+
+	/* Various combinations of the above parts. */
+	pt_psb_lohi		= pt_psb_lo | pt_psb_hi << 8,
+	pt_psb_hilo		= pt_psb_hi | pt_psb_lo << 8,
+
+	/* The repeat count of the payload, not including opc and ext. */
+	pt_psb_repeat_count	= 7,
+
+	/* The size of the repeated pattern in bytes. */
+	pt_psb_repeat_size	= 2
+};
+
+/** An execution mode. */
+enum pt_exec_mode {
+	ptem_unknown,
+	ptem_16bit,
+	ptem_32bit,
+	ptem_64bit
+};
+
+/** The payload details. */
+enum pt_payload {
+	/* The shift counts for post-processing the PIP payload. */
+	pt_pl_pip_shr		= 1,
+	pt_pl_pip_shl		= 5,
+
+	/* The size of a PIP payload in bytes. */
+	pt_pl_pip_size		= 6,
+
+	/* The non-root bit in the first byte of the PIP payload. */
+	pt_pl_pip_nr            = 0x01,
+
+	/* The size of a 8bit TNT packet's payload in bits. */
+	pt_pl_tnt_8_bits	= 8 - pt_opm_tnt_8_shr,
+
+	/* The size of a 64bit TNT packet's payload in bytes. */
+	pt_pl_tnt_64_size	= 6,
+
+	/* The size of a 64bit TNT packet's payload in bits. */
+	pt_pl_tnt_64_bits	= 48,
+
+	/* The size of a TSC packet's payload in bytes and in bits. */
+	pt_pl_tsc_size		= 7,
+	pt_pl_tsc_bit_size	= pt_pl_tsc_size * 8,
+
+	/* The size of a CBR packet's payload in bytes. */
+	pt_pl_cbr_size		= 2,
+
+	/* The size of a PSB packet's payload in bytes. */
+	pt_pl_psb_size		= pt_psb_repeat_count * pt_psb_repeat_size,
+
+	/* The size of a MODE packet's payload in bytes. */
+	pt_pl_mode_size		= 1,
+
+	/* The size of an IP packet's payload with update-16 compression. */
+	pt_pl_ip_upd16_size	= 2,
+
+	/* The size of an IP packet's payload with update-32 compression. */
+	pt_pl_ip_upd32_size	= 4,
+
+	/* The size of an IP packet's payload with update-48 compression. */
+	pt_pl_ip_upd48_size	= 6,
+
+	/* The size of an IP packet's payload with sext-48 compression. */
+	pt_pl_ip_sext48_size	= 6,
+
+	/* The size of an IP packet's payload with full-ip compression. */
+	pt_pl_ip_full_size	= 8,
+
+	/* Byte locations, sizes, and masks for processing TMA packets. */
+	pt_pl_tma_size		= 5,
+	pt_pl_tma_ctc_size	= 2,
+	pt_pl_tma_ctc_bit_size	= pt_pl_tma_ctc_size * 8,
+	pt_pl_tma_ctc_0		= 2,
+	pt_pl_tma_ctc_1		= 3,
+	pt_pl_tma_ctc_mask	= (1 << pt_pl_tma_ctc_bit_size) - 1,
+	pt_pl_tma_fc_size	= 2,
+	pt_pl_tma_fc_bit_size	= 9,
+	pt_pl_tma_fc_0		= 5,
+	pt_pl_tma_fc_1		= 6,
+	pt_pl_tma_fc_mask	= (1 << pt_pl_tma_fc_bit_size) - 1,
+
+	/* The size of a MTC packet's payload in bytes and in bits. */
+	pt_pl_mtc_size		= 1,
+	pt_pl_mtc_bit_size	= pt_pl_mtc_size * 8,
+
+	/* A mask for the MTC payload bits. */
+	pt_pl_mtc_mask		= (1 << pt_pl_mtc_bit_size) - 1,
+
+	/* The maximal payload size in bytes of a CYC packet. */
+	pt_pl_cyc_max_size	= 15,
+
+	/* The size of a VMCS packet's payload in bytes. */
+	pt_pl_vmcs_size		= 5,
+
+	/* The shift counts for post-processing the VMCS payload. */
+	pt_pl_vmcs_shl		= 12,
+
+	/* The size of a MNT packet's payload in bytes. */
+	pt_pl_mnt_size		= 8
+};
+
+/** Mode packet masks. */
+enum pt_mode_mask {
+	pt_mom_leaf		= 0xe0,
+	pt_mom_leaf_shr		= 5,
+	pt_mom_bits		= 0x1f
+};
+
+/** Mode packet leaves. */
+enum pt_mode_leaf {
+	pt_mol_exec		= 0x00,
+	pt_mol_tsx		= 0x20
+};
+
+/** Mode packet bits. */
+enum pt_mode_bit {
+	/* mode.exec */
+	pt_mob_exec_csl		= 0x01,
+	pt_mob_exec_csd		= 0x02,
+
+	/* mode.tsx */
+	pt_mob_tsx_intx		= 0x01,
+	pt_mob_tsx_abrt		= 0x02
+};
+
+/** The IP compression. */
+enum pt_ip_compression {
+	/* The bits encode the payload size and the encoding scheme.
+	 *
+	 * No payload.  The IP has been suppressed.
+	 */
+	pt_ipc_suppressed	= 0x0,
+
+	/* Payload: 16 bits.  Update last IP. */
+	pt_ipc_update_16	= 0x01,
+
+	/* Payload: 32 bits.  Update last IP. */
+	pt_ipc_update_32	= 0x02,
+
+	/* Payload: 48 bits.  Sign extend to full address. */
+	pt_ipc_sext_48		= 0x03,
+
+	/* Payload: 48 bits.  Update last IP. */
+	pt_ipc_update_48	= 0x04,
+
+	/* Payload: 64 bits.  Full address. */
+	pt_ipc_full		= 0x06
+};
+
+/** The size of the various packets in bytes. */
+enum pt_packet_size {
+	ptps_pad		= pt_opcs_pad,
+	ptps_tnt_8		= pt_opcs_tnt_8,
+	ptps_mode		= pt_opcs_mode + pt_pl_mode_size,
+	ptps_tsc		= pt_opcs_tsc + pt_pl_tsc_size,
+	ptps_mtc		= pt_opcs_mtc + pt_pl_mtc_size,
+	ptps_psb		= pt_opcs_psb + pt_pl_psb_size,
+	ptps_psbend		= pt_opcs_psbend,
+	ptps_ovf		= pt_opcs_ovf,
+	ptps_pip		= pt_opcs_pip + pt_pl_pip_size,
+	ptps_tnt_64		= pt_opcs_tnt_64 + pt_pl_tnt_64_size,
+	ptps_cbr		= pt_opcs_cbr + pt_pl_cbr_size,
+	ptps_tip_supp		= pt_opcs_tip,
+	ptps_tip_upd16		= pt_opcs_tip + pt_pl_ip_upd16_size,
+	ptps_tip_upd32		= pt_opcs_tip + pt_pl_ip_upd32_size,
+	ptps_tip_upd48		= pt_opcs_tip + pt_pl_ip_upd48_size,
+	ptps_tip_sext48		= pt_opcs_tip + pt_pl_ip_sext48_size,
+	ptps_tip_full		= pt_opcs_tip + pt_pl_ip_full_size,
+	ptps_tip_pge_supp	= pt_opcs_tip_pge,
+	ptps_tip_pge_upd16	= pt_opcs_tip_pge + pt_pl_ip_upd16_size,
+	ptps_tip_pge_upd32	= pt_opcs_tip_pge + pt_pl_ip_upd32_size,
+	ptps_tip_pge_upd48	= pt_opcs_tip_pge + pt_pl_ip_upd48_size,
+	ptps_tip_pge_sext48	= pt_opcs_tip_pge + pt_pl_ip_sext48_size,
+	ptps_tip_pge_full	= pt_opcs_tip_pge + pt_pl_ip_full_size,
+	ptps_tip_pgd_supp	= pt_opcs_tip_pgd,
+	ptps_tip_pgd_upd16	= pt_opcs_tip_pgd + pt_pl_ip_upd16_size,
+	ptps_tip_pgd_upd32	= pt_opcs_tip_pgd + pt_pl_ip_upd32_size,
+	ptps_tip_pgd_upd48	= pt_opcs_tip_pgd + pt_pl_ip_upd48_size,
+	ptps_tip_pgd_sext48	= pt_opcs_tip_pgd + pt_pl_ip_sext48_size,
+	ptps_tip_pgd_full	= pt_opcs_tip_pgd + pt_pl_ip_full_size,
+	ptps_fup_supp		= pt_opcs_fup,
+	ptps_fup_upd16		= pt_opcs_fup + pt_pl_ip_upd16_size,
+	ptps_fup_upd32		= pt_opcs_fup + pt_pl_ip_upd32_size,
+	ptps_fup_upd48		= pt_opcs_fup + pt_pl_ip_upd48_size,
+	ptps_fup_sext48		= pt_opcs_fup + pt_pl_ip_sext48_size,
+	ptps_fup_full		= pt_opcs_fup + pt_pl_ip_full_size,
+	ptps_tma		= pt_opcs_tma + pt_pl_tma_size,
+	ptps_stop		= pt_opcs_stop,
+	ptps_vmcs		= pt_opcs_vmcs + pt_pl_vmcs_size,
+	ptps_mnt		= pt_opcs_mnt + pt_pl_mnt_size
+};
+
+
+
+/* Errors. */
+
+
+
+/** Error codes. */
+enum pt_error_code {
+	/* No error. Everything is OK. */
+	pte_ok,
+
+	/* Internal decoder error. */
+	pte_internal,
+
+	/* Invalid argument. */
+	pte_invalid,
+
+	/* Decoder out of sync. */
+	pte_nosync,
+
+	/* Unknown opcode. */
+	pte_bad_opc,
+
+	/* Unknown payload. */
+	pte_bad_packet,
+
+	/* Unexpected packet context. */
+	pte_bad_context,
+
+	/* Decoder reached end of trace stream. */
+	pte_eos,
+
+	/* No packet matching the query to be found. */
+	pte_bad_query,
+
+	/* Decoder out of memory. */
+	pte_nomem,
+
+	/* Bad configuration. */
+	pte_bad_config,
+
+	/* There is no IP. */
+	pte_noip,
+
+	/* The IP has been suppressed. */
+	pte_ip_suppressed,
+
+	/* There is no memory mapped at the requested address. */
+	pte_nomap,
+
+	/* An instruction could not be decoded. */
+	pte_bad_insn,
+
+	/* No wall-clock time is available. */
+	pte_no_time,
+
+	/* No core:bus ratio available. */
+	pte_no_cbr,
+
+	/* Bad traced image. */
+	pte_bad_image,
+
+	/* A locking error. */
+	pte_bad_lock,
+
+	/* The requested feature is not supported. */
+	pte_not_supported,
+
+	/* The return address stack is empty. */
+	pte_retstack_empty,
+
+	/* A compressed return is not indicated correctly by a taken branch. */
+	pte_bad_retcomp,
+
+	/* The current decoder state does not match the state in the trace. */
+	pte_bad_status_update,
+
+	/* The trace did not contain an expected enabled event. */
+	pte_no_enable,
+
+	/* An event was ignored. */
+	pte_event_ignored
+};
+
+
+/** Decode a function return value into an pt_error_code. */
+static inline enum pt_error_code pt_errcode(int status)
+{
+	return (status >= 0) ? pte_ok : (enum pt_error_code) -status;
+}
+
+/** Return a human readable error string. */
+extern pt_export const char *pt_errstr(enum pt_error_code);
+
+
+
+/* Configuration. */
+
+
+
+/** A cpu vendor. */
+enum pt_cpu_vendor {
+	pcv_unknown,
+	pcv_intel
+};
+
+/** A cpu identifier. */
+struct pt_cpu {
+	/** The cpu vendor. */
+	enum pt_cpu_vendor vendor;
+
+	/** The cpu family. */
+	uint16_t family;
+
+	/** The cpu model. */
+	uint8_t model;
+
+	/** The stepping. */
+	uint8_t stepping;
+};
+
+/** A collection of Intel PT errata. */
+struct pt_errata {
+	/** BDM70: Intel(R) Processor Trace PSB+ Packets May Contain
+	 *         Unexpected Packets.
+	 *
+	 * Same as: SKD024.
+	 *
+	 * Some Intel Processor Trace packets should be issued only between
+	 * TIP.PGE and TIP.PGD packets.  Due to this erratum, when a TIP.PGE
+	 * packet is generated it may be preceded by a PSB+ that incorrectly
+	 * includes FUP and MODE.Exec packets.
+	 */
+	uint32_t bdm70:1;
+
+	/** BDM64: An Incorrect LBR or Intel(R) Processor Trace Packet May Be
+	 *         Recorded Following a Transactional Abort.
+	 *
+	 * Use of Intel(R) Transactional Synchronization Extensions (Intel(R)
+	 * TSX) may result in a transactional abort.  If an abort occurs
+	 * immediately following a branch instruction, an incorrect branch
+	 * target may be logged in an LBR (Last Branch Record) or in an Intel(R)
+	 * Processor Trace (Intel(R) PT) packet before the LBR or Intel PT
+	 * packet produced by the abort.
+	 */
+	uint32_t bdm64:1;
+
+	/** SKD007: Intel(R) PT Buffer Overflow May Result in Incorrect Packets.
+	 *
+	 * Under complex micro-architectural conditions, an Intel PT (Processor
+	 * Trace) OVF (Overflow) packet may be issued after the first byte of a
+	 * multi-byte CYC (Cycle Count) packet, instead of any remaining bytes
+	 * of the CYC.
+	 */
+	uint32_t skd007:1;
+
+	/** SKD022: VM Entry That Clears TraceEn May Generate a FUP.
+	 *
+	 * If VM entry clears Intel(R) PT (Intel Processor Trace)
+	 * IA32_RTIT_CTL.TraceEn (MSR 570H, bit 0) while PacketEn is 1 then a
+	 * FUP (Flow Update Packet) will precede the TIP.PGD (Target IP Packet,
+	 * Packet Generation Disable).  VM entry can clear TraceEn if the
+	 * VM-entry MSR-load area includes an entry for the IA32_RTIT_CTL MSR.
+	 */
+	uint32_t skd022:1;
+
+	/** SKD010: Intel(R) PT FUP May be Dropped After OVF.
+	 *
+	 * Same as: SKD014.
+	 *
+	 * Some Intel PT (Intel Processor Trace) OVF (Overflow) packets may not
+	 * be followed by a FUP (Flow Update Packet) or TIP.PGE (Target IP
+	 * Packet, Packet Generation Enable).
+	 */
+	uint32_t skd010:1;
+
+	/* Reserve a few bytes for the future. */
+	uint32_t reserved[15];
+};
+
+/** A collection of decoder-specific configuration flags. */
+struct pt_conf_flags {
+	/** The decoder variant. */
+	union {
+		/** Flags for the block decoder. */
+		struct {
+			/** End a block after a call instruction. */
+			uint32_t end_on_call:1;
+		} block;
+
+		/* Reserve a few bytes for future extensions. */
+		uint32_t reserved[4];
+	} variant;
+};
+
+/** An unknown packet. */
+struct pt_packet_unknown;
+
+/** An Intel PT decoder configuration.
+ */
+struct pt_config {
+	/** The size of the config structure in bytes. */
+	size_t size;
+
+	/** The trace buffer begin address. */
+	uint8_t *begin;
+
+	/** The trace buffer end address. */
+	uint8_t *end;
+
+	/** An optional callback for handling unknown packets.
+	 *
+	 * If \@callback is not NULL, it is called for any unknown opcode.
+	 */
+	struct {
+		/** The callback function.
+		 *
+		 * It shall decode the packet at \@pos into \@unknown.
+		 * It shall return the number of bytes read upon success.
+		 * It shall return a negative pt_error_code otherwise.
+		 * The below context is passed as \@context.
+		 */
+		int (*callback)(struct pt_packet_unknown *unknown,
+				const struct pt_config *config,
+				const uint8_t *pos, void *context);
+
+		/** The user-defined context for this configuration. */
+		void *context;
+	} decode;
+
+	/** The cpu on which Intel PT has been recorded. */
+	struct pt_cpu cpu;
+
+	/** The errata to apply when encoding or decoding Intel PT. */
+	struct pt_errata errata;
+
+	/* The CTC frequency.
+	 *
+	 * This is only required if MTC packets have been enabled in
+	 * IA32_RTIT_CTRL.MTCEn.
+	 */
+	uint32_t cpuid_0x15_eax, cpuid_0x15_ebx;
+
+	/* The MTC frequency as defined in IA32_RTIT_CTL.MTCFreq.
+	 *
+	 * This is only required if MTC packets have been enabled in
+	 * IA32_RTIT_CTRL.MTCEn.
+	 */
+	uint8_t mtc_freq;
+
+	/* The nominal frequency as defined in MSR_PLATFORM_INFO[15:8].
+	 *
+	 * This is only required if CYC packets have been enabled in
+	 * IA32_RTIT_CTRL.CYCEn.
+	 *
+	 * If zero, timing calibration will only be able to use MTC and CYC
+	 * packets.
+	 *
+	 * If not zero, timing calibration will also be able to use CBR
+	 * packets.
+	 */
+	uint8_t nom_freq;
+
+	/** A collection of decoder-specific flags. */
+	struct pt_conf_flags flags;
+};
+
+
+/** Zero-initialize an Intel PT configuration. */
+static inline void pt_config_init(struct pt_config *config)
+{
+	memset(config, 0, sizeof(*config));
+
+	config->size = sizeof(*config);
+}
+
+/** Determine errata for a given cpu.
+ *
+ * Updates \@errata based on \@cpu.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ * Returns -pte_invalid if \@errata or \@cpu is NULL.
+ */
+extern pt_export int pt_cpu_errata(struct pt_errata *errata,
+				   const struct pt_cpu *cpu);
+
+
+
+/* Packet encoder / decoder. */
+
+
+
+/* We define a few abbreviations outside of the below enum as we don't
+ * want to handle those in switches.
+ */
+enum {
+	ppt_ext			= pt_opc_ext << 8,
+	ppt_ext2		= ppt_ext << 8 | pt_ext_ext2 << 8
+};
+
+/** Intel PT packet types. */
+enum pt_packet_type {
+	/* 1-byte header packets. */
+	ppt_pad			= pt_opc_pad,
+	ppt_tip			= pt_opc_tip,
+	ppt_tnt_8		= pt_opc_tnt_8 | 0xFE,
+	ppt_tip_pge		= pt_opc_tip_pge,
+	ppt_tip_pgd		= pt_opc_tip_pgd,
+	ppt_fup			= pt_opc_fup,
+	ppt_mode		= pt_opc_mode,
+	ppt_tsc			= pt_opc_tsc,
+	ppt_mtc			= pt_opc_mtc,
+	ppt_cyc			= pt_opc_cyc,
+
+	/* 2-byte header packets. */
+	ppt_psb			= ppt_ext | pt_ext_psb,
+	ppt_tnt_64		= ppt_ext | pt_ext_tnt_64,
+	ppt_pip			= ppt_ext | pt_ext_pip,
+	ppt_stop		= ppt_ext | pt_ext_stop,
+	ppt_ovf			= ppt_ext | pt_ext_ovf,
+	ppt_psbend		= ppt_ext | pt_ext_psbend,
+	ppt_cbr			= ppt_ext | pt_ext_cbr,
+	ppt_tma			= ppt_ext | pt_ext_tma,
+	ppt_vmcs		= ppt_ext | pt_ext_vmcs,
+
+	/* 3-byte header packets. */
+	ppt_mnt			= ppt_ext2 | pt_ext2_mnt,
+
+	/* A packet decodable by the optional decoder callback. */
+	ppt_unknown		= 0x7ffffffe,
+
+	/* An invalid packet. */
+	ppt_invalid		= 0x7fffffff
+};
+
+/** A TNT-8 or TNT-64 packet. */
+struct pt_packet_tnt {
+	/** TNT payload bit size. */
+	uint8_t bit_size;
+
+	/** TNT payload excluding stop bit. */
+	uint64_t payload;
+};
+
+/** A packet with IP payload. */
+struct pt_packet_ip {
+	/** IP compression. */
+	enum pt_ip_compression ipc;
+
+	/** Zero-extended payload ip. */
+	uint64_t ip;
+};
+
+/** A mode.exec packet. */
+struct pt_packet_mode_exec {
+	/** The mode.exec csl bit. */
+	uint32_t csl:1;
+
+	/** The mode.exec csd bit. */
+	uint32_t csd:1;
+};
+
+static inline enum pt_exec_mode
+pt_get_exec_mode(const struct pt_packet_mode_exec *packet)
+{
+	if (packet->csl)
+		return packet->csd ? ptem_unknown : ptem_64bit;
+	else
+		return packet->csd ? ptem_32bit : ptem_16bit;
+}
+
+static inline struct pt_packet_mode_exec
+pt_set_exec_mode(enum pt_exec_mode mode)
+{
+	struct pt_packet_mode_exec packet;
+
+	switch (mode) {
+	default:
+		packet.csl = 1;
+		packet.csd = 1;
+		break;
+
+	case ptem_64bit:
+		packet.csl = 1;
+		packet.csd = 0;
+		break;
+
+	case ptem_32bit:
+		packet.csl = 0;
+		packet.csd = 1;
+		break;
+
+	case ptem_16bit:
+		packet.csl = 0;
+		packet.csd = 0;
+		break;
+	}
+
+	return packet;
+}
+
+/** A mode.tsx packet. */
+struct pt_packet_mode_tsx {
+	/** The mode.tsx intx bit. */
+	uint32_t intx:1;
+
+	/** The mode.tsx abrt bit. */
+	uint32_t abrt:1;
+};
+
+/** A mode packet. */
+struct pt_packet_mode {
+	/** Mode leaf. */
+	enum pt_mode_leaf leaf;
+
+	/** Mode bits. */
+	union {
+		/** Packet: mode.exec. */
+		struct pt_packet_mode_exec exec;
+
+		/** Packet: mode.tsx. */
+		struct pt_packet_mode_tsx tsx;
+	} bits;
+};
+
+/** A PIP packet. */
+struct pt_packet_pip {
+	/** The CR3 value. */
+	uint64_t cr3;
+
+	/** The non-root bit. */
+	uint32_t nr:1;
+};
+
+/** A TSC packet. */
+struct pt_packet_tsc {
+	/** The TSC value. */
+	uint64_t tsc;
+};
+
+/** A CBR packet. */
+struct pt_packet_cbr {
+	/** The core/bus cycle ratio. */
+	uint8_t ratio;
+};
+
+/** A TMA packet. */
+struct pt_packet_tma {
+	/** The crystal clock tick counter value. */
+	uint16_t ctc;
+
+	/** The fast counter value. */
+	uint16_t fc;
+};
+
+/** A MTC packet. */
+struct pt_packet_mtc {
+	/** The crystal clock tick counter value. */
+	uint8_t ctc;
+};
+
+/** A CYC packet. */
+struct pt_packet_cyc {
+	/** The cycle counter value. */
+	uint64_t value;
+};
+
+/** A VMCS packet. */
+struct pt_packet_vmcs {
+       /* The VMCS Base Address (i.e. the shifted payload). */
+	uint64_t base;
+};
+
+/** A MNT packet. */
+struct pt_packet_mnt {
+	/** The raw payload. */
+	uint64_t payload;
+};
+
+/** An unknown packet decodable by the optional decoder callback. */
+struct pt_packet_unknown {
+	/** Pointer to the raw packet bytes. */
+	const uint8_t *packet;
+
+	/** Optional pointer to a user-defined structure. */
+	void *priv;
+};
+
+/** An Intel PT packet. */
+struct pt_packet {
+	/** The type of the packet.
+	 *
+	 * This also determines the \@payload field.
+	 */
+	enum pt_packet_type type;
+
+	/** The size of the packet including opcode and payload. */
+	uint8_t size;
+
+	/** Packet specific data. */
+	union {
+		/** Packets: pad, ovf, psb, psbend, stop - no payload. */
+
+		/** Packet: tnt-8, tnt-64. */
+		struct pt_packet_tnt tnt;
+
+		/** Packet: tip, fup, tip.pge, tip.pgd. */
+		struct pt_packet_ip ip;
+
+		/** Packet: mode. */
+		struct pt_packet_mode mode;
+
+		/** Packet: pip. */
+		struct pt_packet_pip pip;
+
+		/** Packet: tsc. */
+		struct pt_packet_tsc tsc;
+
+		/** Packet: cbr. */
+		struct pt_packet_cbr cbr;
+
+		/** Packet: tma. */
+		struct pt_packet_tma tma;
+
+		/** Packet: mtc. */
+		struct pt_packet_mtc mtc;
+
+		/** Packet: cyc. */
+		struct pt_packet_cyc cyc;
+
+		/** Packet: vmcs. */
+		struct pt_packet_vmcs vmcs;
+
+		/** Packet: mnt. */
+		struct pt_packet_mnt mnt;
+
+		/** Packet: unknown. */
+		struct pt_packet_unknown unknown;
+	} payload;
+};
+
+
+
+/* Packet encoder. */
+
+
+
+/** Allocate an Intel PT packet encoder.
+ *
+ * The encoder will work on the buffer defined in \@config, it shall contain
+ * raw trace data and remain valid for the lifetime of the encoder.
+ *
+ * The encoder starts at the beginning of the trace buffer.
+ */
+extern pt_export struct pt_encoder *
+pt_alloc_encoder(const struct pt_config *config);
+
+/** Free an Intel PT packet encoder.
+ *
+ * The \@encoder must not be used after a successful return.
+ */
+extern pt_export void pt_free_encoder(struct pt_encoder *encoder);
+
+/** Hard set synchronization point of an Intel PT packet encoder.
+ *
+ * Synchronize \@encoder to \@offset within the trace buffer.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_eos if the given offset is behind the end of the trace buffer.
+ * Returns -pte_invalid if \@encoder is NULL.
+ */
+extern pt_export int pt_enc_sync_set(struct pt_encoder *encoder,
+				     uint64_t offset);
+
+/** Get the current packet encoder position.
+ *
+ * Fills the current \@encoder position into \@offset.
+ *
+ * This is useful for reporting errors.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@encoder or \@offset is NULL.
+ */
+extern pt_export int pt_enc_get_offset(struct pt_encoder *encoder,
+				       uint64_t *offset);
+
+/* Return a pointer to \@encoder's configuration.
+ *
+ * Returns a non-null pointer on success, NULL if \@encoder is NULL.
+ */
+extern pt_export const struct pt_config *
+pt_enc_get_config(const struct pt_encoder *encoder);
+
+/** Encode an Intel PT packet.
+ *
+ * Writes \@packet at \@encoder's current position in the Intel PT buffer and
+ * advances the \@encoder beyond the written packet.
+ *
+ * The \@packet.size field is ignored.
+ *
+ * In case of errors, the \@encoder is not advanced and nothing is written
+ * into the Intel PT buffer.
+ *
+ * Returns the number of bytes written on success, a negative error code
+ * otherwise.
+ *
+ * Returns -pte_bad_opc if \@packet.type is not known.
+ * Returns -pte_bad_packet if \@packet's payload is invalid.
+ * Returns -pte_eos if \@encoder reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@encoder or \@packet is NULL.
+ */
+extern pt_export int pt_enc_next(struct pt_encoder *encoder,
+				 const struct pt_packet *packet);
+
+
+
+/* Packet decoder. */
+
+
+
+/** Allocate an Intel PT packet decoder.
+ *
+ * The decoder will work on the buffer defined in \@config, it shall contain
+ * raw trace data and remain valid for the lifetime of the decoder.
+ *
+ * The decoder needs to be synchronized before it can be used.
+ */
+extern pt_export struct pt_packet_decoder *
+pt_pkt_alloc_decoder(const struct pt_config *config);
+
+/** Free an Intel PT packet decoder.
+ *
+ * The \@decoder must not be used after a successful return.
+ */
+extern pt_export void pt_pkt_free_decoder(struct pt_packet_decoder *decoder);
+
+/** Synchronize an Intel PT packet decoder.
+ *
+ * Search for the next synchronization point in forward or backward direction.
+ *
+ * If \@decoder has not been synchronized, yet, the search is started at the
+ * beginning of the trace buffer in case of forward synchronization and at the
+ * end of the trace buffer in case of backward synchronization.
+ *
+ * Returns zero or a positive value on success, a negative error code otherwise.
+ *
+ * Returns -pte_eos if no further synchronization point is found.
+ * Returns -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_pkt_sync_forward(struct pt_packet_decoder *decoder);
+extern pt_export int pt_pkt_sync_backward(struct pt_packet_decoder *decoder);
+
+/** Hard set synchronization point of an Intel PT decoder.
+ *
+ * Synchronize \@decoder to \@offset within the trace buffer.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_eos if the given offset is behind the end of the trace buffer.
+ * Returns -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_pkt_sync_set(struct pt_packet_decoder *decoder,
+				     uint64_t offset);
+
+/** Get the current decoder position.
+ *
+ * Fills the current \@decoder position into \@offset.
+ *
+ * This is useful for reporting errors.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_pkt_get_offset(struct pt_packet_decoder *decoder,
+				       uint64_t *offset);
+
+/** Get the position of the last synchronization point.
+ *
+ * Fills the last synchronization position into \@offset.
+ *
+ * This is useful when splitting a trace stream for parallel decoding.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_pkt_get_sync_offset(struct pt_packet_decoder *decoder,
+					    uint64_t *offset);
+
+/* Return a pointer to \@decoder's configuration.
+ *
+ * Returns a non-null pointer on success, NULL if \@decoder is NULL.
+ */
+extern pt_export const struct pt_config *
+pt_pkt_get_config(const struct pt_packet_decoder *decoder);
+
+/** Decode the next packet and advance the decoder.
+ *
+ * Decodes the packet at \@decoder's current position into \@packet and
+ * adjusts the \@decoder's position by the number of bytes the packet had
+ * consumed.
+ *
+ * The \@size argument must be set to sizeof(struct pt_packet).
+ *
+ * Returns the number of bytes consumed on success, a negative error code
+ * otherwise.
+ *
+ * Returns -pte_bad_opc if the packet is unknown.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if \@decoder reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@packet is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_pkt_next(struct pt_packet_decoder *decoder,
+				 struct pt_packet *packet, size_t size);
+
+
+
+/* Query decoder. */
+
+
+
+/** Decoder status flags. */
+enum pt_status_flag {
+	/** There is an event pending. */
+	pts_event_pending	= 1 << 0,
+
+	/** The address has been suppressed. */
+	pts_ip_suppressed	= 1 << 1,
+
+	/** There is no more trace data available. */
+	pts_eos			= 1 << 2
+};
+
+/** Event types. */
+enum pt_event_type {
+	/* Tracing has been enabled/disabled. */
+	ptev_enabled,
+	ptev_disabled,
+
+	/* Tracing has been disabled asynchronously. */
+	ptev_async_disabled,
+
+	/* An asynchronous branch, e.g. interrupt. */
+	ptev_async_branch,
+
+	/* A synchronous paging event. */
+	ptev_paging,
+
+	/* An asynchronous paging event. */
+	ptev_async_paging,
+
+	/* Trace overflow. */
+	ptev_overflow,
+
+	/* An execution mode change. */
+	ptev_exec_mode,
+
+	/* A transactional execution state change. */
+	ptev_tsx,
+
+	/* Trace Stop. */
+	ptev_stop,
+
+	/* A synchronous vmcs event. */
+	ptev_vmcs,
+
+	/* An asynchronous vmcs event. */
+	ptev_async_vmcs
+};
+
+/** An event. */
+struct pt_event {
+	/** The type of the event. */
+	enum pt_event_type type;
+
+	/** A flag indicating that the event IP has been suppressed. */
+	uint32_t ip_suppressed:1;
+
+	/** A flag indicating that the event is for status update. */
+	uint32_t status_update:1;
+
+	/** A flag indicating that the event has timing information. */
+	uint32_t has_tsc:1;
+
+	/** The time stamp count of the event.
+	 *
+	 * This field is only valid if \@has_tsc is set.
+	 */
+	uint64_t tsc;
+
+	/** The number of lost mtc and cyc packets.
+	 *
+	 * This gives an idea about the quality of the \@tsc.  The more packets
+	 * were dropped, the less precise timing is.
+	 */
+	uint32_t lost_mtc;
+	uint32_t lost_cyc;
+
+	/* Reserved space for future extensions. */
+	uint64_t reserved[2];
+
+	/** Event specific data. */
+	union {
+		/** Event: enabled. */
+		struct {
+			/** The address at which tracing resumes. */
+			uint64_t ip;
+		} enabled;
+
+		/** Event: disabled. */
+		struct {
+			/** The destination of the first branch inside a
+			 * filtered area.
+			 *
+			 * This field is not valid if \@ip_suppressed is set.
+			 */
+			uint64_t ip;
+
+			/* The exact source ip needs to be determined using
+			 * disassembly and the filter configuration.
+			 */
+		} disabled;
+
+		/** Event: async disabled. */
+		struct {
+			/** The source address of the asynchronous branch that
+			 * disabled tracing.
+			 */
+			uint64_t at;
+
+			/** The destination of the first branch inside a
+			 * filtered area.
+			 *
+			 * This field is not valid if \@ip_suppressed is set.
+			 */
+			uint64_t ip;
+		} async_disabled;
+
+		/** Event: async branch. */
+		struct {
+			/** The branch source address. */
+			uint64_t from;
+
+			/** The branch destination address.
+			 *
+			 * This field is not valid if \@ip_suppressed is set.
+			 */
+			uint64_t to;
+		} async_branch;
+
+		/** Event: paging. */
+		struct {
+			/** The updated CR3 value.
+			 *
+			 * The lower 5 bit have been zeroed out.
+			 * The upper bits have been zeroed out depending on the
+			 * maximum possible address.
+			 */
+			uint64_t cr3;
+
+			/** A flag indicating whether the cpu is operating in
+			 * vmx non-root (guest) mode.
+			 */
+			uint32_t non_root:1;
+
+			/* The address at which the event is effective is
+			 * obvious from the disassembly.
+			 */
+		} paging;
+
+		/** Event: async paging. */
+		struct {
+			/** The updated CR3 value.
+			 *
+			 * The lower 5 bit have been zeroed out.
+			 * The upper bits have been zeroed out depending on the
+			 * maximum possible address.
+			 */
+			uint64_t cr3;
+
+			/** A flag indicating whether the cpu is operating in
+			 * vmx non-root (guest) mode.
+			 */
+			uint32_t non_root:1;
+
+			/** The address at which the event is effective. */
+			uint64_t ip;
+		} async_paging;
+
+		/** Event: overflow. */
+		struct {
+			/** The address at which tracing resumes after overflow.
+			 *
+			 * This field is not valid, if ip_suppressed is set.
+			 * In this case, the overflow resolved while tracing
+			 * was disabled.
+			 */
+			uint64_t ip;
+		} overflow;
+
+		/** Event: exec mode. */
+		struct {
+			/** The execution mode. */
+			enum pt_exec_mode mode;
+
+			/** The address at which the event is effective. */
+			uint64_t ip;
+		} exec_mode;
+
+		/** Event: tsx. */
+		struct {
+			/** The address at which the event is effective.
+			 *
+			 * This field is not valid if \@ip_suppressed is set.
+			 */
+			uint64_t ip;
+
+			/** A flag indicating speculative execution mode. */
+			uint32_t speculative:1;
+
+			/** A flag indicating speculative execution aborts. */
+			uint32_t aborted:1;
+		} tsx;
+
+		/** Event: vmcs. */
+		struct {
+			/** The VMCS base address.
+			 *
+			 * The address is zero-extended with the lower 12 bits
+			 * all zero.
+			 */
+			uint64_t base;
+
+			/* The new VMCS base address should be stored and
+			 * applied on subsequent VM entries.
+			 */
+		} vmcs;
+
+		/** Event: async vmcs. */
+		struct {
+			/** The VMCS base address.
+			 *
+			 * The address is zero-extended with the lower 12 bits
+			 * all zero.
+			 */
+			uint64_t base;
+
+			/** The address at which the event is effective. */
+			uint64_t ip;
+
+			/* An async paging event that binds to the same IP
+			 * will always succeed this async vmcs event.
+			 */
+		} async_vmcs;
+	} variant;
+};
+
+
+/** Allocate an Intel PT query decoder.
+ *
+ * The decoder will work on the buffer defined in \@config, it shall contain
+ * raw trace data and remain valid for the lifetime of the decoder.
+ *
+ * The decoder needs to be synchronized before it can be used.
+ */
+extern pt_export struct pt_query_decoder *
+pt_qry_alloc_decoder(const struct pt_config *config);
+
+/** Free an Intel PT query decoder.
+ *
+ * The \@decoder must not be used after a successful return.
+ */
+extern pt_export void pt_qry_free_decoder(struct pt_query_decoder *decoder);
+
+/** Synchronize an Intel PT query decoder.
+ *
+ * Search for the next synchronization point in forward or backward direction.
+ *
+ * If \@decoder has not been synchronized, yet, the search is started at the
+ * beginning of the trace buffer in case of forward synchronization and at the
+ * end of the trace buffer in case of backward synchronization.
+ *
+ * If \@ip is not NULL, set it to last ip.
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if no further synchronization point is found.
+ * Returns -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_qry_sync_forward(struct pt_query_decoder *decoder,
+					 uint64_t *ip);
+extern pt_export int pt_qry_sync_backward(struct pt_query_decoder *decoder,
+					 uint64_t *ip);
+
+/** Manually synchronize an Intel PT query decoder.
+ *
+ * Synchronize \@decoder on the syncpoint at \@offset.  There must be a PSB
+ * packet at \@offset.
+ *
+ * If \@ip is not NULL, set it to last ip.
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
+ * Returns -pte_eos if \@decoder reaches the end of its trace buffer.
+ * Returns -pte_invalid if \@decoder is NULL.
+ * Returns -pte_nosync if there is no syncpoint at \@offset.
+ */
+extern pt_export int pt_qry_sync_set(struct pt_query_decoder *decoder,
+				     uint64_t *ip, uint64_t offset);
+
+/** Get the current decoder position.
+ *
+ * Fills the current \@decoder position into \@offset.
+ *
+ * This is useful for reporting errors.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_qry_get_offset(struct pt_query_decoder *decoder,
+				       uint64_t *offset);
+
+/** Get the position of the last synchronization point.
+ *
+ * Fills the last synchronization position into \@offset.
+ *
+ * This is useful for splitting a trace stream for parallel decoding.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_qry_get_sync_offset(struct pt_query_decoder *decoder,
+					    uint64_t *offset);
+
+/* Return a pointer to \@decoder's configuration.
+ *
+ * Returns a non-null pointer on success, NULL if \@decoder is NULL.
+ */
+extern pt_export const struct pt_config *
+pt_qry_get_config(const struct pt_query_decoder *decoder);
+
+/** Query whether the next unconditional branch has been taken.
+ *
+ * On success, provides 1 (taken) or 0 (not taken) in \@taken for the next
+ * conditional branch and updates \@decoder.
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_bad_query if no conditional branch is found.
+ * Returns -pte_eos if decoding reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@taken is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_qry_cond_branch(struct pt_query_decoder *decoder,
+					int *taken);
+
+/** Get the next indirect branch destination.
+ *
+ * On success, provides the linear destination address of the next indirect
+ * branch in \@ip and updates \@decoder.
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_bad_query if no indirect branch is found.
+ * Returns -pte_eos if decoding reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@ip is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_qry_indirect_branch(struct pt_query_decoder *decoder,
+					    uint64_t *ip);
+
+/** Query the next pending event.
+ *
+ * On success, provides the next event \@event and updates \@decoder.
+ *
+ * The \@size argument must be set to sizeof(struct pt_event).
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_bad_query if no event is found.
+ * Returns -pte_eos if decoding reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@event is NULL.
+ * Returns -pte_invalid if \@size is too small.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_qry_event(struct pt_query_decoder *decoder,
+				  struct pt_event *event, size_t size);
+
+/** Query the current time.
+ *
+ * On success, provides the time at \@decoder's current position in \@time.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the time for that branch or event.
+ *
+ * The time is similar to what a rdtsc instruction would return.  Depending
+ * on the configuration, the time may not be fully accurate.  If TSC is not
+ * enabled, the time is relative to the last synchronization and can't be used
+ * to correlate with other TSC-based time sources.  In this case, -pte_no_time
+ * is returned and the relative time is provided in \@time.
+ *
+ * Some timing-related packets may need to be dropped (mostly due to missing
+ * calibration or incomplete configuration).  To get an idea about the quality
+ * of the estimated time, we record the number of dropped MTC and CYC packets.
+ *
+ * If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
+ * If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@time is NULL.
+ * Returns -pte_no_time if there has not been a TSC packet.
+ */
+extern pt_export int pt_qry_time(struct pt_query_decoder *decoder,
+				 uint64_t *time, uint32_t *lost_mtc,
+				 uint32_t *lost_cyc);
+
+/** Return the current core bus ratio.
+ *
+ * On success, provides the core:bus ratio at \@decoder's current position
+ * in \@cbr.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the core:bus ratio for that branch or event.
+ *
+ * The ratio is defined as core cycles per bus clock cycle.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@cbr is NULL.
+ * Returns -pte_no_cbr if there has not been a CBR packet.
+ */
+extern pt_export int pt_qry_core_bus_ratio(struct pt_query_decoder *decoder,
+					   uint32_t *cbr);
+
+
+
+/* Traced image. */
+
+
+
+/** An Intel PT address space identifier.
+ *
+ * This identifies a particular address space when adding file sections or
+ * when reading memory.
+ */
+struct pt_asid {
+	/** The size of this object - set to sizeof(struct pt_asid). */
+	size_t size;
+
+	/** The CR3 value. */
+	uint64_t cr3;
+
+	/** The VMCS Base address. */
+	uint64_t vmcs;
+};
+
+/** An unknown CR3 value to be used for pt_asid objects. */
+static const uint64_t pt_asid_no_cr3 = 0xffffffffffffffffull;
+
+/** An unknown VMCS Base value to be used for pt_asid objects. */
+static const uint64_t pt_asid_no_vmcs = 0xffffffffffffffffull;
+
+/** Initialize an address space identifier. */
+static inline void pt_asid_init(struct pt_asid *asid)
+{
+	asid->size = sizeof(*asid);
+	asid->cr3 = pt_asid_no_cr3;
+	asid->vmcs = pt_asid_no_vmcs;
+}
+
+
+/** A cache of traced image sections. */
+struct pt_image_section_cache;
+
+/** Allocate a traced memory image section cache.
+ *
+ * An optional \@name may be given to the cache.  The name string is copied.
+ *
+ * Returns a new traced memory image section cache on success, NULL otherwise.
+ */
+extern pt_export struct pt_image_section_cache *
+pt_iscache_alloc(const char *name);
+
+/** Free a traced memory image section cache.
+ *
+ * The \@iscache must have been allocated with pt_iscache_alloc().
+ * The \@iscache must not be used after a successful return.
+ */
+extern pt_export void pt_iscache_free(struct pt_image_section_cache *iscache);
+
+/** Get the image section cache name.
+ *
+ * Returns a pointer to \@iscache's name or NULL if there is no name.
+ */
+extern pt_export const char *
+pt_iscache_name(const struct pt_image_section_cache *iscache);
+
+/** Add a new file section to the traced memory image section cache.
+ *
+ * Adds a new section consisting of \@size bytes starting at \@offset in
+ * \@filename loaded at the virtual address \@vaddr if \@iscache does not
+ * already contain such a section.
+ *
+ * Returns an image section identifier (isid) uniquely identifying that section
+ * in \@iscache.
+ *
+ * The section is silently truncated to match the size of \@filename.
+ *
+ * Returns a positive isid on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@iscache or \@filename is NULL.
+ * Returns -pte_invalid if \@offset is too big.
+ */
+extern pt_export int pt_iscache_add_file(struct pt_image_section_cache *iscache,
+					 const char *filename, uint64_t offset,
+					 uint64_t size, uint64_t vaddr);
+
+/** Read memory from a cached file section
+ *
+ * Reads \@size bytes of memory starting at virtual address \@vaddr in the
+ * section identified by \@isid in \@iscache into \@buffer.
+ *
+ * The caller is responsible for allocating a \@buffer of at least \@size bytes.
+ *
+ * The read request may be truncated if it crosses section boundaries or if
+ * \@size is getting too big.  We support reading at least 4Kbyte in one chunk
+ * unless the read would cross a section boundary.
+ *
+ * Returns the number of bytes read on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@iscache or \@buffer is NULL.
+ * Returns -pte_invalid if \@size is zero.
+ * Returns -pte_nomap if \@vaddr is not contained in section \@isid.
+ * Returns -pte_bad_image if \@iscache does not contain \@isid.
+ */
+extern pt_export int pt_iscache_read(struct pt_image_section_cache *iscache,
+				     uint8_t *buffer, uint64_t size, int isid,
+				     uint64_t vaddr);
+
+/** The traced memory image. */
+struct pt_image;
+
+
+/** Allocate a traced memory image.
+ *
+ * An optional \@name may be given to the image.  The name string is copied.
+ *
+ * Returns a new traced memory image on success, NULL otherwise.
+ */
+extern pt_export struct pt_image *pt_image_alloc(const char *name);
+
+/** Free a traced memory image.
+ *
+ * The \@image must have been allocated with pt_image_alloc().
+ * The \@image must not be used after a successful return.
+ */
+extern pt_export void pt_image_free(struct pt_image *image);
+
+/** Get the image name.
+ *
+ * Returns a pointer to \@image's name or NULL if there is no name.
+ */
+extern pt_export const char *pt_image_name(const struct pt_image *image);
+
+/** Add a new file section to the traced memory image.
+ *
+ * Adds \@size bytes starting at \@offset in \@filename. The section is
+ * loaded at the virtual address \@vaddr in the address space \@asid.
+ *
+ * The \@asid may be NULL or (partially) invalid.  In that case only the valid
+ * fields are considered when comparing with other address-spaces.  Use this
+ * when tracing a single process or when adding sections to all processes.
+ *
+ * The section is silently truncated to match the size of \@filename.
+ *
+ * Existing sections that would overlap with the new section will be shrunk
+ * or split.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@image or \@filename is NULL.
+ * Returns -pte_invalid if \@offset is too big.
+ */
+extern pt_export int pt_image_add_file(struct pt_image *image,
+				       const char *filename, uint64_t offset,
+				       uint64_t size,
+				       const struct pt_asid *asid,
+				       uint64_t vaddr);
+
+/** Add a section from an image section cache.
+ *
+ * Add the section from \@iscache identified by \@isid in address space \@asid.
+ *
+ * Existing sections that would overlap with the new section will be shrunk
+ * or split.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ * Returns -pte_invalid if \@image or \@iscache is NULL.
+ * Returns -pte_bad_image if \@iscache does not contain \@isid.
+ */
+extern pt_export int pt_image_add_cached(struct pt_image *image,
+					 struct pt_image_section_cache *iscache,
+					 int isid, const struct pt_asid *asid);
+
+/** Copy an image.
+ *
+ * Adds all sections from \@src to \@image.  Sections that could not be added
+ * will be ignored.
+ *
+ * Returns the number of ignored sections on success, a negative error code
+ * otherwise.
+ *
+ * Returns -pte_invalid if \@image or \@src is NULL.
+ */
+extern pt_export int pt_image_copy(struct pt_image *image,
+				   const struct pt_image *src);
+
+/** Remove all sections loaded from a file.
+ *
+ * Removes all sections loaded from \@filename from the address space \@asid.
+ * Specify the same \@asid that was used for adding sections from \@filename.
+ *
+ * Returns the number of removed sections on success, a negative error code
+ * otherwise.
+ *
+ * Returns -pte_invalid if \@image or \@filename is NULL.
+ */
+extern pt_export int pt_image_remove_by_filename(struct pt_image *image,
+						 const char *filename,
+						 const struct pt_asid *asid);
+
+/** Remove all sections loaded into an address space.
+ *
+ * Removes all sections loaded into \@asid.  Specify the same \@asid that was
+ * used for adding sections.
+ *
+ * Returns the number of removed sections on success, a negative error code
+ * otherwise.
+ *
+ * Returns -pte_invalid if \@image is NULL.
+ */
+extern pt_export int pt_image_remove_by_asid(struct pt_image *image,
+					     const struct pt_asid *asid);
+
+/** A read memory callback function.
+ *
+ * It shall read \@size bytes of memory from address space \@asid starting
+ * at \@ip into \@buffer.
+ *
+ * It shall return the number of bytes read on success.
+ * It shall return a negative pt_error_code otherwise.
+ */
+typedef int (read_memory_callback_t)(uint8_t *buffer, size_t size,
+				     const struct pt_asid *asid,
+				     uint64_t ip, void *context);
+
+/** Set the memory callback for the traced memory image.
+ *
+ * Sets \@callback for reading memory.  The callback is used for addresses
+ * that are not found in file sections.  The \@context argument is passed
+ * to \@callback on each use.
+ *
+ * There can only be one callback at any time.  A subsequent call will replace
+ * the previous callback.  If \@callback is NULL, the callback is removed.
+ *
+ * Returns -pte_invalid if \@image is NULL.
+ */
+extern pt_export int pt_image_set_callback(struct pt_image *image,
+					   read_memory_callback_t *callback,
+					   void *context);
+
+/** Read memory from an image.
+ *
+ * For use by read_memory_callback_t functions.
+ * Same as pt_image_read, but with no callback support.
+ *
+ * Reads at most @size bytes from @image at @addr in @asid into @buffer.
+ *
+ * Returns the number of bytes read on success, a negative error code otherwise.
+ * Returns -pte_internal if @image, @buffer, or @asid is NULL.
+ * Returns -pte_nomap if the section does not contain @addr.
+ */
+extern pt_export int pt_image_read_for_callback(struct pt_image *image,
+						uint8_t *buffer, size_t size,
+						const struct pt_asid *asid,
+						uint64_t addr);
+
+
+/* Instruction flow decoder. */
+
+
+
+/** The instruction class.
+ *
+ * We provide only a very coarse classification suitable for reconstructing
+ * the execution flow.
+ */
+enum pt_insn_class {
+	/* The instruction could not be classified. */
+	ptic_error,
+
+	/* The instruction is something not listed below. */
+	ptic_other,
+
+	/* The instruction is a near (function) call. */
+	ptic_call,
+
+	/* The instruction is a near (function) return. */
+	ptic_return,
+
+	/* The instruction is a near unconditional jump. */
+	ptic_jump,
+
+	/* The instruction is a near conditional jump. */
+	ptic_cond_jump,
+
+	/* The instruction is a call-like far transfer.
+	 * E.g. SYSCALL, SYSENTER, or FAR CALL.
+	 */
+	ptic_far_call,
+
+	/* The instruction is a return-like far transfer.
+	 * E.g. SYSRET, SYSEXIT, IRET, or FAR RET.
+	 */
+	ptic_far_return,
+
+	/* The instruction is a jump-like far transfer.
+	 * E.g. FAR JMP.
+	 */
+	ptic_far_jump
+};
+
+/** The maximal size of an instruction. */
+enum {
+	pt_max_insn_size	= 15
+};
+
+/** A single traced instruction. */
+struct pt_insn {
+	/** The virtual address in its process. */
+	uint64_t ip;
+
+	/** A coarse classification. */
+	enum pt_insn_class iclass;
+
+	/** The execution mode. */
+	enum pt_exec_mode mode;
+
+	/** The raw bytes. */
+	uint8_t raw[pt_max_insn_size];
+
+	/** The size in bytes. */
+	uint8_t size;
+
+	/** A collection of flags giving additional information:
+	 *
+	 * - the instruction was executed speculatively.
+	 */
+	uint32_t speculative:1;
+
+	/** - speculative execution was aborted after this instruction. */
+	uint32_t aborted:1;
+
+	/** - speculative execution was committed after this instruction. */
+	uint32_t committed:1;
+
+	/** - tracing was disabled after this instruction. */
+	uint32_t disabled:1;
+
+	/** - tracing was enabled at this instruction. */
+	uint32_t enabled:1;
+
+	/** - tracing was resumed at this instruction.
+	 *
+	 *    In addition to tracing being enabled, it continues from the IP
+	 *    at which tracing had been disabled before.
+	 */
+	uint32_t resumed:1;
+
+	/** - normal execution flow was interrupted after this instruction. */
+	uint32_t interrupted:1;
+
+	/** - tracing resumed at this instruction after an overflow. */
+	uint32_t resynced:1;
+
+	/** - tracing was stopped after this instruction. */
+	uint32_t stopped:1;
+
+	/** - this instruction is truncated in its image section.
+	 *
+	 *    It starts in the image section identified by \@isid and continues
+	 *    in one or more other sections.
+	 */
+	uint32_t truncated:1;
+
+	/** The image section identifier for the section containing this
+	 * instruction.
+	 *
+	 * A value of zero means that the section did not have an identifier.
+	 * The section was not added via an image section cache or the memory
+	 * was read via the read memory callback.
+	 */
+	int isid;
+};
+
+
+/** Allocate an Intel PT instruction flow decoder.
+ *
+ * The decoder will work on the buffer defined in \@config, it shall contain
+ * raw trace data and remain valid for the lifetime of the decoder.
+ *
+ * The decoder needs to be synchronized before it can be used.
+ */
+extern pt_export struct pt_insn_decoder *
+pt_insn_alloc_decoder(const struct pt_config *config);
+
+/** Free an Intel PT instruction flow decoder.
+ *
+ * This will destroy the decoder's default image.
+ *
+ * The \@decoder must not be used after a successful return.
+ */
+extern pt_export void pt_insn_free_decoder(struct pt_insn_decoder *decoder);
+
+/** Synchronize an Intel PT instruction flow decoder.
+ *
+ * Search for the next synchronization point in forward or backward direction.
+ *
+ * If \@decoder has not been synchronized, yet, the search is started at the
+ * beginning of the trace buffer in case of forward synchronization and at the
+ * end of the trace buffer in case of backward synchronization.
+ *
+ * Returns zero or a positive value on success, a negative error code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if no further synchronization point is found.
+ * Returns -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_insn_sync_forward(struct pt_insn_decoder *decoder);
+extern pt_export int pt_insn_sync_backward(struct pt_insn_decoder *decoder);
+
+/** Manually synchronize an Intel PT instruction flow decoder.
+ *
+ * Synchronize \@decoder on the syncpoint at \@offset.  There must be a PSB
+ * packet at \@offset.
+ *
+ * Returns zero or a positive value on success, a negative error code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
+ * Returns -pte_eos if \@decoder reaches the end of its trace buffer.
+ * Returns -pte_invalid if \@decoder is NULL.
+ * Returns -pte_nosync if there is no syncpoint at \@offset.
+ */
+extern pt_export int pt_insn_sync_set(struct pt_insn_decoder *decoder,
+				      uint64_t offset);
+
+/** Get the current decoder position.
+ *
+ * Fills the current \@decoder position into \@offset.
+ *
+ * This is useful for reporting errors.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_insn_get_offset(struct pt_insn_decoder *decoder,
+					uint64_t *offset);
+
+/** Get the position of the last synchronization point.
+ *
+ * Fills the last synchronization position into \@offset.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_insn_get_sync_offset(struct pt_insn_decoder *decoder,
+					     uint64_t *offset);
+
+/** Get the current CR3
+ *
+ * Fills the current CR3 of \@decoder into \@cr3.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_insn_get_cr3(struct pt_insn_decoder *decoder,
+				     uint64_t *cr3);
+
+/** Get the traced image.
+ *
+ * The returned image may be modified as long as no decoder that uses this
+ * image is running.
+ *
+ * Returns a pointer to the traced image the decoder uses for reading memory.
+ * Returns NULL if \@decoder is NULL.
+ */
+extern pt_export struct pt_image *
+pt_insn_get_image(struct pt_insn_decoder *decoder);
+
+/** Set the traced image.
+ *
+ * Sets the image that \@decoder uses for reading memory to \@image.  If \@image
+ * is NULL, sets the image to \@decoder's default image.
+ *
+ * Only one image can be active at any time.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ * Return -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_insn_set_image(struct pt_insn_decoder *decoder,
+				       struct pt_image *image);
+
+/* Return a pointer to \@decoder's configuration.
+ *
+ * Returns a non-null pointer on success, NULL if \@decoder is NULL.
+ */
+extern pt_export const struct pt_config *
+pt_insn_get_config(const struct pt_insn_decoder *decoder);
+
+/** Return the current time.
+ *
+ * On success, provides the time at \@decoder's current position in \@time.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the time for that branch or event.
+ *
+ * The time is similar to what a rdtsc instruction would return.  Depending
+ * on the configuration, the time may not be fully accurate.  If TSC is not
+ * enabled, the time is relative to the last synchronization and can't be used
+ * to correlate with other TSC-based time sources.  In this case, -pte_no_time
+ * is returned and the relative time is provided in \@time.
+ *
+ * Some timing-related packets may need to be dropped (mostly due to missing
+ * calibration or incomplete configuration).  To get an idea about the quality
+ * of the estimated time, we record the number of dropped MTC and CYC packets.
+ *
+ * If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
+ * If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@time is NULL.
+ * Returns -pte_no_time if there has not been a TSC packet.
+ */
+extern pt_export int pt_insn_time(struct pt_insn_decoder *decoder,
+				  uint64_t *time, uint32_t *lost_mtc,
+				  uint32_t *lost_cyc);
+
+/** Return the current core bus ratio.
+ *
+ * On success, provides the core:bus ratio at \@decoder's current position
+ * in \@cbr.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the core:bus ratio for that branch or event.
+ *
+ * The ratio is defined as core cycles per bus clock cycle.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@cbr is NULL.
+ * Returns -pte_no_cbr if there has not been a CBR packet.
+ */
+extern pt_export int pt_insn_core_bus_ratio(struct pt_insn_decoder *decoder,
+					    uint32_t *cbr);
+
+/** Return the current address space identifier.
+ *
+ * On success, provides the current address space identifier in \@asid.
+ *
+ * The \@size argument must be set to sizeof(struct pt_asid).  At most \@size
+ * bytes will be copied and \@asid->size will be set to the actual size of the
+ * provided address space identifier.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@asid is NULL.
+ */
+extern pt_export int pt_insn_asid(const struct pt_insn_decoder *decoder,
+				  struct pt_asid *asid, size_t size);
+
+/** Determine the next instruction.
+ *
+ * On success, provides the next instruction in execution order in \@insn.
+ *
+ * The \@size argument must be set to sizeof(struct pt_insn).
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns pts_eos to indicate the end of the trace stream.  Subsequent calls
+ * to pt_insn_next() will continue to return pts_eos until trace is required
+ * to determine the next instruction.
+ *
+ * Returns -pte_bad_context if the decoder encountered an unexpected packet.
+ * Returns -pte_bad_opc if the decoder encountered unknown packets.
+ * Returns -pte_bad_packet if the decoder encountered unknown packet payloads.
+ * Returns -pte_bad_query if the decoder got out of sync.
+ * Returns -pte_eos if decoding reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@insn is NULL.
+ * Returns -pte_nomap if the memory at the instruction address can't be read.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_insn_next(struct pt_insn_decoder *decoder,
+				  struct pt_insn *insn, size_t size);
+
+
+
+/* Block decoder. */
+
+
+
+/** A block of instructions.
+ *
+ * Instructions in this block are executed sequentially but are not necessarily
+ * contiguous in memory.  Users are expected to follow direct branches.
+ */
+struct pt_block {
+	/** The IP of the first instruction in this block. */
+	uint64_t ip;
+
+	/** The IP of the last instruction in this block.
+	 *
+	 * This can be used for error-detection.
+	 */
+	uint64_t end_ip;
+
+	/** The image section that contains the instructions in this block.
+	 *
+	 * A value of zero means that the section did not have an identifier.
+	 * The section was not added via an image section cache or the memory
+	 * was read via the read memory callback.
+	 */
+	int isid;
+
+	/** The execution mode for all instructions in this block. */
+	enum pt_exec_mode mode;
+
+	/** The instruction class for the last instruction in this block.
+	 *
+	 * This field may be set to ptic_error to indicate that the instruction
+	 * class is not available.  The block decoder may choose to not provide
+	 * the instruction class in some cases for performance reasons.
+	 */
+	enum pt_insn_class iclass;
+
+	/** The number of instructions in this block. */
+	uint16_t ninsn;
+
+	/** The raw bytes of the last instruction in this block in case the
+	 * instruction does not fit entirely into this block's section.
+	 *
+	 * This field is only valid if \@truncated is set.
+	 */
+	uint8_t raw[pt_max_insn_size];
+
+	/** The size of the last instruction in this block in bytes.
+	 *
+	 * This field is only valid if \@truncated is set.
+	 */
+	uint8_t size;
+
+	/** A collection of flags giving additional information about the
+	 * instructions in this block.
+	 *
+	 * - all instructions in this block were executed speculatively.
+	 */
+	uint32_t speculative:1;
+
+	/** - speculative execution was aborted after this block. */
+	uint32_t aborted:1;
+
+	/** - speculative execution was committed after this block. */
+	uint32_t committed:1;
+
+	/** - tracing was disabled after this block. */
+	uint32_t disabled:1;
+
+	/** - tracing was enabled at this block. */
+	uint32_t enabled:1;
+
+	/** - tracing was resumed at this block.
+	 *
+	 *    In addition to tracing being enabled, it continues from the IP
+	 *    at which tracing had been disabled before.
+	 *
+	 *    If tracing was disabled at a call instruction, we assume that
+	 *    tracing will be re-enabled after returning from the call at the
+	 *    instruction following the call instruction.
+	 */
+	uint32_t resumed:1;
+
+	/** - normal execution flow was interrupted after this block. */
+	uint32_t interrupted:1;
+
+	/** - tracing resumed at this block after an overflow. */
+	uint32_t resynced:1;
+
+	/** - tracing was stopped after this block. */
+	uint32_t stopped:1;
+
+	/** - the last instruction in this block is truncated.
+	 *
+	 *    It starts in this block's section but continues in one or more
+	 *    other sections depending on how fragmented the memory image is.
+	 *
+	 *    The raw bytes for the last instruction are provided in \@raw and
+	 *    its size in \@size in this case.
+	 */
+	uint32_t truncated:1;
+};
+
+/** Allocate an Intel PT block decoder.
+ *
+ * The decoder will work on the buffer defined in \@config, it shall contain
+ * raw trace data and remain valid for the lifetime of the decoder.
+ *
+ * The decoder needs to be synchronized before it can be used.
+ */
+extern pt_export struct pt_block_decoder *
+pt_blk_alloc_decoder(const struct pt_config *config);
+
+/** Free an Intel PT block decoder.
+ *
+ * This will destroy the decoder's default image.
+ *
+ * The \@decoder must not be used after a successful return.
+ */
+extern pt_export void pt_blk_free_decoder(struct pt_block_decoder *decoder);
+
+/** Synchronize an Intel PT block decoder.
+ *
+ * Search for the next synchronization point in forward or backward direction.
+ *
+ * If \@decoder has not been synchronized, yet, the search is started at the
+ * beginning of the trace buffer in case of forward synchronization and at the
+ * end of the trace buffer in case of backward synchronization.
+ *
+ * Returns zero or a positive value on success, a negative error code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if no further synchronization point is found.
+ * Returns -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_blk_sync_forward(struct pt_block_decoder *decoder);
+extern pt_export int pt_blk_sync_backward(struct pt_block_decoder *decoder);
+
+/** Manually synchronize an Intel PT block decoder.
+ *
+ * Synchronize \@decoder on the syncpoint at \@offset.  There must be a PSB
+ * packet at \@offset.
+ *
+ * Returns zero or a positive value on success, a negative error code otherwise.
+ *
+ * Returns -pte_bad_opc if an unknown packet is encountered.
+ * Returns -pte_bad_packet if an unknown packet payload is encountered.
+ * Returns -pte_eos if \@offset lies outside of \@decoder's trace buffer.
+ * Returns -pte_eos if \@decoder reaches the end of its trace buffer.
+ * Returns -pte_invalid if \@decoder is NULL.
+ * Returns -pte_nosync if there is no syncpoint at \@offset.
+ */
+extern pt_export int pt_blk_sync_set(struct pt_block_decoder *decoder,
+				     uint64_t offset);
+
+/** Get the current decoder position.
+ *
+ * Fills the current \@decoder position into \@offset.
+ *
+ * This is useful for reporting errors.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_blk_get_offset(struct pt_block_decoder *decoder,
+				       uint64_t *offset);
+
+/** Get the position of the last synchronization point.
+ *
+ * Fills the last synchronization position into \@offset.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@offset is NULL.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_blk_get_sync_offset(struct pt_block_decoder *decoder,
+					    uint64_t *offset);
+
+/** Get the traced image.
+ *
+ * The returned image may be modified as long as \@decoder is not running.
+ *
+ * Returns a pointer to the traced image \@decoder uses for reading memory.
+ * Returns NULL if \@decoder is NULL.
+ */
+extern pt_export struct pt_image *
+pt_blk_get_image(struct pt_block_decoder *decoder);
+
+/** Set the traced image.
+ *
+ * Sets the image that \@decoder uses for reading memory to \@image.  If \@image
+ * is NULL, sets the image to \@decoder's default image.
+ *
+ * Only one image can be active at any time.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ * Return -pte_invalid if \@decoder is NULL.
+ */
+extern pt_export int pt_blk_set_image(struct pt_block_decoder *decoder,
+				      struct pt_image *image);
+
+/* Return a pointer to \@decoder's configuration.
+ *
+ * Returns a non-null pointer on success, NULL if \@decoder is NULL.
+ */
+extern pt_export const struct pt_config *
+pt_blk_get_config(const struct pt_block_decoder *decoder);
+
+/** Return the current time.
+ *
+ * On success, provides the time at \@decoder's current position in \@time.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the time for that branch or event.
+ *
+ * The time is similar to what a rdtsc instruction would return.  Depending
+ * on the configuration, the time may not be fully accurate.  If TSC is not
+ * enabled, the time is relative to the last synchronization and can't be used
+ * to correlate with other TSC-based time sources.  In this case, -pte_no_time
+ * is returned and the relative time is provided in \@time.
+ *
+ * Some timing-related packets may need to be dropped (mostly due to missing
+ * calibration or incomplete configuration).  To get an idea about the quality
+ * of the estimated time, we record the number of dropped MTC and CYC packets.
+ *
+ * If \@lost_mtc is not NULL, set it to the number of lost MTC packets.
+ * If \@lost_cyc is not NULL, set it to the number of lost CYC packets.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@time is NULL.
+ * Returns -pte_no_time if there has not been a TSC packet.
+ */
+extern pt_export int pt_blk_time(struct pt_block_decoder *decoder,
+				 uint64_t *time, uint32_t *lost_mtc,
+				 uint32_t *lost_cyc);
+
+/** Return the current core bus ratio.
+ *
+ * On success, provides the core:bus ratio at \@decoder's current position
+ * in \@cbr.
+ * Since \@decoder is reading ahead until the next indirect branch or event,
+ * the value matches the core:bus ratio for that branch or event.
+ *
+ * The ratio is defined as core cycles per bus clock cycle.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@cbr is NULL.
+ * Returns -pte_no_cbr if there has not been a CBR packet.
+ */
+extern pt_export int pt_blk_core_bus_ratio(struct pt_block_decoder *decoder,
+					   uint32_t *cbr);
+
+/** Return the current address space identifier.
+ *
+ * On success, provides the current address space identifier in \@asid.
+ *
+ * The \@size argument must be set to sizeof(struct pt_asid).  At most \@size
+ * bytes will be copied and \@asid->size will be set to the actual size of the
+ * provided address space identifier.
+ *
+ * Returns zero on success, a negative error code otherwise.
+ *
+ * Returns -pte_invalid if \@decoder or \@asid is NULL.
+ */
+extern pt_export int pt_blk_asid(const struct pt_block_decoder *decoder,
+				 struct pt_asid *asid, size_t size);
+
+/** Determine the next block of instructions.
+ *
+ * On success, provides the next block of instructions in execution order in
+ * \@block.
+ *
+ * The \@size argument must be set to sizeof(struct pt_block).
+ *
+ * Returns a non-negative pt_status_flag bit-vector on success, a negative error
+ * code otherwise.
+ *
+ * Returns pts_eos to indicate the end of the trace stream.  Subsequent calls
+ * to pt_block_next() will continue to return pts_eos until trace is required
+ * to determine the next instruction.
+ *
+ * Returns -pte_bad_context if the decoder encountered an unexpected packet.
+ * Returns -pte_bad_opc if the decoder encountered unknown packets.
+ * Returns -pte_bad_packet if the decoder encountered unknown packet payloads.
+ * Returns -pte_bad_query if the decoder got out of sync.
+ * Returns -pte_eos if decoding reached the end of the Intel PT buffer.
+ * Returns -pte_invalid if \@decoder or \@block is NULL.
+ * Returns -pte_nomap if the memory at the instruction address can't be read.
+ * Returns -pte_nosync if \@decoder is out of sync.
+ */
+extern pt_export int pt_blk_next(struct pt_block_decoder *decoder,
+				 struct pt_block *block, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INTEL_PT_H */