summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/regops_gk20a.c
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2014-03-19 03:38:25 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:08:53 -0400
commita9785995d5f22aaeb659285f8aeb64d8b56982e0 (patch)
treecc75f75bcf43db316a002a7a240b81f299bf6d7f /drivers/gpu/nvgpu/gk20a/regops_gk20a.c
parent61efaf843c22b85424036ec98015121c08f5f16c (diff)
gpu: nvgpu: Add NVIDIA GPU Driver
This patch moves the NVIDIA GPU driver to a new location. Bug 1482562 Change-Id: I24293810b9d0f1504fd9be00135e21dad656ccb6 Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-on: http://git-master/r/383722 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/regops_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/regops_gk20a.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/regops_gk20a.c b/drivers/gpu/nvgpu/gk20a/regops_gk20a.c
new file mode 100644
index 00000000..4a115fb1
--- /dev/null
+++ b/drivers/gpu/nvgpu/gk20a/regops_gk20a.c
@@ -0,0 +1,704 @@
1/*
2 *
3 * Tegra GK20A GPU Debugger Driver Register Ops
4 *
5 * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/slab.h>
21#include <linux/err.h>
22#include <linux/bsearch.h>
23#include <linux/nvhost_dbg_gpu_ioctl.h>
24
25#include "gk20a.h"
26#include "gr_gk20a.h"
27#include "dbg_gpu_gk20a.h"
28#include "regops_gk20a.h"
29
30
31
32struct regop_offset_range {
33 u32 base:24;
34 u32 count:8;
35};
36
37static int regop_bsearch_range_cmp(const void *pkey, const void *pelem)
38{
39 u32 key = *(u32 *)pkey;
40 struct regop_offset_range *prange = (struct regop_offset_range *)pelem;
41 if (key < prange->base)
42 return -1;
43 else if (prange->base <= key && key < (prange->base +
44 (prange->count * 4)))
45 return 0;
46 return 1;
47}
48
49static inline bool linear_search(u32 offset, const u32 *list, int size)
50{
51 int i;
52 for (i = 0; i < size; i++)
53 if (list[i] == offset)
54 return true;
55 return false;
56}
57
58static const struct regop_offset_range gk20a_global_whitelist_ranges[] = {
59 { 0x000004f0, 1 },
60 { 0x00001a00, 3 },
61 { 0x0000259c, 1 },
62 { 0x0000280c, 1 },
63 { 0x00009400, 1 },
64 { 0x00009410, 1 },
65 { 0x00020200, 1 },
66 { 0x00022430, 7 },
67 { 0x00022548, 1 },
68 { 0x00100c18, 3 },
69 { 0x00100c84, 1 },
70 { 0x00100cc4, 1 },
71 { 0x00106640, 1 },
72 { 0x0010a0a8, 1 },
73 { 0x0010a4f0, 1 },
74 { 0x0010e064, 1 },
75 { 0x0010e164, 1 },
76 { 0x0010e490, 1 },
77 { 0x00110100, 1 },
78 { 0x00140028, 1 },
79 { 0x001408dc, 1 },
80 { 0x00140a5c, 1 },
81 { 0x001410dc, 1 },
82 { 0x0014125c, 1 },
83 { 0x0017e028, 1 },
84 { 0x0017e8dc, 1 },
85 { 0x0017ea5c, 1 },
86 { 0x0017f0dc, 1 },
87 { 0x0017f25c, 1 },
88 { 0x00180000, 68 },
89 { 0x00180200, 68 },
90 { 0x001a0000, 68 },
91 { 0x001b0000, 68 },
92 { 0x001b0200, 68 },
93 { 0x001b0400, 68 },
94 { 0x001b0600, 68 },
95 { 0x001b4000, 3 },
96 { 0x001b4010, 3 },
97 { 0x001b4020, 3 },
98 { 0x001b4040, 3 },
99 { 0x001b4050, 3 },
100 { 0x001b4060, 16 },
101 { 0x001b40a4, 1 },
102 { 0x001b4100, 6 },
103 { 0x001b4124, 2 },
104 { 0x001b8000, 7 },
105 { 0x001bc000, 7 },
106 { 0x001be000, 7 },
107 { 0x00400500, 1 },
108 { 0x00400700, 1 },
109 { 0x0040415c, 1 },
110 { 0x00405850, 1 },
111 { 0x00405908, 1 },
112 { 0x00405b40, 1 },
113 { 0x00405b50, 1 },
114 { 0x00406024, 1 },
115 { 0x00407010, 1 },
116 { 0x00407808, 1 },
117 { 0x0040803c, 1 },
118 { 0x0040880c, 1 },
119 { 0x00408910, 1 },
120 { 0x00408984, 1 },
121 { 0x004090a8, 1 },
122 { 0x004098a0, 1 },
123 { 0x0041000c, 1 },
124 { 0x00410110, 1 },
125 { 0x00410184, 1 },
126 { 0x00418384, 1 },
127 { 0x004184a0, 1 },
128 { 0x00418604, 1 },
129 { 0x00418680, 1 },
130 { 0x00418714, 1 },
131 { 0x0041881c, 1 },
132 { 0x004188c8, 2 },
133 { 0x00418b04, 1 },
134 { 0x00418c04, 1 },
135 { 0x00418c64, 2 },
136 { 0x00418c88, 1 },
137 { 0x00418cb4, 2 },
138 { 0x00418d00, 1 },
139 { 0x00418d28, 2 },
140 { 0x00418e08, 1 },
141 { 0x00418e1c, 2 },
142 { 0x00418f08, 1 },
143 { 0x00418f20, 2 },
144 { 0x00419000, 1 },
145 { 0x0041900c, 1 },
146 { 0x00419018, 1 },
147 { 0x00419854, 1 },
148 { 0x00419ab0, 1 },
149 { 0x00419ab8, 3 },
150 { 0x00419ac8, 1 },
151 { 0x00419c0c, 1 },
152 { 0x00419c8c, 3 },
153 { 0x00419ca8, 1 },
154 { 0x00419d08, 2 },
155 { 0x00419e00, 1 },
156 { 0x00419e0c, 1 },
157 { 0x00419e14, 2 },
158 { 0x00419e24, 2 },
159 { 0x00419e34, 2 },
160 { 0x00419e44, 4 },
161 { 0x00419ea4, 1 },
162 { 0x00419eb0, 1 },
163 { 0x0041a0a0, 1 },
164 { 0x0041a0a8, 1 },
165 { 0x0041a17c, 1 },
166 { 0x0041a890, 2 },
167 { 0x0041a8a0, 3 },
168 { 0x0041a8b0, 2 },
169 { 0x0041b014, 1 },
170 { 0x0041b0a0, 1 },
171 { 0x0041b0cc, 1 },
172 { 0x0041b0e8, 2 },
173 { 0x0041b1dc, 1 },
174 { 0x0041b1f8, 2 },
175 { 0x0041be14, 1 },
176 { 0x0041bea0, 1 },
177 { 0x0041becc, 1 },
178 { 0x0041bee8, 2 },
179 { 0x0041bfdc, 1 },
180 { 0x0041bff8, 2 },
181 { 0x0041c054, 1 },
182 { 0x0041c2b0, 1 },
183 { 0x0041c2b8, 3 },
184 { 0x0041c2c8, 1 },
185 { 0x0041c40c, 1 },
186 { 0x0041c48c, 3 },
187 { 0x0041c4a8, 1 },
188 { 0x0041c508, 2 },
189 { 0x0041c600, 1 },
190 { 0x0041c60c, 1 },
191 { 0x0041c614, 2 },
192 { 0x0041c624, 2 },
193 { 0x0041c634, 2 },
194 { 0x0041c644, 4 },
195 { 0x0041c6a4, 1 },
196 { 0x0041c6b0, 1 },
197 { 0x00500384, 1 },
198 { 0x005004a0, 1 },
199 { 0x00500604, 1 },
200 { 0x00500680, 1 },
201 { 0x00500714, 1 },
202 { 0x0050081c, 1 },
203 { 0x005008c8, 2 },
204 { 0x00500b04, 1 },
205 { 0x00500c04, 1 },
206 { 0x00500c64, 2 },
207 { 0x00500c88, 1 },
208 { 0x00500cb4, 2 },
209 { 0x00500d00, 1 },
210 { 0x00500d28, 2 },
211 { 0x00500e08, 1 },
212 { 0x00500e1c, 2 },
213 { 0x00500f08, 1 },
214 { 0x00500f20, 2 },
215 { 0x00501000, 1 },
216 { 0x0050100c, 1 },
217 { 0x00501018, 1 },
218 { 0x00501854, 1 },
219 { 0x00501ab0, 1 },
220 { 0x00501ab8, 3 },
221 { 0x00501ac8, 1 },
222 { 0x00501c0c, 1 },
223 { 0x00501c8c, 3 },
224 { 0x00501ca8, 1 },
225 { 0x00501d08, 2 },
226 { 0x00501e00, 1 },
227 { 0x00501e0c, 1 },
228 { 0x00501e14, 2 },
229 { 0x00501e24, 2 },
230 { 0x00501e34, 2 },
231 { 0x00501e44, 4 },
232 { 0x00501ea4, 1 },
233 { 0x00501eb0, 1 },
234 { 0x005020a0, 1 },
235 { 0x005020a8, 1 },
236 { 0x0050217c, 1 },
237 { 0x00502890, 2 },
238 { 0x005028a0, 3 },
239 { 0x005028b0, 2 },
240 { 0x00503014, 1 },
241 { 0x005030a0, 1 },
242 { 0x005030cc, 1 },
243 { 0x005030e8, 2 },
244 { 0x005031dc, 1 },
245 { 0x005031f8, 2 },
246 { 0x00503e14, 1 },
247 { 0x00503ea0, 1 },
248 { 0x00503ecc, 1 },
249 { 0x00503ee8, 2 },
250 { 0x00503fdc, 1 },
251 { 0x00503ff8, 2 },
252 { 0x00504054, 1 },
253 { 0x005042b0, 1 },
254 { 0x005042b8, 3 },
255 { 0x005042c8, 1 },
256 { 0x0050440c, 1 },
257 { 0x0050448c, 3 },
258 { 0x005044a8, 1 },
259 { 0x00504508, 2 },
260 { 0x00504600, 1 },
261 { 0x0050460c, 1 },
262 { 0x00504614, 2 },
263 { 0x00504624, 2 },
264 { 0x00504634, 2 },
265 { 0x00504644, 4 },
266 { 0x005046a4, 1 },
267 { 0x005046b0, 1 },
268};
269static const u32 gk20a_global_whitelist_ranges_count =
270 ARRAY_SIZE(gk20a_global_whitelist_ranges);
271
272/* context */
273
274static const struct regop_offset_range gk20a_context_whitelist_ranges[] = {
275 { 0x0000280c, 1 },
276 { 0x00100cc4, 1 },
277 { 0x00400500, 1 },
278 { 0x00405b40, 1 },
279 { 0x00419000, 1 },
280 { 0x00419c8c, 3 },
281 { 0x00419d08, 2 },
282 { 0x00419e04, 3 },
283 { 0x00419e14, 2 },
284 { 0x00419e24, 2 },
285 { 0x00419e34, 2 },
286 { 0x00419e44, 4 },
287 { 0x00419e58, 6 },
288 { 0x00419e84, 5 },
289 { 0x00419ea4, 1 },
290 { 0x00419eac, 2 },
291 { 0x00419f30, 8 },
292 { 0x0041c48c, 3 },
293 { 0x0041c508, 2 },
294 { 0x0041c604, 3 },
295 { 0x0041c614, 2 },
296 { 0x0041c624, 2 },
297 { 0x0041c634, 2 },
298 { 0x0041c644, 4 },
299 { 0x0041c658, 6 },
300 { 0x0041c684, 5 },
301 { 0x0041c6a4, 1 },
302 { 0x0041c6ac, 2 },
303 { 0x0041c730, 8 },
304 { 0x00501000, 1 },
305 { 0x00501c8c, 3 },
306 { 0x00501d08, 2 },
307 { 0x00501e04, 3 },
308 { 0x00501e14, 2 },
309 { 0x00501e24, 2 },
310 { 0x00501e34, 2 },
311 { 0x00501e44, 4 },
312 { 0x00501e58, 6 },
313 { 0x00501e84, 5 },
314 { 0x00501ea4, 1 },
315 { 0x00501eac, 2 },
316 { 0x00501f30, 8 },
317 { 0x0050448c, 3 },
318 { 0x00504508, 2 },
319 { 0x00504604, 3 },
320 { 0x00504614, 2 },
321 { 0x00504624, 2 },
322 { 0x00504634, 2 },
323 { 0x00504644, 4 },
324 { 0x00504658, 6 },
325 { 0x00504684, 5 },
326 { 0x005046a4, 1 },
327 { 0x005046ac, 2 },
328 { 0x00504730, 8 },
329};
330static const u32 gk20a_context_whitelist_ranges_count =
331 ARRAY_SIZE(gk20a_context_whitelist_ranges);
332
333/* runcontrol */
334static const u32 gk20a_runcontrol_whitelist[] = {
335 0x00419e10,
336 0x0041c610,
337 0x00501e10,
338 0x00504610,
339};
340static const u32 gk20a_runcontrol_whitelist_count =
341 ARRAY_SIZE(gk20a_runcontrol_whitelist);
342
343static const struct regop_offset_range gk20a_runcontrol_whitelist_ranges[] = {
344 { 0x00419e10, 1 },
345 { 0x0041c610, 1 },
346 { 0x00501e10, 1 },
347 { 0x00504610, 1 },
348};
349static const u32 gk20a_runcontrol_whitelist_ranges_count =
350 ARRAY_SIZE(gk20a_runcontrol_whitelist_ranges);
351
352
353/* quad ctl */
354static const u32 gk20a_qctl_whitelist[] = {
355 0x00504670,
356 0x00504674,
357 0x00504678,
358 0x0050467c,
359 0x00504680,
360 0x00504730,
361 0x00504734,
362 0x00504738,
363 0x0050473c,
364};
365static const u32 gk20a_qctl_whitelist_count =
366 ARRAY_SIZE(gk20a_qctl_whitelist);
367
368static const struct regop_offset_range gk20a_qctl_whitelist_ranges[] = {
369 { 0x00504670, 1 },
370 { 0x00504730, 4 },
371};
372static const u32 gk20a_qctl_whitelist_ranges_count =
373 ARRAY_SIZE(gk20a_qctl_whitelist_ranges);
374
375
376
377
378static bool validate_reg_ops(struct dbg_session_gk20a *dbg_s,
379 u32 *ctx_rd_count, u32 *ctx_wr_count,
380 struct nvhost_dbg_gpu_reg_op *ops,
381 u32 op_count);
382
383
384int exec_regops_gk20a(struct dbg_session_gk20a *dbg_s,
385 struct nvhost_dbg_gpu_reg_op *ops,
386 u64 num_ops)
387{
388 int err = 0, i;
389 struct channel_gk20a *ch = NULL;
390 struct gk20a *g = dbg_s->g;
391 /*struct gr_gk20a *gr = &g->gr;*/
392 u32 data32_lo = 0, data32_hi = 0;
393 u32 ctx_rd_count = 0, ctx_wr_count = 0;
394 bool skip_read_lo, skip_read_hi;
395 bool ok;
396
397 gk20a_dbg(gpu_dbg_fn | gpu_dbg_gpu_dbg, "");
398
399 ch = dbg_s->ch;
400
401 ok = validate_reg_ops(dbg_s,
402 &ctx_rd_count, &ctx_wr_count,
403 ops, num_ops);
404 if (!ok) {
405 dev_err(dbg_s->dev, "invalid op(s)");
406 err = -EINVAL;
407 /* each op has its own err/status */
408 goto clean_up;
409 }
410
411 for (i = 0; i < num_ops; i++) {
412 /* if it isn't global then it is done in the ctx ops... */
413 if (ops[i].type != REGOP(TYPE_GLOBAL))
414 continue;
415
416 switch (ops[i].op) {
417
418 case REGOP(READ_32):
419 ops[i].value_hi = 0;
420 ops[i].value_lo = gk20a_readl(g, ops[i].offset);
421 gk20a_dbg(gpu_dbg_gpu_dbg, "read_32 0x%08x from 0x%08x",
422 ops[i].value_lo, ops[i].offset);
423
424 break;
425
426 case REGOP(READ_64):
427 ops[i].value_lo = gk20a_readl(g, ops[i].offset);
428 ops[i].value_hi =
429 gk20a_readl(g, ops[i].offset + 4);
430
431 gk20a_dbg(gpu_dbg_gpu_dbg, "read_64 0x%08x:%08x from 0x%08x",
432 ops[i].value_hi, ops[i].value_lo,
433 ops[i].offset);
434 break;
435
436 case REGOP(WRITE_32):
437 case REGOP(WRITE_64):
438 /* some of this appears wonky/unnecessary but
439 we've kept it for compat with existing
440 debugger code. just in case... */
441 skip_read_lo = skip_read_hi = false;
442 if (ops[i].and_n_mask_lo == ~(u32)0) {
443 data32_lo = ops[i].value_lo;
444 skip_read_lo = true;
445 }
446
447 if ((ops[i].op == REGOP(WRITE_64)) &&
448 (ops[i].and_n_mask_hi == ~(u32)0)) {
449 data32_hi = ops[i].value_hi;
450 skip_read_hi = true;
451 }
452
453 /* read first 32bits */
454 if (unlikely(skip_read_lo == false)) {
455 data32_lo = gk20a_readl(g, ops[i].offset);
456 data32_lo &= ~ops[i].and_n_mask_lo;
457 data32_lo |= ops[i].value_lo;
458 }
459
460 /* if desired, read second 32bits */
461 if ((ops[i].op == REGOP(WRITE_64)) &&
462 !skip_read_hi) {
463 data32_hi = gk20a_readl(g, ops[i].offset + 4);
464 data32_hi &= ~ops[i].and_n_mask_hi;
465 data32_hi |= ops[i].value_hi;
466 }
467
468 /* now update first 32bits */
469 gk20a_writel(g, ops[i].offset, data32_lo);
470 gk20a_dbg(gpu_dbg_gpu_dbg, "Wrote 0x%08x to 0x%08x ",
471 data32_lo, ops[i].offset);
472 /* if desired, update second 32bits */
473 if (ops[i].op == REGOP(WRITE_64)) {
474 gk20a_writel(g, ops[i].offset + 4, data32_hi);
475 gk20a_dbg(gpu_dbg_gpu_dbg, "Wrote 0x%08x to 0x%08x ",
476 data32_hi, ops[i].offset + 4);
477
478 }
479
480
481 break;
482
483 /* shouldn't happen as we've already screened */
484 default:
485 BUG();
486 err = -EINVAL;
487 goto clean_up;
488 break;
489 }
490 }
491
492 if (ctx_wr_count | ctx_rd_count) {
493 err = gr_gk20a_exec_ctx_ops(ch, ops, num_ops,
494 ctx_wr_count, ctx_rd_count);
495 if (err) {
496 dev_warn(dbg_s->dev,
497 "failed to perform ctx ops\n");
498 goto clean_up;
499 }
500 }
501
502 clean_up:
503 gk20a_dbg(gpu_dbg_gpu_dbg, "ret=%d", err);
504 return err;
505
506}
507
508
509static int validate_reg_op_info(struct dbg_session_gk20a *dbg_s,
510 struct nvhost_dbg_gpu_reg_op *op)
511{
512 int err = 0;
513
514 op->status = REGOP(STATUS_SUCCESS);
515
516 switch (op->op) {
517 case REGOP(READ_32):
518 case REGOP(READ_64):
519 case REGOP(WRITE_32):
520 case REGOP(WRITE_64):
521 break;
522 default:
523 op->status |= REGOP(STATUS_UNSUPPORTED_OP);
524 /*gk20a_err(dbg_s->dev, "Invalid regops op %d!", op->op);*/
525 err = -EINVAL;
526 break;
527 }
528
529 switch (op->type) {
530 case REGOP(TYPE_GLOBAL):
531 case REGOP(TYPE_GR_CTX):
532 case REGOP(TYPE_GR_CTX_TPC):
533 case REGOP(TYPE_GR_CTX_SM):
534 case REGOP(TYPE_GR_CTX_CROP):
535 case REGOP(TYPE_GR_CTX_ZROP):
536 case REGOP(TYPE_GR_CTX_QUAD):
537 break;
538 /*
539 case NVHOST_DBG_GPU_REG_OP_TYPE_FB:
540 */
541 default:
542 op->status |= REGOP(STATUS_INVALID_TYPE);
543 /*gk20a_err(dbg_s->dev, "Invalid regops type %d!", op->type);*/
544 err = -EINVAL;
545 break;
546 }
547
548 return err;
549}
550
551static bool check_whitelists(struct dbg_session_gk20a *dbg_s,
552 struct nvhost_dbg_gpu_reg_op *op, u32 offset)
553{
554 bool valid = false;
555
556 if (op->type == REGOP(TYPE_GLOBAL)) {
557 /* search global list */
558 valid = !!bsearch(&offset,
559 gk20a_global_whitelist_ranges,
560 gk20a_global_whitelist_ranges_count,
561 sizeof(*gk20a_global_whitelist_ranges),
562 regop_bsearch_range_cmp);
563
564 /* if debug session and channel is bound search context list */
565 if ((!valid) && (!dbg_s->is_profiler && dbg_s->ch)) {
566 /* binary search context list */
567 valid = !!bsearch(&offset,
568 gk20a_context_whitelist_ranges,
569 gk20a_context_whitelist_ranges_count,
570 sizeof(*gk20a_context_whitelist_ranges),
571 regop_bsearch_range_cmp);
572 }
573
574 /* if debug session and channel is bound search runcontrol list */
575 if ((!valid) && (!dbg_s->is_profiler && dbg_s->ch)) {
576 valid = linear_search(offset,
577 gk20a_runcontrol_whitelist,
578 gk20a_runcontrol_whitelist_count);
579 }
580 } else if (op->type == REGOP(TYPE_GR_CTX)) {
581 /* it's a context-relative op */
582 if (!dbg_s->ch) {
583 gk20a_err(dbg_s->dev, "can't perform ctx regop unless bound");
584 op->status = REGOP(STATUS_UNSUPPORTED_OP);
585 return -ENODEV;
586 }
587
588 /* binary search context list */
589 valid = !!bsearch(&offset,
590 gk20a_context_whitelist_ranges,
591 gk20a_context_whitelist_ranges_count,
592 sizeof(*gk20a_context_whitelist_ranges),
593 regop_bsearch_range_cmp);
594
595 /* if debug session and channel is bound search runcontrol list */
596 if ((!valid) && (!dbg_s->is_profiler && dbg_s->ch)) {
597 valid = linear_search(offset,
598 gk20a_runcontrol_whitelist,
599 gk20a_runcontrol_whitelist_count);
600 }
601
602 } else if (op->type == REGOP(TYPE_GR_CTX_QUAD)) {
603 valid = linear_search(offset,
604 gk20a_qctl_whitelist,
605 gk20a_qctl_whitelist_count);
606 }
607
608 return valid;
609}
610
611/* note: the op here has already been through validate_reg_op_info */
612static int validate_reg_op_offset(struct dbg_session_gk20a *dbg_s,
613 struct nvhost_dbg_gpu_reg_op *op)
614{
615 int err;
616 u32 buf_offset_lo, buf_offset_addr, num_offsets, offset;
617 bool valid = false;
618
619 op->status = 0;
620 offset = op->offset;
621
622 /* support only 24-bit 4-byte aligned offsets */
623 if (offset & 0xFF000003) {
624 gk20a_err(dbg_s->dev, "invalid regop offset: 0x%x\n", offset);
625 op->status |= REGOP(STATUS_INVALID_OFFSET);
626 return -EINVAL;
627 }
628
629 valid = check_whitelists(dbg_s, op, offset);
630 if ((op->op == REGOP(READ_64) || op->op == REGOP(WRITE_64)) && valid)
631 valid = check_whitelists(dbg_s, op, offset + 4);
632
633 if (valid && (op->type != REGOP(TYPE_GLOBAL))) {
634 err = gr_gk20a_get_ctx_buffer_offsets(dbg_s->g,
635 op->offset,
636 1,
637 &buf_offset_lo,
638 &buf_offset_addr,
639 &num_offsets,
640 op->type == REGOP(TYPE_GR_CTX_QUAD),
641 op->quad);
642 if (err) {
643 op->status |= REGOP(STATUS_INVALID_OFFSET);
644 return -EINVAL;
645 }
646 if (!buf_offset_lo) {
647 op->status |= REGOP(STATUS_INVALID_OFFSET);
648 return -EINVAL;
649 }
650 }
651
652 if (!valid) {
653 gk20a_err(dbg_s->dev, "invalid regop offset: 0x%x\n", offset);
654 op->status |= REGOP(STATUS_INVALID_OFFSET);
655 return -EINVAL;
656 }
657
658 return 0;
659}
660
661static bool validate_reg_ops(struct dbg_session_gk20a *dbg_s,
662 u32 *ctx_rd_count, u32 *ctx_wr_count,
663 struct nvhost_dbg_gpu_reg_op *ops,
664 u32 op_count)
665{
666 u32 i;
667 int err;
668 bool ok = true;
669
670 /* keep going until the end so every op can get
671 * a separate error code if needed */
672 for (i = 0; i < op_count; i++) {
673
674 err = validate_reg_op_info(dbg_s, &ops[i]);
675 ok &= !err;
676
677 if (reg_op_is_gr_ctx(ops[i].type)) {
678 if (reg_op_is_read(ops[i].op))
679 (*ctx_rd_count)++;
680 else
681 (*ctx_wr_count)++;
682 }
683
684 err = validate_reg_op_offset(dbg_s, &ops[i]);
685 ok &= !err;
686 }
687
688 gk20a_dbg(gpu_dbg_gpu_dbg, "ctx_wrs:%d ctx_rds:%d\n",
689 *ctx_wr_count, *ctx_rd_count);
690
691 return ok;
692}
693
694/* exported for tools like cyclestats, etc */
695bool is_bar0_global_offset_whitelisted_gk20a(u32 offset)
696{
697
698 bool valid = !!bsearch(&offset,
699 gk20a_global_whitelist_ranges,
700 gk20a_global_whitelist_ranges_count,
701 sizeof(*gk20a_global_whitelist_ranges),
702 regop_bsearch_range_cmp);
703 return valid;
704}