1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/trace_processor/importers/ftrace/mali_gpu_event_tracker.h"
18
19 #include <cstdint>
20
21 #include "perfetto/base/logging.h"
22 #include "perfetto/ext/base/string_utils.h"
23 #include "perfetto/protozero/field.h"
24 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
25 #include "src/trace_processor/importers/common/slice_tracker.h"
26 #include "src/trace_processor/importers/common/track_compressor.h"
27 #include "src/trace_processor/importers/common/track_tracker.h"
28 #include "src/trace_processor/importers/common/tracks.h"
29 #include "src/trace_processor/importers/common/tracks_common.h"
30 #include "src/trace_processor/importers/common/tracks_internal.h"
31 #include "src/trace_processor/storage/stats.h"
32 #include "src/trace_processor/storage/trace_storage.h"
33 #include "src/trace_processor/types/variadic.h"
34
35 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
36
37 namespace perfetto::trace_processor {
38 namespace {
39
40 constexpr auto kMaliIrqBlueprint = tracks::SliceBlueprint(
41 "cpu_mali_irq",
42 tracks::DimensionBlueprints(tracks::kCpuDimensionBlueprint),
__anon3d2bbbd90202(uint32_t cpu) 43 tracks::FnNameBlueprint([](uint32_t cpu) {
44 return base::StackString<255>("Mali Irq Cpu %u", cpu);
45 }));
46
47 } // namespace
48
49 namespace {
50
51 constexpr auto kMcuStateBlueprint = tracks::SliceBlueprint("mali_mcu_state");
52
53 }
54
MaliGpuEventTracker(TraceProcessorContext * context)55 MaliGpuEventTracker::MaliGpuEventTracker(TraceProcessorContext* context)
56 : context_(context),
57 mali_KCPU_CQS_SET_id_(
58 context->storage->InternString("mali_KCPU_CQS_SET")),
59 mali_KCPU_CQS_WAIT_id_(
60 context->storage->InternString("mali_KCPU_CQS_WAIT")),
61 mali_KCPU_FENCE_SIGNAL_id_(
62 context->storage->InternString("mali_KCPU_FENCE_SIGNAL")),
63 mali_KCPU_FENCE_WAIT_id_(
64 context->storage->InternString("mali_KCPU_FENCE_WAIT")),
65 mali_CSF_INTERRUPT_id_(
66 context->storage->InternString("mali_CSF_INTERRUPT")),
67 mali_CSF_INTERRUPT_info_val_id_(
68 context->storage->InternString("info_val")),
69 current_mcu_state_name_(kNullStringId) {
70 using protos::pbzero::FtraceEvent;
71
72 mcu_state_names_.fill(kNullStringId);
73 RegisterMcuState<
74 FtraceEvent::kMaliMaliPMMCUHCTLCORESDOWNSCALENOTIFYPENDFieldNumber>(
75 "HCTL_CORES_DOWN_SCALE_NOTIFY_PEND");
76 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLCORESNOTIFYPENDFieldNumber>(
77 "HCTL_CORES_NOTIFY_PEND");
78 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLCOREINACTIVEPENDFieldNumber>(
79 "HCTL_CORE_INACTIVE_PEND");
80 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLMCUONRECHECKFieldNumber>(
81 "HCTL_MCU_ON_RECHECK");
82 RegisterMcuState<
83 FtraceEvent::kMaliMaliPMMCUHCTLSHADERSCOREOFFPENDFieldNumber>(
84 "HCTL_SHADERS_CORE_OFF_PEND");
85 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSPENDOFFFieldNumber>(
86 "HCTL_SHADERS_PEND_OFF");
87 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSPENDONFieldNumber>(
88 "HCTL_SHADERS_PEND_ON");
89 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSREADYOFFFieldNumber>(
90 "HCTL_SHADERS_READY_OFF");
91 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUINSLEEPFieldNumber>("IN_SLEEP");
92 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUOFFFieldNumber>("OFF");
93 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONFieldNumber>("ON");
94 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONCOREATTRUPDATEPENDFieldNumber>(
95 "ON_CORE_ATTR_UPDATE_PEND");
96 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONGLBREINITPENDFieldNumber>(
97 "ON_GLB_REINIT_PEND");
98 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHALTFieldNumber>("ON_HALT");
99 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHWCNTDISABLEFieldNumber>(
100 "ON_HWCNT_DISABLE");
101 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHWCNTENABLEFieldNumber>(
102 "ON_HWCNT_ENABLE");
103 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONPENDHALTFieldNumber>(
104 "ON_PEND_HALT");
105 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONPENDSLEEPFieldNumber>(
106 "ON_PEND_SLEEP");
107 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONSLEEPINITIATEFieldNumber>(
108 "ON_SLEEP_INITIATE");
109 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPENDOFFFieldNumber>("PEND_OFF");
110 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPENDONRELOADFieldNumber>(
111 "PEND_ON_RELOAD");
112 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPOWERDOWNFieldNumber>(
113 "POWER_DOWN");
114 RegisterMcuState<FtraceEvent::kMaliMaliPMMCURESETWAITFieldNumber>(
115 "RESET_WAIT");
116 }
117
118 template <uint32_t FieldId>
RegisterMcuState(const char * state_name)119 void MaliGpuEventTracker::RegisterMcuState(const char* state_name) {
120 static_assert(FieldId >= kFirstMcuStateId && FieldId <= kLastMcuStateId);
121 mcu_state_names_[FieldId - kFirstMcuStateId] =
122 context_->storage->InternString(state_name);
123 }
124
ParseMaliGpuIrqEvent(int64_t ts,uint32_t field_id,uint32_t cpu,protozero::ConstBytes blob)125 void MaliGpuEventTracker::ParseMaliGpuIrqEvent(int64_t ts,
126 uint32_t field_id,
127 uint32_t cpu,
128 protozero::ConstBytes blob) {
129 // Since these events are called from an interrupt context they cannot be
130 // associated to a single process or thread. Add to a custom Mali Irq track
131 // instead.
132 TrackId track_id = context_->track_tracker->InternTrack(
133 kMaliIrqBlueprint, tracks::Dimensions(cpu));
134
135 switch (field_id) {
136 case protos::pbzero::FtraceEvent::kMaliMaliCSFINTERRUPTSTARTFieldNumber: {
137 ParseMaliCSFInterruptStart(ts, track_id, blob);
138 break;
139 }
140 case protos::pbzero::FtraceEvent::kMaliMaliCSFINTERRUPTENDFieldNumber: {
141 ParseMaliCSFInterruptEnd(ts, track_id, blob);
142 break;
143 }
144 default:
145 PERFETTO_DFATAL("Unexpected field id");
146 break;
147 }
148 }
149
ParseMaliGpuMcuStateEvent(int64_t timestamp,uint32_t field_id)150 void MaliGpuEventTracker::ParseMaliGpuMcuStateEvent(int64_t timestamp,
151 uint32_t field_id) {
152 if (field_id < kFirstMcuStateId || field_id > kLastMcuStateId) {
153 PERFETTO_FATAL("Mali MCU state ID out of range");
154 }
155
156 StringId state_name = mcu_state_names_[field_id - kFirstMcuStateId];
157 if (state_name == kNullStringId) {
158 context_->storage->IncrementStats(stats::mali_unknown_mcu_state_id);
159 return;
160 }
161
162 TrackId track_id = context_->track_tracker->InternTrack(kMcuStateBlueprint);
163 if (current_mcu_state_name_ != kNullStringId) {
164 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
165 current_mcu_state_name_);
166 }
167
168 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
169 state_name);
170 current_mcu_state_name_ = state_name;
171 }
172
ParseMaliCSFInterruptStart(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)173 void MaliGpuEventTracker::ParseMaliCSFInterruptStart(
174 int64_t timestamp,
175 TrackId track_id,
176 protozero::ConstBytes blob) {
177 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob);
178 context_->slice_tracker->Begin(
179 timestamp, track_id, kNullStringId, mali_CSF_INTERRUPT_id_,
180 [&, this](ArgsTracker::BoundInserter* inserter) {
181 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
182 Variadic::UnsignedInteger(evt.info_val()));
183 });
184 }
185
ParseMaliCSFInterruptEnd(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)186 void MaliGpuEventTracker::ParseMaliCSFInterruptEnd(int64_t timestamp,
187 TrackId track_id,
188 protozero::ConstBytes blob) {
189 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob);
190
191 context_->slice_tracker->End(
192 timestamp, track_id, kNullStringId, mali_CSF_INTERRUPT_id_,
193 [&, this](ArgsTracker::BoundInserter* inserter) {
194 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
195 Variadic::UnsignedInteger(evt.info_val()));
196 });
197 }
198 } // namespace perfetto::trace_processor
199