blob: 7a27b8690ba96defeacd1e7e59d7f3cc5b31af40 [file] [log] [blame]
/*
* Copyright (C) 2025 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.
*/
#include "src/traced/probes/ftrace/predefined_tracepoints.h"
#include <map>
#include <set>
#include "src/traced/probes/ftrace/proto_translation_table.h"
#include "src/traced/probes/ftrace/tracefs.h"
namespace perfetto::predefined_tracepoints {
namespace {
void AddEventGroup(const ProtoTranslationTable* table,
const std::string& group,
base::FlatSet<GroupAndName>* to) {
const std::vector<const Event*>* events = table->GetEventsByGroup(group);
if (!events)
return;
for (const Event* event : *events) {
to->insert(GroupAndName(group, event->name));
}
}
void PERFETTO_NO_INLINE InsertEvent(const char* group,
const char* name,
base::FlatSet<GroupAndName>* dst) {
dst->insert(GroupAndName(group, name));
}
base::FlatSet<GroupAndName> GenerateGfxTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "mdss", &events);
InsertEvent("mdss", "rotator_bw_ao_as_context", &events);
InsertEvent("mdss", "mdp_trace_counter", &events);
InsertEvent("mdss", "tracing_mark_write", &events);
InsertEvent("mdss", "mdp_cmd_wait_pingpong", &events);
InsertEvent("mdss", "mdp_cmd_kickoff", &events);
InsertEvent("mdss", "mdp_cmd_release_bw", &events);
InsertEvent("mdss", "mdp_cmd_readptr_done", &events);
InsertEvent("mdss", "mdp_cmd_pingpong_done", &events);
InsertEvent("mdss", "mdp_misr_crc", &events);
InsertEvent("mdss", "mdp_compare_bw", &events);
InsertEvent("mdss", "mdp_perf_update_bus", &events);
InsertEvent("mdss", "mdp_video_underrun_done", &events);
InsertEvent("mdss", "mdp_commit", &events);
InsertEvent("mdss", "mdp_mixer_update", &events);
InsertEvent("mdss", "mdp_perf_prefill_calc", &events);
InsertEvent("mdss", "mdp_perf_set_ot", &events);
InsertEvent("mdss", "mdp_perf_set_wm_levels", &events);
InsertEvent("mdss", "mdp_perf_set_panic_luts", &events);
InsertEvent("mdss", "mdp_perf_set_qos_luts", &events);
InsertEvent("mdss", "mdp_sspp_change", &events);
InsertEvent("mdss", "mdp_sspp_set", &events);
AddEventGroup(table, "mali", &events);
InsertEvent("mali", "tracing_mark_write", &events);
AddEventGroup(table, "sde", &events);
InsertEvent("sde", "tracing_mark_write", &events);
InsertEvent("sde", "sde_perf_update_bus", &events);
InsertEvent("sde", "sde_perf_set_qos_luts", &events);
InsertEvent("sde", "sde_perf_set_ot", &events);
InsertEvent("sde", "sde_perf_set_danger_luts", &events);
InsertEvent("sde", "sde_perf_crtc_update", &events);
InsertEvent("sde", "sde_perf_calc_crtc", &events);
InsertEvent("sde", "sde_evtlog", &events);
InsertEvent("sde", "sde_encoder_underrun", &events);
InsertEvent("sde", "sde_cmd_release_bw", &events);
AddEventGroup(table, "dpu", &events);
InsertEvent("dpu", "tracing_mark_write", &events);
InsertEvent("dpu", "disp_dpu_underrun", &events);
AddEventGroup(table, "g2d", &events);
InsertEvent("g2d", "tracing_mark_write", &events);
InsertEvent("g2d", "g2d_perf_update_qos", &events);
AddEventGroup(table, "panel", &events);
InsertEvent("panel", "panel_write_generic", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateIonTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("kmem", "ion_alloc_buffer_start", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateSchedTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
// Note: sched_wakeup intentionally removed (diverging from atrace), as it
// is high-volume, but mostly redundant when sched_waking is also enabled.
// The event can still be enabled explicitly when necessary.
InsertEvent("sched", "sched_switch", &events);
InsertEvent("sched", "sched_waking", &events);
InsertEvent("sched", "sched_blocked_reason", &events);
InsertEvent("sched", "sched_cpu_hotplug", &events);
InsertEvent("sched", "sched_pi_setprio", &events);
InsertEvent("sched", "sched_process_exit", &events);
AddEventGroup(table, "cgroup", &events);
InsertEvent("cgroup", "cgroup_transfer_tasks", &events);
InsertEvent("cgroup", "cgroup_setup_root", &events);
InsertEvent("cgroup", "cgroup_rmdir", &events);
InsertEvent("cgroup", "cgroup_rename", &events);
InsertEvent("cgroup", "cgroup_remount", &events);
InsertEvent("cgroup", "cgroup_release", &events);
InsertEvent("cgroup", "cgroup_mkdir", &events);
InsertEvent("cgroup", "cgroup_destroy_root", &events);
InsertEvent("cgroup", "cgroup_attach_task", &events);
InsertEvent("oom", "oom_score_adj_update", &events);
InsertEvent("task", "task_rename", &events);
InsertEvent("task", "task_newtask", &events);
AddEventGroup(table, "systrace", &events);
InsertEvent("systrace", "0", &events);
AddEventGroup(table, "scm", &events);
InsertEvent("scm", "scm_call_start", &events);
InsertEvent("scm", "scm_call_end", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateIrqTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "irq", &events);
InsertEvent("irq", "tasklet_hi_exit", &events);
InsertEvent("irq", "tasklet_hi_entry", &events);
InsertEvent("irq", "tasklet_exit", &events);
InsertEvent("irq", "tasklet_entry", &events);
InsertEvent("irq", "softirq_raise", &events);
InsertEvent("irq", "softirq_exit", &events);
InsertEvent("irq", "softirq_entry", &events);
InsertEvent("irq", "irq_handler_exit", &events);
InsertEvent("irq", "irq_handler_entry", &events);
AddEventGroup(table, "ipi", &events);
InsertEvent("ipi", "ipi_raise", &events);
InsertEvent("ipi", "ipi_exit", &events);
InsertEvent("ipi", "ipi_entry", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateIrqOffTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("preemptirq", "irq_enable", &events);
InsertEvent("preemptirq", "irq_disable", &events);
return events;
}
base::FlatSet<GroupAndName> GeneratePreemptoffTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("preemptirq", "preempt_enable", &events);
InsertEvent("preemptirq", "preempt_disable", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateI2cTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "i2c", &events);
InsertEvent("i2c", "i2c_read", &events);
InsertEvent("i2c", "i2c_write", &events);
InsertEvent("i2c", "i2c_result", &events);
InsertEvent("i2c", "i2c_reply", &events);
InsertEvent("i2c", "smbus_read", &events);
InsertEvent("i2c", "smbus_write", &events);
InsertEvent("i2c", "smbus_result", &events);
InsertEvent("i2c", "smbus_reply", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateFreqTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
InsertEvent("power", "cpu_frequency", &events);
InsertEvent("power", "gpu_frequency", &events);
InsertEvent("power", "clock_set_rate", &events);
InsertEvent("power", "clock_disable", &events);
InsertEvent("power", "clock_enable", &events);
InsertEvent("clk", "clk_set_rate", &events);
InsertEvent("clk", "clk_disable", &events);
InsertEvent("clk", "clk_enable", &events);
InsertEvent("power", "cpu_frequency_limits", &events);
InsertEvent("power", "suspend_resume", &events);
InsertEvent("cpuhp", "cpuhp_enter", &events);
InsertEvent("cpuhp", "cpuhp_exit", &events);
InsertEvent("cpuhp", "cpuhp_pause", &events);
AddEventGroup(table, "msm_bus", &events);
InsertEvent("msm_bus", "bus_update_request_end", &events);
InsertEvent("msm_bus", "bus_update_request", &events);
InsertEvent("msm_bus", "bus_rules_matches", &events);
InsertEvent("msm_bus", "bus_max_votes", &events);
InsertEvent("msm_bus", "bus_client_status", &events);
InsertEvent("msm_bus", "bus_bke_params", &events);
InsertEvent("msm_bus", "bus_bimc_config_limiter", &events);
InsertEvent("msm_bus", "bus_avail_bw", &events);
InsertEvent("msm_bus", "bus_agg_bw", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateMembusTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "memory_bus", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateIdleTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("power", "cpu_idle", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateDiskTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("f2fs", "f2fs_sync_file_enter", &events);
InsertEvent("f2fs", "f2fs_sync_file_exit", &events);
InsertEvent("f2fs", "f2fs_write_begin", &events);
InsertEvent("f2fs", "f2fs_write_end", &events);
InsertEvent("f2fs", "f2fs_iostat", &events);
InsertEvent("f2fs", "f2fs_iostat_latency", &events);
InsertEvent("ext4", "ext4_da_write_begin", &events);
InsertEvent("ext4", "ext4_da_write_end", &events);
InsertEvent("ext4", "ext4_sync_file_enter", &events);
InsertEvent("ext4", "ext4_sync_file_exit", &events);
InsertEvent("block", "block_bio_queue", &events);
InsertEvent("block", "block_bio_complete", &events);
InsertEvent("ufs", "ufshcd_command", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateMmcTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "mmc", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateLoadTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "cpufreq_interactive", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateSyncTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
// linux kernel < 4.9
AddEventGroup(table, "sync", &events);
InsertEvent("sync", "sync_pt", &events);
InsertEvent("sync", "sync_timeline", &events);
InsertEvent("sync", "sync_wait", &events);
// linux kernel == 4.9.x
AddEventGroup(table, "fence", &events);
InsertEvent("fence", "fence_annotate_wait_on", &events);
InsertEvent("fence", "fence_destroy", &events);
InsertEvent("fence", "fence_emit", &events);
InsertEvent("fence", "fence_enable_signal", &events);
InsertEvent("fence", "fence_init", &events);
InsertEvent("fence", "fence_signaled", &events);
InsertEvent("fence", "fence_wait_end", &events);
InsertEvent("fence", "fence_wait_start", &events);
// linux kernel > 4.9
AddEventGroup(table, "dma_fence", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateWorkqTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "workqueue", &events);
InsertEvent("workqueue", "workqueue_queue_work", &events);
InsertEvent("workqueue", "workqueue_execute_start", &events);
InsertEvent("workqueue", "workqueue_execute_end", &events);
InsertEvent("workqueue", "workqueue_activate_work", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateMemreclaimTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
InsertEvent("vmscan", "mm_vmscan_direct_reclaim_begin", &events);
InsertEvent("vmscan", "mm_vmscan_direct_reclaim_end", &events);
InsertEvent("vmscan", "mm_vmscan_kswapd_wake", &events);
InsertEvent("vmscan", "mm_vmscan_kswapd_sleep", &events);
AddEventGroup(table, "lowmemorykiller", &events);
InsertEvent("lowmemorykiller", "lowmemory_kill", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateRegulatorsTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "regulator", &events);
InsertEvent("regulator", "regulator_set_voltage_complete", &events);
InsertEvent("regulator", "regulator_set_voltage", &events);
InsertEvent("regulator", "regulator_enable_delay", &events);
InsertEvent("regulator", "regulator_enable_complete", &events);
InsertEvent("regulator", "regulator_enable", &events);
InsertEvent("regulator", "regulator_disable_complete", &events);
InsertEvent("regulator", "regulator_disable", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateBinderDriverTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("binder", "binder_transaction", &events);
InsertEvent("binder", "binder_transaction_received", &events);
InsertEvent("binder", "binder_transaction_alloc_buf", &events);
InsertEvent("binder", "binder_set_priority", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateBinderLockTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("binder", "binder_lock", &events);
InsertEvent("binder", "binder_locked", &events);
InsertEvent("binder", "binder_unlock", &events);
return events;
}
base::FlatSet<GroupAndName> GeneratePagecacheTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "filemap", &events);
InsertEvent("filemap", "mm_filemap_delete_from_page_cache", &events);
InsertEvent("filemap", "mm_filemap_add_to_page_cache", &events);
InsertEvent("filemap", "filemap_set_wb_err", &events);
InsertEvent("filemap", "file_check_and_advance_wb_err", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateMemoryTracePoints(Tracefs* ftrace) {
base::FlatSet<GroupAndName> events;
// Use rss_stat_throttled if supported
if (ftrace->SupportsRssStatThrottled()) {
InsertEvent("synthetic", "rss_stat_throttled", &events);
} else {
InsertEvent("kmem", "rss_stat", &events);
}
InsertEvent("kmem", "ion_heap_grow", &events);
InsertEvent("kmem", "ion_heap_shrink", &events);
// ion_stat supersedes ion_heap_grow / shrink for kernel 4.19+
InsertEvent("ion", "ion_stat", &events);
InsertEvent("mm_event", "mm_event_record", &events);
InsertEvent("dmabuf_heap", "dma_heap_stat", &events);
InsertEvent("gpu_mem", "gpu_mem_total", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateThermalTracePoints() {
base::FlatSet<GroupAndName> events;
InsertEvent("thermal", "thermal_temperature", &events);
InsertEvent("thermal", "cdev_update", &events);
return events;
}
base::FlatSet<GroupAndName> GenerateCameraTracePoints(
const ProtoTranslationTable* table) {
base::FlatSet<GroupAndName> events;
AddEventGroup(table, "lwis", &events);
InsertEvent("lwis", "tracing_mark_write", &events);
return events;
}
std::map<std::string, base::FlatSet<GroupAndName>>
GeneratePredefinedTracePoints(const ProtoTranslationTable* table,
Tracefs* ftrace) {
// Ideally we should keep this code in sync with:
// platform/frameworks/native/cmds/atrace/atrace.cpp
// It's not a disaster if they go out of sync, we can always add the ftrace
// categories manually server side but this is user friendly and reduces the
// size of the configs.
std::map<std::string, base::FlatSet<GroupAndName>> tracepoints;
tracepoints["gfx"] = GenerateGfxTracePoints(table);
tracepoints["ion"] = GenerateIonTracePoints();
tracepoints["sched"] = GenerateSchedTracePoints(table);
tracepoints["irq"] = GenerateIrqTracePoints(table);
tracepoints["irqoff"] = GenerateIrqOffTracePoints();
tracepoints["preemptoff"] = GeneratePreemptoffTracePoints();
tracepoints["i2c"] = GenerateI2cTracePoints(table);
tracepoints["freq"] = GenerateFreqTracePoints(table);
tracepoints["membus"] = GenerateMembusTracePoints(table);
tracepoints["idle"] = GenerateIdleTracePoints();
tracepoints["disk"] = GenerateDiskTracePoints();
tracepoints["mmc"] = GenerateMmcTracePoints(table);
tracepoints["load"] = GenerateLoadTracePoints(table);
tracepoints["sync"] = GenerateSyncTracePoints(table);
tracepoints["workq"] = GenerateWorkqTracePoints(table);
tracepoints["memreclaim"] = GenerateMemreclaimTracePoints(table);
tracepoints["regulators"] = GenerateRegulatorsTracePoints(table);
tracepoints["binder_driver"] = GenerateBinderDriverTracePoints();
tracepoints["binder_lock"] = GenerateBinderLockTracePoints();
tracepoints["pagecache"] = GeneratePagecacheTracePoints(table);
tracepoints["memory"] = GenerateMemoryTracePoints(ftrace);
tracepoints["thermal"] = GenerateThermalTracePoints();
tracepoints["camera"] = GenerateCameraTracePoints(table);
return tracepoints;
}
} // namespace
std::map<std::string, base::FlatSet<GroupAndName>> GetPredefinedTracePoints(
const ProtoTranslationTable* table,
Tracefs* ftrace) {
return GeneratePredefinedTracePoints(table, ftrace);
}
std::map<std::string, base::FlatSet<GroupAndName>>
GetAccessiblePredefinedTracePoints(const ProtoTranslationTable* table,
Tracefs* ftrace) {
auto tracepoints = GetPredefinedTracePoints(table, ftrace);
bool generic_enable = ftrace->IsGenericSetEventWritable();
std::map<std::string, base::FlatSet<GroupAndName>> accessible_tracepoints;
for (const auto& [category, events] : tracepoints) {
base::FlatSet<GroupAndName> accessible_events;
for (const auto& event : events) {
if (generic_enable
? ftrace->IsEventFormatReadable(event.group(), event.name())
: ftrace->IsEventAccessible(event.group(), event.name())) {
accessible_events.insert(event);
}
}
if (!accessible_events.empty()) {
accessible_tracepoints[category] = accessible_events;
}
}
return accessible_tracepoints;
}
} // namespace perfetto::predefined_tracepoints