• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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