drm/etnaviv: implement per-process address spaces on MMUv2
[linux-2.6-microblaze.git] / drivers / gpu / drm / etnaviv / etnaviv_perfmon.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2017 Etnaviv Project
4  * Copyright (C) 2017 Zodiac Inflight Innovations
5  */
6
7 #include "common.xml.h"
8 #include "etnaviv_gpu.h"
9 #include "etnaviv_perfmon.h"
10 #include "state_hi.xml.h"
11
12 struct etnaviv_pm_domain;
13
14 struct etnaviv_pm_signal {
15         char name[64];
16         u32 data;
17
18         u32 (*sample)(struct etnaviv_gpu *gpu,
19                       const struct etnaviv_pm_domain *domain,
20                       const struct etnaviv_pm_signal *signal);
21 };
22
23 struct etnaviv_pm_domain {
24         char name[64];
25
26         /* profile register */
27         u32 profile_read;
28         u32 profile_config;
29
30         u8 nr_signals;
31         const struct etnaviv_pm_signal *signal;
32 };
33
34 struct etnaviv_pm_domain_meta {
35         const struct etnaviv_pm_domain *domains;
36         u32 nr_domains;
37 };
38
39 static u32 perf_reg_read(struct etnaviv_gpu *gpu,
40         const struct etnaviv_pm_domain *domain,
41         const struct etnaviv_pm_signal *signal)
42 {
43         gpu_write(gpu, domain->profile_config, signal->data);
44
45         return gpu_read(gpu, domain->profile_read);
46 }
47
48 static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
49         const struct etnaviv_pm_domain *domain,
50         const struct etnaviv_pm_signal *signal)
51 {
52         u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
53         u32 value = 0;
54         unsigned i;
55
56         for (i = 0; i < gpu->identity.pixel_pipes; i++) {
57                 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
58                 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i);
59                 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
60                 gpu_write(gpu, domain->profile_config, signal->data);
61                 value += gpu_read(gpu, domain->profile_read);
62         }
63
64         /* switch back to pixel pipe 0 to prevent GPU hang */
65         clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
66         clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0);
67         gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
68
69         return value;
70 }
71
72 static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
73         const struct etnaviv_pm_domain *domain,
74         const struct etnaviv_pm_signal *signal)
75 {
76         u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
77
78         if (gpu->identity.model == chipModel_GC880 ||
79                 gpu->identity.model == chipModel_GC2000 ||
80                 gpu->identity.model == chipModel_GC2100)
81                 reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
82
83         return gpu_read(gpu, reg);
84 }
85
86 static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
87         const struct etnaviv_pm_domain *domain,
88         const struct etnaviv_pm_signal *signal)
89 {
90         u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
91
92         if (gpu->identity.model == chipModel_GC880 ||
93                 gpu->identity.model == chipModel_GC2000 ||
94                 gpu->identity.model == chipModel_GC2100)
95                 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
96
97         return gpu_read(gpu, reg);
98 }
99
100 static const struct etnaviv_pm_domain doms_3d[] = {
101         {
102                 .name = "HI",
103                 .profile_read = VIVS_MC_PROFILE_HI_READ,
104                 .profile_config = VIVS_MC_PROFILE_CONFIG2,
105                 .nr_signals = 5,
106                 .signal = (const struct etnaviv_pm_signal[]) {
107                         {
108                                 "TOTAL_CYCLES",
109                                 0,
110                                 &hi_total_cycle_read
111                         },
112                         {
113                                 "IDLE_CYCLES",
114                                 0,
115                                 &hi_total_idle_cycle_read
116                         },
117                         {
118                                 "AXI_CYCLES_READ_REQUEST_STALLED",
119                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
120                                 &perf_reg_read
121                         },
122                         {
123                                 "AXI_CYCLES_WRITE_REQUEST_STALLED",
124                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
125                                 &perf_reg_read
126                         },
127                         {
128                                 "AXI_CYCLES_WRITE_DATA_STALLED",
129                                 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
130                                 &perf_reg_read
131                         }
132                 }
133         },
134         {
135                 .name = "PE",
136                 .profile_read = VIVS_MC_PROFILE_PE_READ,
137                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
138                 .nr_signals = 4,
139                 .signal = (const struct etnaviv_pm_signal[]) {
140                         {
141                                 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
142                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
143                                 &pipe_reg_read
144                         },
145                         {
146                                 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
147                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
148                                 &pipe_reg_read
149                         },
150                         {
151                                 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
152                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
153                                 &pipe_reg_read
154                         },
155                         {
156                                 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
157                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
158                                 &pipe_reg_read
159                         }
160                 }
161         },
162         {
163                 .name = "SH",
164                 .profile_read = VIVS_MC_PROFILE_SH_READ,
165                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
166                 .nr_signals = 9,
167                 .signal = (const struct etnaviv_pm_signal[]) {
168                         {
169                                 "SHADER_CYCLES",
170                                 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
171                                 &perf_reg_read
172                         },
173                         {
174                                 "PS_INST_COUNTER",
175                                 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
176                                 &perf_reg_read
177                         },
178                         {
179                                 "RENDERED_PIXEL_COUNTER",
180                                 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
181                                 &perf_reg_read
182                         },
183                         {
184                                 "VS_INST_COUNTER",
185                                 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
186                                 &pipe_reg_read
187                         },
188                         {
189                                 "RENDERED_VERTICE_COUNTER",
190                                 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
191                                 &pipe_reg_read
192                         },
193                         {
194                                 "VTX_BRANCH_INST_COUNTER",
195                                 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
196                                 &pipe_reg_read
197                         },
198                         {
199                                 "VTX_TEXLD_INST_COUNTER",
200                                 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
201                                 &pipe_reg_read
202                         },
203                         {
204                                 "PXL_BRANCH_INST_COUNTER",
205                                 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
206                                 &pipe_reg_read
207                         },
208                         {
209                                 "PXL_TEXLD_INST_COUNTER",
210                                 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
211                                 &pipe_reg_read
212                         }
213                 }
214         },
215         {
216                 .name = "PA",
217                 .profile_read = VIVS_MC_PROFILE_PA_READ,
218                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
219                 .nr_signals = 6,
220                 .signal = (const struct etnaviv_pm_signal[]) {
221                         {
222                                 "INPUT_VTX_COUNTER",
223                                 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
224                                 &perf_reg_read
225                         },
226                         {
227                                 "INPUT_PRIM_COUNTER",
228                                 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
229                                 &perf_reg_read
230                         },
231                         {
232                                 "OUTPUT_PRIM_COUNTER",
233                                 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
234                                 &perf_reg_read
235                         },
236                         {
237                                 "DEPTH_CLIPPED_COUNTER",
238                                 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
239                                 &pipe_reg_read
240                         },
241                         {
242                                 "TRIVIAL_REJECTED_COUNTER",
243                                 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
244                                 &pipe_reg_read
245                         },
246                         {
247                                 "CULLED_COUNTER",
248                                 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
249                                 &pipe_reg_read
250                         }
251                 }
252         },
253         {
254                 .name = "SE",
255                 .profile_read = VIVS_MC_PROFILE_SE_READ,
256                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
257                 .nr_signals = 2,
258                 .signal = (const struct etnaviv_pm_signal[]) {
259                         {
260                                 "CULLED_TRIANGLE_COUNT",
261                                 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
262                                 &perf_reg_read
263                         },
264                         {
265                                 "CULLED_LINES_COUNT",
266                                 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
267                                 &perf_reg_read
268                         }
269                 }
270         },
271         {
272                 .name = "RA",
273                 .profile_read = VIVS_MC_PROFILE_RA_READ,
274                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
275                 .nr_signals = 7,
276                 .signal = (const struct etnaviv_pm_signal[]) {
277                         {
278                                 "VALID_PIXEL_COUNT",
279                                 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
280                                 &perf_reg_read
281                         },
282                         {
283                                 "TOTAL_QUAD_COUNT",
284                                 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
285                                 &perf_reg_read
286                         },
287                         {
288                                 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
289                                 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
290                                 &perf_reg_read
291                         },
292                         {
293                                 "TOTAL_PRIMITIVE_COUNT",
294                                 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
295                                 &perf_reg_read
296                         },
297                         {
298                                 "PIPE_CACHE_MISS_COUNTER",
299                                 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
300                                 &perf_reg_read
301                         },
302                         {
303                                 "PREFETCH_CACHE_MISS_COUNTER",
304                                 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
305                                 &perf_reg_read
306                         },
307                         {
308                                 "CULLED_QUAD_COUNT",
309                                 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
310                                 &perf_reg_read
311                         }
312                 }
313         },
314         {
315                 .name = "TX",
316                 .profile_read = VIVS_MC_PROFILE_TX_READ,
317                 .profile_config = VIVS_MC_PROFILE_CONFIG1,
318                 .nr_signals = 9,
319                 .signal = (const struct etnaviv_pm_signal[]) {
320                         {
321                                 "TOTAL_BILINEAR_REQUESTS",
322                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
323                                 &perf_reg_read
324                         },
325                         {
326                                 "TOTAL_TRILINEAR_REQUESTS",
327                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
328                                 &perf_reg_read
329                         },
330                         {
331                                 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
332                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
333                                 &perf_reg_read
334                         },
335                         {
336                                 "TOTAL_TEXTURE_REQUESTS",
337                                 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
338                                 &perf_reg_read
339                         },
340                         {
341                                 "MEM_READ_COUNT",
342                                 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
343                                 &perf_reg_read
344                         },
345                         {
346                                 "MEM_READ_IN_8B_COUNT",
347                                 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
348                                 &perf_reg_read
349                         },
350                         {
351                                 "CACHE_MISS_COUNT",
352                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
353                                 &perf_reg_read
354                         },
355                         {
356                                 "CACHE_HIT_TEXEL_COUNT",
357                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
358                                 &perf_reg_read
359                         },
360                         {
361                                 "CACHE_MISS_TEXEL_COUNT",
362                                 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
363                                 &perf_reg_read
364                         }
365                 }
366         },
367         {
368                 .name = "MC",
369                 .profile_read = VIVS_MC_PROFILE_MC_READ,
370                 .profile_config = VIVS_MC_PROFILE_CONFIG2,
371                 .nr_signals = 3,
372                 .signal = (const struct etnaviv_pm_signal[]) {
373                         {
374                                 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
375                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
376                                 &perf_reg_read
377                         },
378                         {
379                                 "TOTAL_READ_REQ_8B_FROM_IP",
380                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
381                                 &perf_reg_read
382                         },
383                         {
384                                 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
385                                 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
386                                 &perf_reg_read
387                         }
388                 }
389         }
390 };
391
392 static const struct etnaviv_pm_domain doms_2d[] = {
393         {
394                 .name = "PE",
395                 .profile_read = VIVS_MC_PROFILE_PE_READ,
396                 .profile_config = VIVS_MC_PROFILE_CONFIG0,
397                 .nr_signals = 1,
398                 .signal = (const struct etnaviv_pm_signal[]) {
399                         {
400                                 "PIXELS_RENDERED_2D",
401                                 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
402                                 &pipe_reg_read
403                         }
404                 }
405         }
406 };
407
408 static const struct etnaviv_pm_domain doms_vg[] = {
409 };
410
411 static const struct etnaviv_pm_domain_meta doms_meta[] = {
412         {
413                 .nr_domains = ARRAY_SIZE(doms_3d),
414                 .domains = &doms_3d[0]
415         },
416         {
417                 .nr_domains = ARRAY_SIZE(doms_2d),
418                 .domains = &doms_2d[0]
419         },
420         {
421                 .nr_domains = ARRAY_SIZE(doms_vg),
422                 .domains = &doms_vg[0]
423         }
424 };
425
426 int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
427         struct drm_etnaviv_pm_domain *domain)
428 {
429         const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe];
430         const struct etnaviv_pm_domain *dom;
431
432         if (domain->iter >= meta->nr_domains)
433                 return -EINVAL;
434
435         dom = meta->domains + domain->iter;
436
437         domain->id = domain->iter;
438         domain->nr_signals = dom->nr_signals;
439         strncpy(domain->name, dom->name, sizeof(domain->name));
440
441         domain->iter++;
442         if (domain->iter == meta->nr_domains)
443                 domain->iter = 0xff;
444
445         return 0;
446 }
447
448 int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
449         struct drm_etnaviv_pm_signal *signal)
450 {
451         const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe];
452         const struct etnaviv_pm_domain *dom;
453         const struct etnaviv_pm_signal *sig;
454
455         if (signal->domain >= meta->nr_domains)
456                 return -EINVAL;
457
458         dom = meta->domains + signal->domain;
459
460         if (signal->iter >= dom->nr_signals)
461                 return -EINVAL;
462
463         sig = &dom->signal[signal->iter];
464
465         signal->id = signal->iter;
466         strncpy(signal->name, sig->name, sizeof(signal->name));
467
468         signal->iter++;
469         if (signal->iter == dom->nr_signals)
470                 signal->iter = 0xffff;
471
472         return 0;
473 }
474
475 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
476         u32 exec_state)
477 {
478         const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
479         const struct etnaviv_pm_domain *dom;
480
481         if (r->domain >= meta->nr_domains)
482                 return -EINVAL;
483
484         dom = meta->domains + r->domain;
485
486         if (r->signal >= dom->nr_signals)
487                 return -EINVAL;
488
489         return 0;
490 }
491
492 void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
493         const struct etnaviv_perfmon_request *pmr, u32 exec_state)
494 {
495         const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
496         const struct etnaviv_pm_domain *dom;
497         const struct etnaviv_pm_signal *sig;
498         u32 *bo = pmr->bo_vma;
499         u32 val;
500
501         dom = meta->domains + pmr->domain;
502         sig = &dom->signal[pmr->signal];
503         val = sig->sample(gpu, dom, sig);
504
505         *(bo + pmr->offset) = val;
506 }