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 "perfetto/ext/base/string_utils.h"
20 #include "protos/perfetto/trace/ftrace/mali.pbzero.h"
21 #include "src/trace_processor/importers/common/async_track_set_tracker.h"
22 #include "src/trace_processor/importers/common/process_tracker.h"
23 #include "src/trace_processor/importers/common/slice_tracker.h"
24 #include "src/trace_processor/importers/common/track_tracker.h"
25
26 namespace perfetto {
27 namespace trace_processor {
28
MaliGpuEventTracker(TraceProcessorContext * context)29 MaliGpuEventTracker::MaliGpuEventTracker(TraceProcessorContext* context)
30 : context_(context),
31 mali_KCPU_CQS_SET_id_(
32 context->storage->InternString("mali_KCPU_CQS_SET")),
33 mali_KCPU_CQS_WAIT_id_(
34 context->storage->InternString("mali_KCPU_CQS_WAIT")),
35 mali_KCPU_FENCE_SIGNAL_id_(
36 context->storage->InternString("mali_KCPU_FENCE_SIGNAL")),
37 mali_KCPU_FENCE_WAIT_id_(
38 context->storage->InternString("mali_KCPU_FENCE_WAIT")),
39 mali_CSF_INTERRUPT_id_(
40 context->storage->InternString("mali_CSF_INTERRUPT")),
41 mali_CSF_INTERRUPT_info_val_id_(
42 context->storage->InternString("info_val")),
43 current_mcu_state_name_(kNullStringId),
44 mcu_state_track_name_(context->storage->InternString("Mali MCU state")) {
45 using protos::pbzero::FtraceEvent;
46
47 mcu_state_names_.fill(kNullStringId);
48 RegisterMcuState<
49 FtraceEvent::kMaliMaliPMMCUHCTLCORESDOWNSCALENOTIFYPENDFieldNumber>(
50 "HCTL_CORES_DOWN_SCALE_NOTIFY_PEND");
51 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLCORESNOTIFYPENDFieldNumber>(
52 "HCTL_CORES_NOTIFY_PEND");
53 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLCOREINACTIVEPENDFieldNumber>(
54 "HCTL_CORE_INACTIVE_PEND");
55 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLMCUONRECHECKFieldNumber>(
56 "HCTL_MCU_ON_RECHECK");
57 RegisterMcuState<
58 FtraceEvent::kMaliMaliPMMCUHCTLSHADERSCOREOFFPENDFieldNumber>(
59 "HCTL_SHADERS_CORE_OFF_PEND");
60 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSPENDOFFFieldNumber>(
61 "HCTL_SHADERS_PEND_OFF");
62 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSPENDONFieldNumber>(
63 "HCTL_SHADERS_PEND_ON");
64 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUHCTLSHADERSREADYOFFFieldNumber>(
65 "HCTL_SHADERS_READY_OFF");
66 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUINSLEEPFieldNumber>("IN_SLEEP");
67 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUOFFFieldNumber>("OFF");
68 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONFieldNumber>("ON");
69 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONCOREATTRUPDATEPENDFieldNumber>(
70 "ON_CORE_ATTR_UPDATE_PEND");
71 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONGLBREINITPENDFieldNumber>(
72 "ON_GLB_REINIT_PEND");
73 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHALTFieldNumber>("ON_HALT");
74 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHWCNTDISABLEFieldNumber>(
75 "ON_HWCNT_DISABLE");
76 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONHWCNTENABLEFieldNumber>(
77 "ON_HWCNT_ENABLE");
78 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONPENDHALTFieldNumber>(
79 "ON_PEND_HALT");
80 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONPENDSLEEPFieldNumber>(
81 "ON_PEND_SLEEP");
82 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUONSLEEPINITIATEFieldNumber>(
83 "ON_SLEEP_INITIATE");
84 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPENDOFFFieldNumber>("PEND_OFF");
85 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPENDONRELOADFieldNumber>(
86 "PEND_ON_RELOAD");
87 RegisterMcuState<FtraceEvent::kMaliMaliPMMCUPOWERDOWNFieldNumber>(
88 "POWER_DOWN");
89 RegisterMcuState<FtraceEvent::kMaliMaliPMMCURESETWAITFieldNumber>(
90 "RESET_WAIT");
91 }
92
93 template <uint32_t FieldId>
RegisterMcuState(const char * state_name)94 void MaliGpuEventTracker::RegisterMcuState(const char* state_name) {
95 static_assert(FieldId >= kFirstMcuStateId && FieldId <= kLastMcuStateId);
96 mcu_state_names_[FieldId - kFirstMcuStateId] =
97 context_->storage->InternString(state_name);
98 }
99
ParseMaliGpuEvent(int64_t ts,uint32_t field_id,uint32_t pid)100 void MaliGpuEventTracker::ParseMaliGpuEvent(int64_t ts,
101 uint32_t field_id,
102 uint32_t pid) {
103 using protos::pbzero::FtraceEvent;
104
105 // It seems like it is not correct to add to add any of these slices
106 // in the normal thread slice track since they are not guaranteed to
107 // be correctly nested with respect to atrace events.
108 // For now just disable all mali events by early returning here.
109 // TODO(b/294866695): Consider how to best visualise these events.
110 if (ts != 0) {
111 return;
112 }
113
114 UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
115 TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
116
117 switch (field_id) {
118 case FtraceEvent::kMaliMaliKCPUCQSSETFieldNumber: {
119 ParseMaliKcpuCqsSet(ts, track_id);
120 break;
121 }
122 case FtraceEvent::kMaliMaliKCPUCQSWAITSTARTFieldNumber: {
123 ParseMaliKcpuCqsWaitStart(ts, track_id);
124 break;
125 }
126 case FtraceEvent::kMaliMaliKCPUCQSWAITENDFieldNumber: {
127 ParseMaliKcpuCqsWaitEnd(ts, track_id);
128 break;
129 }
130 case FtraceEvent::kMaliMaliKCPUFENCESIGNALFieldNumber: {
131 ParseMaliKcpuFenceSignal(ts, track_id);
132 break;
133 }
134 case FtraceEvent::kMaliMaliKCPUFENCEWAITSTARTFieldNumber: {
135 ParseMaliKcpuFenceWaitStart(ts, track_id);
136 break;
137 }
138 case FtraceEvent::kMaliMaliKCPUFENCEWAITENDFieldNumber: {
139 ParseMaliKcpuFenceWaitEnd(ts, track_id);
140 break;
141 }
142 default:
143 PERFETTO_DFATAL("Unexpected field id");
144 break;
145 }
146 }
147
ParseMaliGpuIrqEvent(int64_t ts,uint32_t field_id,uint32_t cpu,protozero::ConstBytes blob)148 void MaliGpuEventTracker::ParseMaliGpuIrqEvent(int64_t ts,
149 uint32_t field_id,
150 uint32_t cpu,
151 protozero::ConstBytes blob) {
152 using protos::pbzero::FtraceEvent;
153
154 // Since these events are called from an interrupt context they cannot be
155 // associated to a single process or thread. Add to a custom Mali Irq track
156 // instead.
157 base::StackString<255> track_name("Mali Irq Cpu %d", cpu);
158 StringId track_name_id =
159 context_->storage->InternString(track_name.string_view());
160 TrackId track_id =
161 context_->track_tracker->InternCpuTrack(track_name_id, cpu);
162
163 switch (field_id) {
164 case FtraceEvent::kMaliMaliCSFINTERRUPTSTARTFieldNumber: {
165 ParseMaliCSFInterruptStart(ts, track_id, blob);
166 break;
167 }
168 case FtraceEvent::kMaliMaliCSFINTERRUPTENDFieldNumber: {
169 ParseMaliCSFInterruptEnd(ts, track_id, blob);
170 break;
171 }
172 default:
173 PERFETTO_DFATAL("Unexpected field id");
174 break;
175 }
176 }
177
ParseMaliGpuMcuStateEvent(int64_t timestamp,uint32_t field_id)178 void MaliGpuEventTracker::ParseMaliGpuMcuStateEvent(int64_t timestamp,
179 uint32_t field_id) {
180 tables::GpuTrackTable::Row track_info(mcu_state_track_name_);
181 TrackId track_id = context_->track_tracker->InternGpuTrack(track_info);
182
183 if (field_id < kFirstMcuStateId || field_id > kLastMcuStateId) {
184 PERFETTO_FATAL("Mali MCU state ID out of range");
185 }
186
187 StringId state_name = mcu_state_names_[field_id - kFirstMcuStateId];
188 if (state_name == kNullStringId) {
189 context_->storage->IncrementStats(stats::mali_unknown_mcu_state_id);
190 return;
191 }
192
193 if (current_mcu_state_name_ != kNullStringId) {
194 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
195 current_mcu_state_name_);
196 }
197
198 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
199 state_name);
200 current_mcu_state_name_ = state_name;
201 }
202
ParseMaliKcpuCqsSet(int64_t timestamp,TrackId track_id)203 void MaliGpuEventTracker::ParseMaliKcpuCqsSet(int64_t timestamp,
204 TrackId track_id) {
205 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
206 mali_KCPU_CQS_SET_id_, 0);
207 }
208
ParseMaliKcpuCqsWaitStart(int64_t timestamp,TrackId track_id)209 void MaliGpuEventTracker::ParseMaliKcpuCqsWaitStart(int64_t timestamp,
210 TrackId track_id) {
211 // TODO(b/294866695): Remove
212 if (base::GetSysPageSize()) {
213 PERFETTO_FATAL("This causes incorrectly nested slices at present.");
214 }
215 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
216 mali_KCPU_CQS_WAIT_id_);
217 }
218
ParseMaliKcpuCqsWaitEnd(int64_t timestamp,TrackId track_id)219 void MaliGpuEventTracker::ParseMaliKcpuCqsWaitEnd(int64_t timestamp,
220 TrackId track_id) {
221 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
222 mali_KCPU_CQS_WAIT_id_);
223 }
224
ParseMaliKcpuFenceSignal(int64_t timestamp,TrackId track_id)225 void MaliGpuEventTracker::ParseMaliKcpuFenceSignal(int64_t timestamp,
226 TrackId track_id) {
227 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
228 mali_KCPU_FENCE_SIGNAL_id_, 0);
229 }
230
ParseMaliKcpuFenceWaitStart(int64_t timestamp,TrackId track_id)231 void MaliGpuEventTracker::ParseMaliKcpuFenceWaitStart(int64_t timestamp,
232 TrackId track_id) {
233 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
234 mali_KCPU_FENCE_WAIT_id_);
235 }
236
ParseMaliKcpuFenceWaitEnd(int64_t timestamp,TrackId track_id)237 void MaliGpuEventTracker::ParseMaliKcpuFenceWaitEnd(int64_t timestamp,
238 TrackId track_id) {
239 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
240 mali_KCPU_FENCE_WAIT_id_);
241 }
242
ParseMaliCSFInterruptStart(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)243 void MaliGpuEventTracker::ParseMaliCSFInterruptStart(
244 int64_t timestamp,
245 TrackId track_id,
246 protozero::ConstBytes blob) {
247 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob.data,
248 blob.size);
249 auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
250 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
251 Variadic::UnsignedInteger(evt.info_val()));
252 };
253
254 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
255 mali_CSF_INTERRUPT_id_, args_inserter);
256 }
257
ParseMaliCSFInterruptEnd(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)258 void MaliGpuEventTracker::ParseMaliCSFInterruptEnd(int64_t timestamp,
259 TrackId track_id,
260 protozero::ConstBytes blob) {
261 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob.data,
262 blob.size);
263 auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
264 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
265 Variadic::UnsignedInteger(evt.info_val()));
266 };
267
268 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
269 mali_CSF_INTERRUPT_id_, args_inserter);
270 }
271 } // namespace trace_processor
272 } // namespace perfetto
273