blob: e25c308bf2ed7154d5891181b690e3d2f03095ce [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.perfmon.cpu;
using zx;
// The type of the `rate` field of EventConfig.
alias EventRate = uint32;
// Trace buffer space is expensive, we want to keep records small.
// Having more than 64K different events for any one arch is unlikely
// so we use 16 bits for the event id.
// To help each arch manage the plethora of different events, the event id
// is split it two parts: 5 bit event group, and 11 bit event within that
// group.
// An event id of zero is defined to be unused.
alias EventId = uint16;
const uint16 API_VERSION = 0;
/// The maximum number of events we support simultaneously.
/// Typically the h/w supports less than this, e.g., 7 or so.
const uint16 MAX_NUM_EVENTS = 32;
/// Bits for Properties.flags field.
bits PropertyFlags : uint64 {
/// The architecture supports LBR records (Last Branch Records).
HAS_LAST_BRANCH = 0x1;
};
/// The properties of this system.
struct Properties {
/// S/W API version = `API_VERSION`.
uint16 api_version;
/// The H/W Performance Monitor version.
/// This is the version defined by the architecture.
uint16 pm_version;
/// The maximum number of events that can be simultaneously supported.
/// The combination of events that can be simultaneously supported is
/// architecture/model specific.
uint16 max_num_events;
/// The maximum number of fixed events that can be simultaneously
/// supported, and their maximum width.
/// These values are for informational/display purposes.
uint16 max_num_fixed_events;
uint16 max_fixed_counter_width;
/// The maximum number of programmable events that can be simultaneously
/// supported, and their maximum width.
/// These values are for informational/display purposes.
uint16 max_num_programmable_events;
uint16 max_programmable_counter_width;
/// The maximum number of misc events that can be simultaneously
/// supported, and their maximum width.
/// These values are for informational/display purposes.
uint16 max_num_misc_events;
uint16 max_misc_counter_width;
/// Various flags.
PropertyFlags flags;
};
/// Bits for EventConfig.flags field.
// TODO(dje): hypervisor, host/guest os/user
bits EventConfigFlags : uint32 {
/// Collect data when running in kernel mode.
COLLECT_OS = 0x1;
/// Collect data when running in userspace mode.
COLLECT_USER = 0x2;
/// Collect aspace+pc values.
COLLECT_PC = 0x4;
/// If set for an event then the event is used as the "timebase": data
/// for events with a zero rate is collected when data for the timebase
/// event is collected.
/// It is an error to have this set and have the event's rate be zero.
/// At most one event may be the timebase event.
IS_TIMEBASE = 0x8;
/// Collect the available set of last branches.
/// Branch data is emitted as LastBranch records.
/// This is only available when the underlying system supports it.
// TODO(dje): Provide knob to specify how many branches.
COLLECT_LAST_BRANCH = 0x10;
};
struct EventConfig {
/// Event to collect data for.
/// The values are architecture specific ids.
/// Each event may appear at most once.
EventId event;
/// Sampling rate.
/// - If rate is non-zero then when the event gets this many hits data is
/// collected (e.g., pc, time).
/// The rate can be non-zero for counting based events only.
/// - If rate is zero then:
/// If there is a timebase event then data for this event is collected
/// when data for the timebase event is collected.
/// Otherwise data for the event is collected once, when tracing stops.
EventRate rate;
/// Flags for the event.
EventConfigFlags flags;
};
/// Passed to `StageConfig()` to select the data to be collected.
struct Config {
/// Events to collect data for.
array<EventConfig>:MAX_NUM_EVENTS events;
};
/// The allocation configuration for a data collection run.
/// This is generally the first call to allocate resources for a trace,
/// "trace" is used generically here: == "data collection run".
struct Allocation {
/// The number of buffers to allocate for trace data.
/// This must be #cpus for now.
uint32 num_buffers;
/// The size of each buffer in 4K pages.
/// Each cpu gets same buffer size.
uint32 buffer_size_in_pages;
};
protocol Controller {
/// Fetch the performance monitor properties of the system.
GetProperties() -> (Properties properties);
/// Create a trace, allocating the needed trace buffers and other resources.
/// "other resources" is basically a catch-all for other things that will
/// be needed. This does not include reserving the events, that is done
/// later by `StageConfig()`.
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.
/// Tracing is first stopped if not already stopped.
/// May be called multiple times.
Terminate() -> ();
/// Return the trace allocation configuration, if there is one.
GetAllocation() -> (Allocation? allocation);
/// Stage performance monitor specification for a cpu.
/// Must be called with data collection off and after `Initialize()`.
/// Note: This doesn't actually configure the h/w, this just stages
/// the values for subsequent use by `Start()`.
StageConfig(Config config) -> () error zx.status;
/// Fetch performance monitor specification for a cpu, if it exists.
/// Must be called with data collection off and after `StageConfig()`.
GetConfig() -> (Config? config);
/// Return a handle of a trace buffer, if it exists, and if `descriptor`
/// is valid.
/// `descriptor` is (0, 1, 2, ..., `num_buffers`-1)
GetBufferHandle(uint32 descriptor) -> (zx.handle:VMO? vmo);
/// Turn on data collection.
/// Must be called after `Initialize()` + `StageConfig()` and with data
/// collection off.
Start() -> () error zx.status;
/// Turn off data collection.
/// May be called any time after `Initialize()` has been called and before
/// `Terminate()`. If called at other times the call is ignored.
/// May be called multiple times.
Stop() -> ();
};