/*
 * Copyright (C) 2018 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;

// Per-CPU kernel buffer stats for the ftrace data source gathered from
// /sys/kernel/tracing/per_cpu/cpuX/stats.
message FtraceCpuStats {
  // CPU index.
  optional uint64 cpu = 1;

  // Number of entries currently in the kernel buffer.
  optional uint64 entries = 2;

  // Number of events lost in kernel buffers due to overwriting of old events
  // before userspace had a chance to drain them. Valid if the buffer is in
  // "overwrite" mode, otherwise see |dropped_events|.
  optional uint64 overrun = 3;

  // This should always be zero. If not the buffer size is way too small or
  // something went wrong with the tracer. Quoting the kernel: "number of
  // commits failing due to the buffer wrapping around while there are
  // uncommitted events, such as during an interrupt storm".
  optional uint64 commit_overrun = 4;

  // Size of entries currently in the kernel buffer (see |entries|) in bytes.
  // The field should be named "bytes", but is misnamed for historical reasons.
  // This value has known inaccuracies before Linux v6.6:
  // https://github.com/torvalds/linux/commit/45d99ea
  optional uint64 bytes_read = 5;

  // The timestamp for the oldest event still in the ring buffer.
  // Unit: seconds for typical trace clocks (i.e. not tsc/counter).
  optional double oldest_event_ts = 6;

  // The current timestamp.
  // Unit: seconds for typical trace clocks (i.e. not tsc/counter).
  optional double now_ts = 7;

  // If the kernel buffer has overwrite mode disabled, this will show the number
  // of new events that were lost because the buffer was full. This is similar
  // to |overrun| but only for the overwrite=false case.
  optional uint64 dropped_events = 8;

  // The number of events read (consumed) from the buffer by userspace.
  optional uint64 read_events = 9;
}

// Kprobe statistical data, gathered from /sys/kernel/tracing/kprobe_profile.
message FtraceKprobeStats {
  // Cumulative number of kprobe events generated for this function
  optional int64 hits = 1;
  // Cumulative number of kprobe events that could not be generated for this
  // function and were missed.  This happens when too much nesting
  // happens between a kprobe and its kretprobe, overflowing the
  // maxactives buffer.
  optional int64 misses = 2;
}

// Errors and kernel buffer stats for the ftrace data source.
message FtraceStats {
  enum Phase {
    UNSPECIFIED = 0;
    START_OF_TRACE = 1;
    END_OF_TRACE = 2;
  }

  // A pair of FtraceStats is written on every trace flush:
  // * START_OF_TRACE - stats recorded at the beginning of the trace.
  // * END_OF_TRACE - stats recorded during the flush. In other words shortly
  //                  before this packet was written. For simple traces this
  //                  will be once at the end of the trace.
  optional Phase phase = 1;

  // Per-CPU stats (one entry for each CPU).
  repeated FtraceCpuStats cpu_stats = 2;

  // When FtraceConfig.symbolize_ksyms = true, this records the number of
  // symbols parsed from /proc/kallsyms, whether they have been seen in the
  // trace or not. It can be used to debug kptr_restrict or security-related
  // errors.
  // Note: this will be valid only when phase = END_OF_TRACE. The symbolizer is
  // initialized. When START_OF_TRACE is emitted it is not ready yet.
  optional uint32 kernel_symbols_parsed = 3;

  // The memory used by the kernel symbolizer (KernelSymbolMap.size_bytes()).
  optional uint32 kernel_symbols_mem_kb = 4;

  // Atrace errors (even non-fatal ones) are reported here. A typical example is
  // one or more atrace categories not available on the device.
  optional string atrace_errors = 5;

  // Error message due to exclusivity violation of a single-tenant feature.
  optional string exclusive_feature_error = 13;

  // Ftrace events requested by the config but not present on device.
  repeated string unknown_ftrace_events = 6;

  // Ftrace events requested by the config and present on device, but which we
  // failed to enable due to permissions, or due to a conflicting option
  // (currently FtraceConfig.disable_generic_events).
  repeated string failed_ftrace_events = 7;

  // The data source was configured to preserve existing events in the ftrace
  // buffer before the start of the trace.
  optional bool preserve_ftrace_buffer = 8;

  // Unique errors encountered during reading and parsing of the raw ftrace
  // data. Ring buffer ABI related errors will also be recorded in the
  // affected FtraceEventBundles with a timestamp.
  // Any traces with entries in this field should be investigated, as they
  // indicate a bug in perfetto or the kernel.
  repeated FtraceParseStatus ftrace_parse_errors = 9;

  // Kprobe profile stats for functions hits and misses
  optional FtraceKprobeStats kprobe_stats = 10;

  // Per-cpu buffer size as returned by buffer_size_kb in pages (rounded up).
  // Added in: perfetto v52.
  optional uint32 cpu_buffer_size_pages = 11;

  // Per-cpu buffer size as cached by our implementation (ftrace muxer), based
  // on the value we're writing into the tracefs control file. Might not be
  // exactly equal to |cpu_buffer_size_pages| due to the kernel allocating extra
  // scratch pages (and/or other factors). Added in: perfetto v52.
  optional uint32 cached_cpu_buffer_size_pages = 12;
}

enum FtraceParseStatus {
  FTRACE_STATUS_UNSPECIFIED = 0;
  // Not written, used for convenience of implementation:
  FTRACE_STATUS_OK = 1;
  // Issues with reading data out of the ftrace ring buffer:
  FTRACE_STATUS_UNEXPECTED_READ_ERROR = 2;
  FTRACE_STATUS_PARTIAL_PAGE_READ = 3;
  // Ring buffer binary data not matching our understanding of the layout:
  FTRACE_STATUS_ABI_INVALID_PAGE_HEADER = 4;
  FTRACE_STATUS_ABI_SHORT_EVENT_HEADER = 5;
  FTRACE_STATUS_ABI_NULL_PADDING = 6;
  FTRACE_STATUS_ABI_SHORT_PADDING_LENGTH = 7;
  FTRACE_STATUS_ABI_INVALID_PADDING_LENGTH = 8;
  FTRACE_STATUS_ABI_SHORT_TIME_EXTEND = 9;
  FTRACE_STATUS_ABI_SHORT_TIME_STAMP = 10;
  FTRACE_STATUS_ABI_SHORT_DATA_LENGTH = 11;
  FTRACE_STATUS_ABI_ZERO_DATA_LENGTH = 12;
  FTRACE_STATUS_ABI_INVALID_DATA_LENGTH = 13;
  FTRACE_STATUS_ABI_SHORT_EVENT_ID = 14;
  FTRACE_STATUS_ABI_END_OVERFLOW = 15;
  // Issues with parsing the event payload:
  FTRACE_STATUS_SHORT_COMPACT_EVENT = 16;
  FTRACE_STATUS_INVALID_EVENT = 17;
}
