| // 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() -> (); |
| }; |