blob: 22410e230a66e8d6bdaeb7bbf3d027d680736629 [file] [log] [blame]
// Copyright 2019 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.
library fuchsia.hardware.cpu.insntrace;
using zx;
const uint16 API_VERSION = 0;
/// The maximum number of traces that can be collected at once.
/// A "trace" is the instruction stream for one entity, cpu or thread.
const uint16 MAX_NUM_TRACES = 64;
/// The maximum number of supported address ranges.
const uint16 MAX_NUM_ADDR_RANGES = 2;
/// Tracing modes
enum Mode : uint8 {
// Trace each cpu, regardless of what's running on it.
CPU = 0;
// Trace specific threads.
THREAD = 1;
};
/// The allocation configuration of a trace.
struct Allocation {
Mode 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. This value can be at most
// MAX_NUM_TRACES.
uint16 num_traces;
};
/// An address range, as [start,end].
struct AddressRange {
uint64 start;
uint64 end;
};
/// A buffer's configuration.
struct BufferConfig {
/// A "buffer" is made up of `num_chunks` chunks with each chunk having
/// size `1<<chunk_order` pages.
uint32 num_chunks;
/// log2 of the number of pages
uint32 chunk_order;
/// If true then use circular buffering.
bool is_circular;
/// The value of the control register.
uint64 ctl;
/// If non-zero then the address space of the instruction must match in
/// order for the instruction to be traced. On x86 architectures the
/// address space is specified by CR3.
uint64 address_space_match;
/// If non-zero, tracing is restricted to these address ranges.
/// TODO(dje): There's only two, and vectors don't currently work here,
/// so spell these out individually
AddressRange address_range_0;
AddressRange address_range_1;
};
/// A buffer's runtime state.
struct BufferState {
/// This is the offset in the buffer where tracing stopped (treating all
/// buffers as one large one). If using a circular buffer then all of the
/// buffer may contain data, there's no current way to know if tracing
/// wrapped without scanning records.
uint64 capture_end;
};
alias BufferDescriptor = uint32;
protocol Controller {
/// Initialize the trace.
/// This does not include allocating space for the trace buffers, that is
/// done later by `AllocateBuffer()`.
Initialize(Allocation allocation) -> () error zx.status;
/// Free all trace buffers and any other resources allocated for the trace.
/// This is also done when the connection is closed (as well as stopping
/// the trace).
/// May be called multiple times.
/// This can only fail when tracing in THREAD mode where tracing is
/// terminated differently, in which case the error is `ZX_ERR_BAD_STATE`.
// TODO(fxbug.dev/30840): Support terminating the trace in THREAD mode.
Terminate() -> () error zx.status;
/// Return the trace allocation configuration.
GetAllocation() -> (Allocation? allocation);
/// Allocate a trace buffer.
/// When tracing cpus, buffers are auto-assigned to cpus: the resulting
/// trace buffer descriptor is the number of the cpu using the buffer.
AllocateBuffer(BufferConfig config) -> (BufferDescriptor descriptor) error zx.status;
/// Assign a buffer to a thread.
AssignThreadBuffer(BufferDescriptor descriptor, zx.handle:THREAD thread) -> () error zx.status;
/// Release a previously assigned buffer from a thread.
ReleaseThreadBuffer(BufferDescriptor descriptor, zx.handle:THREAD thread) -> () error zx.status;
/// Fetch a buffer's configuration.
GetBufferConfig(BufferDescriptor descriptor) -> (BufferConfig? config);
/// Fetch runtime information about a buffer.
GetBufferState(BufferDescriptor descriptor) -> (BufferState? state);
/// Fetch the handle of a chunk of a trace buffer.
GetChunkHandle(BufferDescriptor descriptor, uint32 chunk_num) -> (zx.handle:VMO? buffer);
/// Free a previously allocated trace buffer.
FreeBuffer(BufferDescriptor descriptor) -> ();
/// Start tracing.
/// Must be called after `Initialize()` + `AllocateBuffer()`,
/// with tracing off.
Start() -> ();
/// Stop tracing.
/// May be called any time after `Allocate()` has been called and before
/// `Free()`. If called at other times the call is ignored.
/// May be called multiple times.
// TODO(fxbug.dev/30840): Support terminating the trace in THREAD mode.
Stop() -> ();
};