xref: /linux/drivers/gpu/drm/xe/xe_debugfs.c (revision 992694ad28584188725751f695a85661e8e3797a)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "xe_debugfs.h"
7 
8 #include <linux/debugfs.h>
9 #include <linux/fault-inject.h>
10 #include <linux/string_helpers.h>
11 
12 #include <drm/drm_debugfs.h>
13 
14 #include "regs/xe_pmt.h"
15 #include "xe_bo.h"
16 #include "xe_device.h"
17 #include "xe_force_wake.h"
18 #include "xe_gt.h"
19 #include "xe_gt_debugfs.h"
20 #include "xe_gt_printk.h"
21 #include "xe_guc_ads.h"
22 #include "xe_hw_engine.h"
23 #include "xe_mmio.h"
24 #include "xe_pm.h"
25 #include "xe_psmi.h"
26 #include "xe_pxp_debugfs.h"
27 #include "xe_sriov.h"
28 #include "xe_sriov_pf_debugfs.h"
29 #include "xe_sriov_vf.h"
30 #include "xe_step.h"
31 #include "xe_tile_debugfs.h"
32 #include "xe_vsec.h"
33 #include "xe_wa.h"
34 
35 #ifdef CONFIG_DRM_XE_DEBUG
36 #include "xe_bo_evict.h"
37 #include "xe_migrate.h"
38 #include "xe_vm.h"
39 #endif
40 
41 DECLARE_FAULT_ATTR(gt_reset_failure);
42 DECLARE_FAULT_ATTR(inject_csc_hw_error);
43 
44 static void read_residency_counter(struct xe_device *xe, struct xe_mmio *mmio,
45 				   u32 offset, const char *name, struct drm_printer *p)
46 {
47 	u64 residency = 0;
48 	int ret;
49 
50 	ret = xe_pmt_telem_read(xe->drm.dev,
51 				xe_mmio_read32(mmio, PUNIT_TELEMETRY_GUID),
52 				&residency, offset, sizeof(residency));
53 	if (ret != sizeof(residency)) {
54 		drm_warn(&xe->drm, "%s counter failed to read, ret %d\n", name, ret);
55 		return;
56 	}
57 
58 	drm_printf(p, "%s : %llu\n", name, residency);
59 }
60 
61 static struct xe_device *node_to_xe(struct drm_info_node *node)
62 {
63 	return to_xe_device(node->minor->dev);
64 }
65 
66 static void print_engine_class_mask(struct drm_printer *p, u16 mask)
67 {
68 	if (!mask) {
69 		drm_printf(p, " none\n");
70 		return;
71 	}
72 
73 	for (enum xe_engine_class ec = 0; ec < XE_ENGINE_CLASS_MAX; ec++) {
74 		if (mask & BIT(ec))
75 			drm_printf(p, " %s", xe_hw_engine_class_to_str(ec));
76 	}
77 	drm_printf(p, "\n");
78 }
79 
80 static void print_engine_mask(struct drm_printer *p, struct xe_gt *gt, u64 mask)
81 {
82 	struct xe_hw_engine *hwe;
83 	enum xe_hw_engine_id id;
84 
85 	if (!mask) {
86 		drm_printf(p, " none\n");
87 		return;
88 	}
89 
90 	for_each_hw_engine(hwe, gt, id) {
91 		if (mask & BIT_ULL(id))
92 			drm_printf(p, " %s", hwe->name);
93 	}
94 	drm_printf(p, "\n");
95 }
96 
97 static int info(struct seq_file *m, void *data)
98 {
99 	struct xe_device *xe = node_to_xe(m->private);
100 	struct drm_printer p = drm_seq_file_printer(m);
101 	struct xe_gt *gt;
102 	u8 id;
103 
104 	guard(xe_pm_runtime)(xe);
105 
106 	drm_printf(&p, "graphics_verx100 %d\n", xe->info.graphics_verx100);
107 	drm_printf(&p, "media_verx100 %d\n", xe->info.media_verx100);
108 	drm_printf(&p, "stepping G:%s M:%s B:%s\n",
109 		   xe_step_name(xe->info.step.graphics),
110 		   xe_step_name(xe->info.step.media),
111 		   xe_step_name(xe->info.step.basedie));
112 	drm_printf(&p, "is_dgfx %s\n", str_yes_no(xe->info.is_dgfx));
113 	drm_printf(&p, "platform %d\n", xe->info.platform);
114 	drm_printf(&p, "subplatform %d\n",
115 		   xe->info.subplatform > XE_SUBPLATFORM_NONE ? xe->info.subplatform : 0);
116 	drm_printf(&p, "devid 0x%x\n", xe->info.devid);
117 	drm_printf(&p, "revid %d\n", xe->info.revid);
118 	drm_printf(&p, "tile_count %d\n", xe->info.tile_count);
119 	drm_printf(&p, "vm_max_level %d\n", xe->info.vm_max_level);
120 	drm_printf(&p, "has_flat_ccs %s\n", str_yes_no(xe->info.has_flat_ccs));
121 	drm_printf(&p, "has_usm %s\n", str_yes_no(xe->info.has_usm));
122 	drm_printf(&p, "skip_guc_pc %s\n", str_yes_no(xe->info.skip_guc_pc));
123 	drm_printf(&p, "multi_lrc_engine_classes");
124 	print_engine_class_mask(&p, xe->info.multi_lrc_mask);
125 	for_each_gt(gt, xe, id) {
126 		drm_printf(&p, "gt%d force wake %d\n", id,
127 			   xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT));
128 		drm_printf(&p, "gt%d engines", id);
129 		print_engine_mask(&p, gt, gt->info.engine_mask);
130 		drm_printf(&p, "gt%d multi_queue_engine_classes", id);
131 		print_engine_class_mask(&p, gt->info.multi_queue_engine_class_mask);
132 	}
133 
134 	return 0;
135 }
136 
137 static int sriov_info(struct seq_file *m, void *data)
138 {
139 	struct xe_device *xe = node_to_xe(m->private);
140 	struct drm_printer p = drm_seq_file_printer(m);
141 
142 	xe_sriov_print_info(xe, &p);
143 	return 0;
144 }
145 
146 static int workarounds(struct xe_device *xe, struct drm_printer *p)
147 {
148 	guard(xe_pm_runtime)(xe);
149 	xe_wa_device_dump(xe, p);
150 
151 	return 0;
152 }
153 
154 static int workaround_info(struct seq_file *m, void *data)
155 {
156 	struct xe_device *xe = node_to_xe(m->private);
157 	struct drm_printer p = drm_seq_file_printer(m);
158 
159 	workarounds(xe, &p);
160 	return 0;
161 }
162 
163 static int dgfx_pkg_residencies_show(struct seq_file *m, void *data)
164 {
165 	struct xe_device *xe;
166 	struct xe_mmio *mmio;
167 	struct drm_printer p;
168 
169 	xe = node_to_xe(m->private);
170 	p = drm_seq_file_printer(m);
171 	guard(xe_pm_runtime)(xe);
172 	mmio = xe_root_tile_mmio(xe);
173 	static const struct {
174 		u32 offset;
175 		const char *name;
176 	} residencies[] = {
177 		{BMG_G2_RESIDENCY_OFFSET, "Package G2"},
178 		{BMG_G6_RESIDENCY_OFFSET, "Package G6"},
179 		{BMG_G7_RESIDENCY_OFFSET, "Package G7"},
180 		{BMG_G8_RESIDENCY_OFFSET, "Package G8"},
181 		{BMG_G10_RESIDENCY_OFFSET, "Package G10"},
182 		{BMG_MODS_RESIDENCY_OFFSET, "Package ModS"}
183 	};
184 
185 	for (int i = 0; i < ARRAY_SIZE(residencies); i++)
186 		read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p);
187 
188 	return 0;
189 }
190 
191 static int dgfx_pcie_link_residencies_show(struct seq_file *m, void *data)
192 {
193 	struct xe_device *xe;
194 	struct xe_mmio *mmio;
195 	struct drm_printer p;
196 
197 	xe = node_to_xe(m->private);
198 	p = drm_seq_file_printer(m);
199 	guard(xe_pm_runtime)(xe);
200 	mmio = xe_root_tile_mmio(xe);
201 
202 	static const struct {
203 		u32 offset;
204 		const char *name;
205 	} residencies[] = {
206 		{BMG_PCIE_LINK_L0_RESIDENCY_OFFSET, "PCIE LINK L0 RESIDENCY"},
207 		{BMG_PCIE_LINK_L1_RESIDENCY_OFFSET, "PCIE LINK L1 RESIDENCY"},
208 		{BMG_PCIE_LINK_L1_2_RESIDENCY_OFFSET, "PCIE LINK L1.2 RESIDENCY"}
209 	};
210 
211 	for (int i = 0; i < ARRAY_SIZE(residencies); i++)
212 		read_residency_counter(xe, mmio, residencies[i].offset, residencies[i].name, &p);
213 
214 	return 0;
215 }
216 
217 static const struct drm_info_list debugfs_list[] = {
218 	{"info", info, 0},
219 	{ .name = "sriov_info", .show = sriov_info, },
220 	{ .name = "workarounds", .show = workaround_info, },
221 };
222 
223 static const struct drm_info_list debugfs_residencies[] = {
224 	{ .name = "dgfx_pkg_residencies", .show = dgfx_pkg_residencies_show, },
225 	{ .name = "dgfx_pcie_link_residencies", .show = dgfx_pcie_link_residencies_show, },
226 };
227 
228 static int forcewake_open(struct inode *inode, struct file *file)
229 {
230 	struct xe_device *xe = inode->i_private;
231 	struct xe_gt *gt;
232 	u8 id, last_gt;
233 	unsigned int fw_ref;
234 
235 	xe_pm_runtime_get(xe);
236 	for_each_gt(gt, xe, id) {
237 		last_gt = id;
238 
239 		fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
240 		if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
241 			goto err_fw_get;
242 	}
243 
244 	return 0;
245 
246 err_fw_get:
247 	for_each_gt(gt, xe, id) {
248 		if (id < last_gt)
249 			xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
250 		else if (id == last_gt)
251 			xe_force_wake_put(gt_to_fw(gt), fw_ref);
252 		else
253 			break;
254 	}
255 
256 	xe_pm_runtime_put(xe);
257 	return -ETIMEDOUT;
258 }
259 
260 static int forcewake_release(struct inode *inode, struct file *file)
261 {
262 	struct xe_device *xe = inode->i_private;
263 	struct xe_gt *gt;
264 	u8 id;
265 
266 	for_each_gt(gt, xe, id)
267 		xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
268 	xe_pm_runtime_put(xe);
269 
270 	return 0;
271 }
272 
273 static const struct file_operations forcewake_all_fops = {
274 	.owner = THIS_MODULE,
275 	.open = forcewake_open,
276 	.release = forcewake_release,
277 };
278 
279 static ssize_t wedged_mode_show(struct file *f, char __user *ubuf,
280 				size_t size, loff_t *pos)
281 {
282 	struct xe_device *xe = file_inode(f)->i_private;
283 	char buf[32];
284 	int len = 0;
285 
286 	len = scnprintf(buf, sizeof(buf), "%d\n", xe->wedged.mode);
287 
288 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
289 }
290 
291 static int __wedged_mode_set_reset_policy(struct xe_gt *gt, enum xe_wedged_mode mode)
292 {
293 	bool enable_engine_reset;
294 	int ret;
295 
296 	enable_engine_reset = (mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET);
297 	ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads,
298 						       enable_engine_reset);
299 	if (ret)
300 		xe_gt_err(gt, "Failed to update GuC ADS scheduler policy (%pe)\n", ERR_PTR(ret));
301 
302 	return ret;
303 }
304 
305 static int wedged_mode_set_reset_policy(struct xe_device *xe, enum xe_wedged_mode mode)
306 {
307 	struct xe_gt *gt;
308 	int ret;
309 	u8 id;
310 
311 	guard(xe_pm_runtime)(xe);
312 	for_each_gt(gt, xe, id) {
313 		ret = __wedged_mode_set_reset_policy(gt, mode);
314 		if (ret) {
315 			if (id > 0) {
316 				xe->wedged.inconsistent_reset = true;
317 				drm_err(&xe->drm, "Inconsistent reset policy state between GTs\n");
318 			}
319 			return ret;
320 		}
321 	}
322 
323 	xe->wedged.inconsistent_reset = false;
324 
325 	return 0;
326 }
327 
328 static bool wedged_mode_needs_policy_update(struct xe_device *xe, enum xe_wedged_mode mode)
329 {
330 	if (xe->wedged.inconsistent_reset)
331 		return true;
332 
333 	if (xe->wedged.mode == mode)
334 		return false;
335 
336 	if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET ||
337 	    mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)
338 		return true;
339 
340 	return false;
341 }
342 
343 static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
344 			       size_t size, loff_t *pos)
345 {
346 	struct xe_device *xe = file_inode(f)->i_private;
347 	u32 wedged_mode;
348 	ssize_t ret;
349 
350 	ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode);
351 	if (ret)
352 		return ret;
353 
354 	ret = xe_device_validate_wedged_mode(xe, wedged_mode);
355 	if (ret)
356 		return ret;
357 
358 	if (wedged_mode_needs_policy_update(xe, wedged_mode)) {
359 		ret = wedged_mode_set_reset_policy(xe, wedged_mode);
360 		if (ret)
361 			return ret;
362 	}
363 
364 	xe->wedged.mode = wedged_mode;
365 
366 	return size;
367 }
368 
369 static const struct file_operations wedged_mode_fops = {
370 	.owner = THIS_MODULE,
371 	.read = wedged_mode_show,
372 	.write = wedged_mode_set,
373 };
374 
375 static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
376 					   size_t size, loff_t *pos)
377 {
378 	struct xe_device *xe = file_inode(f)->i_private;
379 	char buf[8];
380 	int len;
381 
382 	len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
383 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
384 }
385 
386 static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
387 					  size_t size, loff_t *pos)
388 {
389 	struct xe_device *xe = file_inode(f)->i_private;
390 	bool val;
391 	ssize_t ret;
392 
393 	ret = kstrtobool_from_user(ubuf, size, &val);
394 	if (ret)
395 		return ret;
396 
397 	xe->info.has_page_reclaim_hw_assist = val;
398 
399 	return size;
400 }
401 
402 static const struct file_operations page_reclaim_hw_assist_fops = {
403 	.owner = THIS_MODULE,
404 	.read = page_reclaim_hw_assist_show,
405 	.write = page_reclaim_hw_assist_set,
406 };
407 
408 static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
409 					    size_t size, loff_t *pos)
410 {
411 	struct xe_device *xe = file_inode(f)->i_private;
412 	char buf[32];
413 	int len = 0;
414 
415 	len = scnprintf(buf, sizeof(buf), "%d\n", xe->atomic_svm_timeslice_ms);
416 
417 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
418 }
419 
420 static ssize_t atomic_svm_timeslice_ms_set(struct file *f,
421 					   const char __user *ubuf,
422 					   size_t size, loff_t *pos)
423 {
424 	struct xe_device *xe = file_inode(f)->i_private;
425 	u32 atomic_svm_timeslice_ms;
426 	ssize_t ret;
427 
428 	ret = kstrtouint_from_user(ubuf, size, 0, &atomic_svm_timeslice_ms);
429 	if (ret)
430 		return ret;
431 
432 	xe->atomic_svm_timeslice_ms = atomic_svm_timeslice_ms;
433 
434 	return size;
435 }
436 
437 static const struct file_operations atomic_svm_timeslice_ms_fops = {
438 	.owner = THIS_MODULE,
439 	.read = atomic_svm_timeslice_ms_show,
440 	.write = atomic_svm_timeslice_ms_set,
441 };
442 
443 static ssize_t min_run_period_lr_ms_show(struct file *f, char __user *ubuf,
444 					 size_t size, loff_t *pos)
445 {
446 	struct xe_device *xe = file_inode(f)->i_private;
447 	char buf[32];
448 	int len = 0;
449 
450 	len = scnprintf(buf, sizeof(buf), "%d\n", xe->min_run_period_lr_ms);
451 
452 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
453 }
454 
455 static ssize_t min_run_period_lr_ms_set(struct file *f, const char __user *ubuf,
456 					size_t size, loff_t *pos)
457 {
458 	struct xe_device *xe = file_inode(f)->i_private;
459 	u32 min_run_period_lr_ms;
460 	ssize_t ret;
461 
462 	ret = kstrtouint_from_user(ubuf, size, 0, &min_run_period_lr_ms);
463 	if (ret)
464 		return ret;
465 
466 	xe->min_run_period_lr_ms = min_run_period_lr_ms;
467 
468 	return size;
469 }
470 
471 static const struct file_operations min_run_period_lr_ms_fops = {
472 	.owner = THIS_MODULE,
473 	.read = min_run_period_lr_ms_show,
474 	.write = min_run_period_lr_ms_set,
475 };
476 
477 static ssize_t min_run_period_pf_ms_show(struct file *f, char __user *ubuf,
478 					 size_t size, loff_t *pos)
479 {
480 	struct xe_device *xe = file_inode(f)->i_private;
481 	char buf[32];
482 	int len = 0;
483 
484 	len = scnprintf(buf, sizeof(buf), "%d\n", xe->min_run_period_pf_ms);
485 
486 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
487 }
488 
489 static ssize_t min_run_period_pf_ms_set(struct file *f, const char __user *ubuf,
490 					size_t size, loff_t *pos)
491 {
492 	struct xe_device *xe = file_inode(f)->i_private;
493 	u32 min_run_period_pf_ms;
494 	ssize_t ret;
495 
496 	ret = kstrtouint_from_user(ubuf, size, 0, &min_run_period_pf_ms);
497 	if (ret)
498 		return ret;
499 
500 	xe->min_run_period_pf_ms = min_run_period_pf_ms;
501 
502 	return size;
503 }
504 
505 static const struct file_operations min_run_period_pf_ms_fops = {
506 	.owner = THIS_MODULE,
507 	.read = min_run_period_pf_ms_show,
508 	.write = min_run_period_pf_ms_set,
509 };
510 
511 static ssize_t disable_late_binding_show(struct file *f, char __user *ubuf,
512 					 size_t size, loff_t *pos)
513 {
514 	struct xe_device *xe = file_inode(f)->i_private;
515 	struct xe_late_bind *late_bind = &xe->late_bind;
516 	char buf[32];
517 	int len;
518 
519 	len = scnprintf(buf, sizeof(buf), "%d\n", late_bind->disable);
520 
521 	return simple_read_from_buffer(ubuf, size, pos, buf, len);
522 }
523 
524 static ssize_t disable_late_binding_set(struct file *f, const char __user *ubuf,
525 					size_t size, loff_t *pos)
526 {
527 	struct xe_device *xe = file_inode(f)->i_private;
528 	struct xe_late_bind *late_bind = &xe->late_bind;
529 	bool val;
530 	int ret;
531 
532 	ret = kstrtobool_from_user(ubuf, size, &val);
533 	if (ret)
534 		return ret;
535 
536 	late_bind->disable = val;
537 	return size;
538 }
539 
540 static const struct file_operations disable_late_binding_fops = {
541 	.owner = THIS_MODULE,
542 	.read = disable_late_binding_show,
543 	.write = disable_late_binding_set,
544 };
545 
546 void xe_debugfs_register(struct xe_device *xe)
547 {
548 	struct ttm_device *bdev = &xe->ttm;
549 	struct drm_minor *minor = xe->drm.primary;
550 	struct dentry *root = minor->debugfs_root;
551 	struct ttm_resource_manager *man;
552 	struct xe_tile *tile;
553 	struct xe_gt *gt;
554 	u8 tile_id;
555 	u8 id;
556 
557 	drm_debugfs_create_files(debugfs_list,
558 				 ARRAY_SIZE(debugfs_list),
559 				 root, minor);
560 
561 	if (xe->info.platform == XE_BATTLEMAGE && !IS_SRIOV_VF(xe)) {
562 		drm_debugfs_create_files(debugfs_residencies,
563 					 ARRAY_SIZE(debugfs_residencies),
564 					 root, minor);
565 		fault_create_debugfs_attr("inject_csc_hw_error", root,
566 					  &inject_csc_hw_error);
567 	}
568 
569 	debugfs_create_file("forcewake_all", 0400, root, xe,
570 			    &forcewake_all_fops);
571 
572 	debugfs_create_file("wedged_mode", 0600, root, xe,
573 			    &wedged_mode_fops);
574 
575 	debugfs_create_file("atomic_svm_timeslice_ms", 0600, root, xe,
576 			    &atomic_svm_timeslice_ms_fops);
577 
578 	debugfs_create_file("min_run_period_lr_ms", 0600, root, xe,
579 			    &min_run_period_lr_ms_fops);
580 
581 	debugfs_create_file("min_run_period_pf_ms", 0600, root, xe,
582 			    &min_run_period_pf_ms_fops);
583 
584 	debugfs_create_file("disable_late_binding", 0600, root, xe,
585 			    &disable_late_binding_fops);
586 
587 	/*
588 	 * Don't expose page reclaim configuration file if not supported by the
589 	 * hardware initially.
590 	 */
591 	if (xe->info.has_page_reclaim_hw_assist)
592 		debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
593 				    &page_reclaim_hw_assist_fops);
594 
595 	man = ttm_manager_type(bdev, XE_PL_TT);
596 	ttm_resource_manager_create_debugfs(man, root, "gtt_mm");
597 
598 	man = ttm_manager_type(bdev, XE_PL_STOLEN);
599 	if (man)
600 		ttm_resource_manager_create_debugfs(man, root, "stolen_mm");
601 
602 	for_each_tile(tile, xe, tile_id)
603 		xe_tile_debugfs_register(tile);
604 
605 	for_each_gt(gt, xe, id)
606 		xe_gt_debugfs_register(gt);
607 
608 	xe_pxp_debugfs_register(xe->pxp);
609 
610 	xe_psmi_debugfs_register(xe);
611 
612 	fault_create_debugfs_attr("fail_gt_reset", root, &gt_reset_failure);
613 
614 	if (IS_SRIOV_PF(xe))
615 		xe_sriov_pf_debugfs_register(xe, root);
616 	else if (IS_SRIOV_VF(xe))
617 		xe_sriov_vf_debugfs_register(xe, root);
618 }
619