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 TrackId track_id = context_->track_tracker->InternCpuTrack(
158 tracks::cpu_mali_irq, cpu,
159 TrackTracker::LegacyCharArrayName{
160 base::StackString<255>("Mali Irq Cpu %u", cpu)});
161
162 switch (field_id) {
163 case FtraceEvent::kMaliMaliCSFINTERRUPTSTARTFieldNumber: {
164 ParseMaliCSFInterruptStart(ts, track_id, blob);
165 break;
166 }
167 case FtraceEvent::kMaliMaliCSFINTERRUPTENDFieldNumber: {
168 ParseMaliCSFInterruptEnd(ts, track_id, blob);
169 break;
170 }
171 default:
172 PERFETTO_DFATAL("Unexpected field id");
173 break;
174 }
175 }
176
ParseMaliGpuMcuStateEvent(int64_t timestamp,uint32_t field_id)177 void MaliGpuEventTracker::ParseMaliGpuMcuStateEvent(int64_t timestamp,
178 uint32_t field_id) {
179 tables::GpuTrackTable::Row track_info(mcu_state_track_name_);
180 TrackId track_id = context_->track_tracker->LegacyInternGpuTrack(track_info);
181
182 if (field_id < kFirstMcuStateId || field_id > kLastMcuStateId) {
183 PERFETTO_FATAL("Mali MCU state ID out of range");
184 }
185
186 StringId state_name = mcu_state_names_[field_id - kFirstMcuStateId];
187 if (state_name == kNullStringId) {
188 context_->storage->IncrementStats(stats::mali_unknown_mcu_state_id);
189 return;
190 }
191
192 if (current_mcu_state_name_ != kNullStringId) {
193 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
194 current_mcu_state_name_);
195 }
196
197 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
198 state_name);
199 current_mcu_state_name_ = state_name;
200 }
201
ParseMaliKcpuCqsSet(int64_t timestamp,TrackId track_id)202 void MaliGpuEventTracker::ParseMaliKcpuCqsSet(int64_t timestamp,
203 TrackId track_id) {
204 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
205 mali_KCPU_CQS_SET_id_, 0);
206 }
207
ParseMaliKcpuCqsWaitStart(int64_t timestamp,TrackId track_id)208 void MaliGpuEventTracker::ParseMaliKcpuCqsWaitStart(int64_t timestamp,
209 TrackId track_id) {
210 // TODO(b/294866695): Remove
211 if (base::GetSysPageSize()) {
212 PERFETTO_FATAL("This causes incorrectly nested slices at present.");
213 }
214 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
215 mali_KCPU_CQS_WAIT_id_);
216 }
217
ParseMaliKcpuCqsWaitEnd(int64_t timestamp,TrackId track_id)218 void MaliGpuEventTracker::ParseMaliKcpuCqsWaitEnd(int64_t timestamp,
219 TrackId track_id) {
220 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
221 mali_KCPU_CQS_WAIT_id_);
222 }
223
ParseMaliKcpuFenceSignal(int64_t timestamp,TrackId track_id)224 void MaliGpuEventTracker::ParseMaliKcpuFenceSignal(int64_t timestamp,
225 TrackId track_id) {
226 context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
227 mali_KCPU_FENCE_SIGNAL_id_, 0);
228 }
229
ParseMaliKcpuFenceWaitStart(int64_t timestamp,TrackId track_id)230 void MaliGpuEventTracker::ParseMaliKcpuFenceWaitStart(int64_t timestamp,
231 TrackId track_id) {
232 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
233 mali_KCPU_FENCE_WAIT_id_);
234 }
235
ParseMaliKcpuFenceWaitEnd(int64_t timestamp,TrackId track_id)236 void MaliGpuEventTracker::ParseMaliKcpuFenceWaitEnd(int64_t timestamp,
237 TrackId track_id) {
238 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
239 mali_KCPU_FENCE_WAIT_id_);
240 }
241
ParseMaliCSFInterruptStart(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)242 void MaliGpuEventTracker::ParseMaliCSFInterruptStart(
243 int64_t timestamp,
244 TrackId track_id,
245 protozero::ConstBytes blob) {
246 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob.data,
247 blob.size);
248 auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
249 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
250 Variadic::UnsignedInteger(evt.info_val()));
251 };
252
253 context_->slice_tracker->Begin(timestamp, track_id, kNullStringId,
254 mali_CSF_INTERRUPT_id_, args_inserter);
255 }
256
ParseMaliCSFInterruptEnd(int64_t timestamp,TrackId track_id,protozero::ConstBytes blob)257 void MaliGpuEventTracker::ParseMaliCSFInterruptEnd(int64_t timestamp,
258 TrackId track_id,
259 protozero::ConstBytes blob) {
260 protos::pbzero::MaliMaliCSFINTERRUPTSTARTFtraceEvent::Decoder evt(blob.data,
261 blob.size);
262 auto args_inserter = [this, &evt](ArgsTracker::BoundInserter* inserter) {
263 inserter->AddArg(mali_CSF_INTERRUPT_info_val_id_,
264 Variadic::UnsignedInteger(evt.info_val()));
265 };
266
267 context_->slice_tracker->End(timestamp, track_id, kNullStringId,
268 mali_CSF_INTERRUPT_id_, args_inserter);
269 }
270 } // namespace trace_processor
271 } // namespace perfetto
272