/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

syntax = "proto2";

package perfetto.protos;

message PerfEvents {
  // The primary event to count. If recording multiple events, this
  // counter is the "group leader".
  // Commented from the perspective of its use in |PerfEventConfig|.
  // Next id: 12
  message Timebase {
    // How often to snapshot the counter, along with any follower events and
    // any additional sampled data such as callstacks.
    //
    // This choice also controls how the readings are taken:
    // * With |frequency| or |period|, samples are taken by the kernel
    //   into a ring buffer. Analogous to `perf record`.
    // * With |poll_period_ms|, the userspace periodically snapshots
    //   the counters using the read syscall. Analogous to `perf stat -I`.
    // Prefer the sampling options unless you're recording PMUs whose
    // perf drivers only support the reading mode.
    //
    // If unset, an implementation-defined sampling default is used.
    oneof interval {
      // Per-cpu sampling frequency in Hz, as requested from the kernel. Not the
      // same as 1/period.
      // Details: the actual sampling will still be based on a period, but the
      // kernel will dynamically adjust it based on the observed event rate, to
      // approximate this frequency. Works best with steady-rate events like
      // timers.
      // Not guaranteed to be honored as the kernel can throttle the sampling
      // rate if it's too high.
      uint64 frequency = 2;

      // Per-cpu sampling will occur every |period| counts of |event|.
      // Prefer |frequency| by default, as it's easier to oversample with a
      // fixed period.
      // Not guaranteed to be honored as the kernel can throttle the sampling
      // rate if it's too high.
      uint64 period = 1;

      // Per-cpu values are read by the userspace every interval. If using this
      // mode, only follower events are supported. Options such as
      // |PerfEventConfig.CallstackSampling| are incompatible.
      // The period can't be guaranteed to be exact since the readings are taken
      // by userspace.
      uint32 poll_period_ms = 6;
    }

    // Counting event to use as the timebase.
    // If unset, implies the CPU timer (SW_CPU_CLOCK) as the event,
    // which is what you usually want.
    oneof event {
      Counter counter = 4;
      Tracepoint tracepoint = 3;
      RawEvent raw_event = 5;
    }

    // If set, samples will be timestamped with the given clock.
    // If unset, the clock is chosen by the implementation.
    // For software events, prefer PERF_CLOCK_BOOTTIME. However it cannot be
    // used for hardware events (due to interrupt safety), for which the
    // recommendation is to use one of the monotonic clocks.
    optional PerfClock timestamp_clock = 11;

    // Optional arbitrary name for the event, to identify it in the parsed
    // trace. Does *not* affect the profiling itself. If unset, the trace
    // parser will choose a suitable name.
    optional string name = 10;
  }

  // Builtin counter names from the uapi header. Commented with their perf tool
  // aliases.
  // TODO(rsavitski): consider generating enums for cache events (should be
  // finite), and generally make this list as extensive as possible. Excluding
  // things like dynamic PMUs since those don't fit into a static enum.
  // Next id: 21
  enum Counter {
    UNKNOWN_COUNTER = 0;

    // cpu-clock
    SW_CPU_CLOCK = 1;
    // page-faults, faults
    SW_PAGE_FAULTS = 2;
    // task-clock
    SW_TASK_CLOCK = 3;
    // context-switches, cs
    SW_CONTEXT_SWITCHES = 4;
    // cpu-migrations, migrations
    SW_CPU_MIGRATIONS = 5;
    // minor-faults
    SW_PAGE_FAULTS_MIN = 6;
    // major-faults
    SW_PAGE_FAULTS_MAJ = 7;
    // alignment-faults
    SW_ALIGNMENT_FAULTS = 8;
    // emulation-faults
    SW_EMULATION_FAULTS = 9;
    // dummy
    SW_DUMMY = 20;

    // cpu-cycles, cycles
    HW_CPU_CYCLES = 10;
    // instructions
    HW_INSTRUCTIONS = 11;
    // cache-references
    HW_CACHE_REFERENCES = 12;
    // cache-misses
    HW_CACHE_MISSES = 13;
    // branch-instructions, branches
    HW_BRANCH_INSTRUCTIONS = 14;
    // branch-misses
    HW_BRANCH_MISSES = 15;
    // bus-cycles
    HW_BUS_CYCLES = 16;
    // stalled-cycles-frontend, idle-cycles-frontend
    HW_STALLED_CYCLES_FRONTEND = 17;
    // stalled-cycles-backend, idle-cycles-backend
    HW_STALLED_CYCLES_BACKEND = 18;
    // ref-cycles
    HW_REF_CPU_CYCLES = 19;
  }

  message Tracepoint {
    // Group and name for the tracepoint, acceptable forms:
    // * "sched/sched_switch"
    // * "sched:sched_switch"
    optional string name = 1;

    // Optional field-level filter for the tracepoint. Only events matching this
    // filter will be counted (and therefore contribute to the sampling period).
    // Example: "prev_pid >= 42 && next_pid == 0".
    // For full syntax, see kernel documentation on "Event filtering":
    // https://www.kernel.org/doc/Documentation/trace/events.txt
    optional string filter = 2;
  }

  // Syscall-level description of the event, propagated to the perf_event_attr
  // struct. Primarily for local use-cases, since the event availability and
  // encoding is hardware-specific.
  message RawEvent {
    optional uint32 type = 1;
    optional uint64 config = 2;
    optional uint64 config1 = 3;
    optional uint64 config2 = 4;
  }

  // Subset of clocks that is supported by perf timestamping.
  // CLOCK_TAI is excluded since it's not expected to be used in practice, but
  // would require additions to the trace clock synchronisation logic.
  enum PerfClock {
    UNKNOWN_PERF_CLOCK = 0;
    PERF_CLOCK_REALTIME = 1;
    PERF_CLOCK_MONOTONIC = 2;
    PERF_CLOCK_MONOTONIC_RAW = 3;
    PERF_CLOCK_BOOTTIME = 4;
  }
}

// Additional events associated with a leader.
// Configuration is similar to Timebase event. Because data acquisition is
// driven by the leader there is no option to configure the clock or the
// frequency.
message FollowerEvent {
  oneof event {
    PerfEvents.Counter counter = 1;
    PerfEvents.Tracepoint tracepoint = 2;
    PerfEvents.RawEvent raw_event = 3;
  }
  optional string name = 4;
}
