xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/ftrace/mali_gpu_event_tracker.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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