blob: 25eb3868c6d87bb6d2b374c052b672109da51e86 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_ZIRCON_INTERNAL_DEVICE_CPU_TRACE_INTEL_PT_H_
#define LIB_ZIRCON_INTERNAL_DEVICE_CPU_TRACE_INTEL_PT_H_
#include <sys/types.h>
#ifdef __Fuchsia__
#include <zircon/compiler.h>
#include <zircon/types.h>
#endif
__BEGIN_CDECLS
#if !defined(__x86_64__)
#error "unsupported architecture"
#endif
#define IPT_MSR_BITS(len, shift) (((1ULL << (len)) - 1) << (shift))
// Bits in the IA32_RTIT_CTL MSR.
// These bits are writable by the user with ioctl_insntrace_set_ctl_config.
// The driver will override a setting if it's unsafe (e.g., causes #gpf).
#define IPT_CTL_CYC_EN_SHIFT (1)
#define IPT_CTL_CYC_EN_LEN (1)
#define IPT_CTL_CYC_EN_MASK IPT_MSR_BITS(IPT_CTL_CYC_EN_LEN, IPT_CTL_CYC_EN_SHIFT)
#define IPT_CTL_OS_ALLOWED_SHIFT (2)
#define IPT_CTL_OS_ALLOWED_LEN (1)
#define IPT_CTL_OS_ALLOWED_MASK IPT_MSR_BITS(IPT_CTL_OS_ALLOWED_LEN, IPT_CTL_OS_ALLOWED_SHIFT)
#define IPT_CTL_USER_ALLOWED_SHIFT (3)
#define IPT_CTL_USER_ALLOWED_LEN (1)
#define IPT_CTL_USER_ALLOWED_MASK IPT_MSR_BITS(IPT_CTL_USER_ALLOWED_LEN, IPT_CTL_USER_ALLOWED_SHIFT)
#define IPT_CTL_POWER_EVENT_EN_SHIFT (4)
#define IPT_CTL_POWER_EVENT_EN_LEN (1)
#define IPT_CTL_POWER_EVENT_EN_MASK \
IPT_MSR_BITS(IPT_CTL_POWER_EVENT_EN_LEN, IPT_CTL_POWER_EVENT_EN_SHIFT)
#define IPT_CTL_FUP_ON_PTW_SHIFT (5)
#define IPT_CTL_FUP_ON_PTW_LEN (1)
#define IPT_CTL_FUP_ON_PTW_MASK IPT_MSR_BITS(IPT_CTL_FUP_ON_PTW_LEN, IPT_CTL_FUP_ON_PTW_SHIFT)
#define IPT_CTL_CR3_FILTER_SHIFT (7)
#define IPT_CTL_CR3_FILTER_LEN (1)
#define IPT_CTL_CR3_FILTER_MASK IPT_MSR_BITS(IPT_CTL_CR3_FILTER_LEN, IPT_CTL_CR3_FILTER_SHIFT)
#define IPT_CTL_MTC_EN_SHIFT (9)
#define IPT_CTL_MTC_EN_LEN (1)
#define IPT_CTL_MTC_EN_MASK IPT_MSR_BITS(IPT_CTL_MTC_EN_LEN, IPT_CTL_MTC_EN_SHIFT)
#define IPT_CTL_TSC_EN_SHIFT (10)
#define IPT_CTL_TSC_EN_LEN (1)
#define IPT_CTL_TSC_EN_MASK IPT_MSR_BITS(IPT_CTL_TSC_EN_LEN, IPT_CTL_TSC_EN_SHIFT)
#define IPT_CTL_DIS_RETC_SHIFT (11)
#define IPT_CTL_DIS_RETC_LEN (1)
#define IPT_CTL_DIS_RETC_MASK IPT_MSR_BITS(IPT_CTL_DIS_RETC_LEN, IPT_CTL_DIS_RETC_SHIFT)
#define IPT_CTL_PTW_EN_SHIFT (12)
#define IPT_CTL_PTW_EN_LEN (1)
#define IPT_CTL_PTW_EN_MASK IPT_MSR_BITS(IPT_CTL_PTW_EN_LEN, IPT_CTL_PTW_EN_SHIFT)
#define IPT_CTL_BRANCH_EN_SHIFT (13)
#define IPT_CTL_BRANCH_EN_LEN (1)
#define IPT_CTL_BRANCH_EN_MASK IPT_MSR_BITS(IPT_CTL_BRANCH_EN_LEN, IPT_CTL_BRANCH_EN_SHIFT)
#define IPT_CTL_MTC_FREQ_SHIFT (14)
#define IPT_CTL_MTC_FREQ_LEN (4)
#define IPT_CTL_MTC_FREQ_MASK IPT_MSR_BITS(IPT_CTL_MTC_FREQ_LEN, IPT_CTL_MTC_FREQ_SHIFT)
#define IPT_CTL_CYC_THRESH_SHIFT (19)
#define IPT_CTL_CYC_THRESH_LEN (4)
#define IPT_CTL_CYC_THRESH_MASK IPT_MSR_BITS(IPT_CTL_CYC_THRESH_LEN, IPT_CTL_CYC_THRESH_SHIFT)
#define IPT_CTL_PSB_FREQ_SHIFT (24)
#define IPT_CTL_PSB_FREQ_LEN (4)
#define IPT_CTL_PSB_FREQ_MASK IPT_MSR_BITS(IPT_CTL_PSB_FREQ_LEN, IPT_CTL_PSB_FREQ_SHIFT)
#define IPT_CTL_ADDR0_SHIFT (32)
#define IPT_CTL_ADDR_LEN (4)
#define IPT_CTL_ADDR0_MASK IPT_MSR_BITS(IPT_CTL_ADDR_LEN, IPT_CTL_ADDR0_SHIFT)
#define IPT_CTL_ADDR1_SHIFT (36)
#define IPT_CTL_ADDR1_MASK IPT_MSR_BITS(IPT_CTL_ADDR_LEN, IPT_CTL_ADDR1_SHIFT)
#define IPT_CTL_ADDR2_SHIFT (40)
#define IPT_CTL_ADDR2_MASK IPT_MSR_BITS(IPT_CTL_ADDR_LEN, IPT_CTL_ADDR2_SHIFT)
#define IPT_CTL_ADDR3_SHIFT (44)
#define IPT_CTL_ADDR3_MASK IPT_MSR_BITS(IPT_CTL_ADDR_LEN, IPT_CTL_ADDR3_SHIFT)
// Other bits in IA32_RTIT_CTL MSR, not writable with ioctl_insntrace_set_ctl_config.
#define IPT_CTL_TRACE_EN_SHIFT (0)
#define IPT_CTL_TRACE_EN_LEN (1)
#define IPT_CTL_TRACE_EN_MASK IPT_MSR_BITS(IPT_CTL_TRACE_EN_LEN, IPT_CTL_TRACE_EN_SHIFT)
#define IPT_CTL_FABRIC_EN_SHIFT (6)
#define IPT_CTL_FABRIC_EN_LEN (1)
#define IPT_CTL_FABRIC_EN_MASK IPT_MSR_BITS(IPT_CTL_FABRIC_EN_LEN, IPT_CTL_FABRIC_EN_SHIFT)
#define IPT_CTL_TOPA_SHIFT (8)
#define IPT_CTL_TOPA_LEN (1)
#define IPT_CTL_TOPA_MASK IPT_MSR_BITS(IPT_CTL_TOPA_LEN, IPT_CTL_TOPA_SHIFT)
// Masks for reading IA32_RTIT_STATUS.
#define IPT_STATUS_FILTER_EN_SHIFT (0)
#define IPT_STATUS_FILTER_EN_LEN (1)
#define IPT_STATUS_FILTER_EN_MASK IPT_MSR_BITS(IPT_STATUS_FILTER_EN_LEN, IPT_STATUS_FILTER_EN_SHIFT)
#define IPT_STATUS_CONTEXT_EN_SHIFT (1)
#define IPT_STATUS_CONTEXT_EN_LEN (1)
#define IPT_STATUS_CONTEXT_EN_MASK \
IPT_MSR_BITS(IPT_STATUS_CONTEXT_EN_LEN, IPT_STATUS_CONTEXT_EN_SHIFT)
#define IPT_STATUS_TRIGGER_EN_SHIFT (2)
#define IPT_STATUS_TRIGGER_EN_LEN (1)
#define IPT_STATUS_TRIGGER_EN_MASK \
IPT_MSR_BITS(IPT_STATUS_TRIGGER_EN_LEN, IPT_STATUS_TRIGGER_EN_SHIFT)
#define IPT_STATUS_ERROR_SHIFT (4)
#define IPT_STATUS_ERROR_LEN (1)
#define IPT_STATUS_ERROR_MASK IPT_MSR_BITS(IPT_STATUS_ERROR_LEN, IPT_STATUS_ERROR_SHIFT)
#define IPT_STATUS_STOPPED_SHIFT (5)
#define IPT_STATUS_STOPPED_LEN (1)
#define IPT_STATUS_STOPPED_MASK IPT_MSR_BITS(IPT_STATUS_STOPPED_LEN, IPT_STATUS_STOPPED_SHIFT)
#define IPT_STATUS_PACKET_BYTE_COUNT_SHIFT (32)
#define IPT_STATUS_PACKET_BYTE_COUNT_LEN (17)
#define IPT_STATUS_PACKET_BYTE_COUNT_MASK \
IPT_MSR_BITS(IPT_STATUS_IPT_STATUS_PACKET_BYTE_COUNT_LEN_LEN, \
IPT_STATUS_IPT_STATUS_PACKET_BYTE_COUNT_LEN_SHIFT)
// Maximum number of address ranges that h/w may support.
// No chip supports more than 2 at the moment.
// Plus the XSAVES docs don't define more than 2 (see Intel Vol 3 section
// 36.3.5.2 "Trace Configuration Context Switch using XSAVES/XRSTORS").
#define IPT_MAX_NUM_ADDR_RANGES 2
// Valid ToPA entry sizes.
#define IPT_TOPA_MIN_SHIFT 12
#define IPT_TOPA_MAX_SHIFT 27
// These bits are for internal use
// Macros for building entries for the Table of Physical Addresses
#define IPT_TOPA_ENTRY_PHYS_ADDR(x) ((uint64_t)(x) & ~((1ULL << 12) - 1))
#define IPT_TOPA_ENTRY_SIZE(size_log2) ((uint64_t)((size_log2)-12) << 6)
#define IPT_TOPA_ENTRY_STOP (1ULL << 4)
#define IPT_TOPA_ENTRY_INT (1ULL << 2)
#define IPT_TOPA_ENTRY_END (1ULL << 0)
// Macros for extracting info from ToPA entries
#define IPT_TOPA_ENTRY_EXTRACT_PHYS_ADDR(e) ((zx_paddr_t)((e) & ~((1ULL << 12) - 1)))
#define IPT_TOPA_ENTRY_EXTRACT_SIZE(e) ((uint)((((e) >> 6) & 0xf) + 12))
// Arbitarily picked constants for ourselves.
// ToPA tables are 16KB in size (technically can be up to 256MB).
// A 16KB table provides 2047 non-END entries, so at the
// minimum can provide a capture buffer of just under 8MB.
#define IPT_TOPA_MAX_TABLE_ENTRIES 2048
// The maximum value for |zx_insntrace_trace_config_t.num_traces|.
#define IPT_MAX_NUM_TRACES 64
// Two "modes" of tracing are supported:
typedef enum {
// trace each cpu, regardless of what's running on it
IPT_MODE_CPU,
// trace specific threads
IPT_MODE_THREAD
} zx_insntrace_trace_mode_t;
// A trace configuration.
// This is used to pass data from the driver to the kernel.
typedef struct {
// One of IPT_MODE_{CPUS,THREADS}.
uint32_t mode;
// The number of traces to create.
// In CPU mode this must be zx_system_get_num_cpus().
// In THREAD mode this is the maximum number of threads for which traces
// will be collected. Buffer space is allocated on demand, but the
// underlying data structure has a maximum. The value can be at most
// IPT_MAX_NUM_TRACES.
uint32_t num_traces;
} zx_insntrace_trace_config_t;
// An integer identifying a particular buffer.
typedef uint32_t zx_insntrace_buffer_descriptor_t;
// The PT register set.
// This is used to pass data from the driver to the kernel.
// This is accessed via mtrace, but basically it's a regset.
typedef struct {
uint64_t ctl;
uint64_t status;
uint64_t output_base;
uint64_t output_mask_ptrs;
uint64_t cr3_match;
struct {
uint64_t a, b;
} addr_ranges[IPT_MAX_NUM_ADDR_RANGES];
} zx_x86_pt_regs_t;
__END_CDECLS
#endif // LIB_ZIRCON_INTERNAL_DEVICE_CPU_TRACE_INTEL_PT_H_