xref: /openbmc/linux/drivers/gpu/drm/i915/gvt/debugfs.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1bc7b0be3SChangbin Du /*
2bc7b0be3SChangbin Du  * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
3bc7b0be3SChangbin Du  *
4bc7b0be3SChangbin Du  * Permission is hereby granted, free of charge, to any person obtaining a
5bc7b0be3SChangbin Du  * copy of this software and associated documentation files (the "Software"),
6bc7b0be3SChangbin Du  * to deal in the Software without restriction, including without limitation
7bc7b0be3SChangbin Du  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bc7b0be3SChangbin Du  * and/or sell copies of the Software, and to permit persons to whom the
9bc7b0be3SChangbin Du  * Software is furnished to do so, subject to the following conditions:
10bc7b0be3SChangbin Du  *
11bc7b0be3SChangbin Du  * The above copyright notice and this permission notice (including the next
12bc7b0be3SChangbin Du  * paragraph) shall be included in all copies or substantial portions of the
13bc7b0be3SChangbin Du  * Software.
14bc7b0be3SChangbin Du  *
15bc7b0be3SChangbin Du  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bc7b0be3SChangbin Du  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bc7b0be3SChangbin Du  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bc7b0be3SChangbin Du  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bc7b0be3SChangbin Du  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bc7b0be3SChangbin Du  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bc7b0be3SChangbin Du  * SOFTWARE.
22bc7b0be3SChangbin Du  */
23bc7b0be3SChangbin Du #include <linux/debugfs.h>
24cea9083eSChangbin Du #include <linux/list_sort.h>
25bc7b0be3SChangbin Du #include "i915_drv.h"
26bc7b0be3SChangbin Du #include "gvt.h"
27bc7b0be3SChangbin Du 
28cea9083eSChangbin Du struct mmio_diff_param {
29cea9083eSChangbin Du 	struct intel_vgpu *vgpu;
30cea9083eSChangbin Du 	int total;
31cea9083eSChangbin Du 	int diff;
32cea9083eSChangbin Du 	struct list_head diff_mmio_list;
33cea9083eSChangbin Du };
34cea9083eSChangbin Du 
35cea9083eSChangbin Du struct diff_mmio {
36cea9083eSChangbin Du 	struct list_head node;
37cea9083eSChangbin Du 	u32 offset;
38cea9083eSChangbin Du 	u32 preg;
39cea9083eSChangbin Du 	u32 vreg;
40cea9083eSChangbin Du };
41cea9083eSChangbin Du 
42cea9083eSChangbin Du /* Compare two diff_mmio items. */
mmio_offset_compare(void * priv,const struct list_head * a,const struct list_head * b)43cea9083eSChangbin Du static int mmio_offset_compare(void *priv,
444f0f586bSSami Tolvanen 	const struct list_head *a, const struct list_head *b)
45cea9083eSChangbin Du {
46cea9083eSChangbin Du 	struct diff_mmio *ma;
47cea9083eSChangbin Du 	struct diff_mmio *mb;
48cea9083eSChangbin Du 
49cea9083eSChangbin Du 	ma = container_of(a, struct diff_mmio, node);
50cea9083eSChangbin Du 	mb = container_of(b, struct diff_mmio, node);
51cea9083eSChangbin Du 	if (ma->offset < mb->offset)
52cea9083eSChangbin Du 		return -1;
53cea9083eSChangbin Du 	else if (ma->offset > mb->offset)
54cea9083eSChangbin Du 		return 1;
55cea9083eSChangbin Du 	return 0;
56cea9083eSChangbin Du }
57cea9083eSChangbin Du 
mmio_diff_handler(struct intel_gvt * gvt,u32 offset,void * data)58cea9083eSChangbin Du static inline int mmio_diff_handler(struct intel_gvt *gvt,
59cea9083eSChangbin Du 				    u32 offset, void *data)
60cea9083eSChangbin Du {
61cea9083eSChangbin Du 	struct mmio_diff_param *param = data;
62cea9083eSChangbin Du 	struct diff_mmio *node;
63cea9083eSChangbin Du 	u32 preg, vreg;
64cea9083eSChangbin Du 
65a61ac1e7SChris Wilson 	preg = intel_uncore_read_notrace(gvt->gt->uncore, _MMIO(offset));
66cea9083eSChangbin Du 	vreg = vgpu_vreg(param->vgpu, offset);
67cea9083eSChangbin Du 
68cea9083eSChangbin Du 	if (preg != vreg) {
69a291e4fbSColin Xu 		node = kmalloc(sizeof(*node), GFP_ATOMIC);
70cea9083eSChangbin Du 		if (!node)
71cea9083eSChangbin Du 			return -ENOMEM;
72cea9083eSChangbin Du 
73cea9083eSChangbin Du 		node->offset = offset;
74cea9083eSChangbin Du 		node->preg = preg;
75cea9083eSChangbin Du 		node->vreg = vreg;
76cea9083eSChangbin Du 		list_add(&node->node, &param->diff_mmio_list);
77cea9083eSChangbin Du 		param->diff++;
78cea9083eSChangbin Du 	}
79cea9083eSChangbin Du 	param->total++;
80cea9083eSChangbin Du 	return 0;
81cea9083eSChangbin Du }
82cea9083eSChangbin Du 
83cea9083eSChangbin Du /* Show the all the different values of tracked mmio. */
vgpu_mmio_diff_show(struct seq_file * s,void * unused)84cea9083eSChangbin Du static int vgpu_mmio_diff_show(struct seq_file *s, void *unused)
85cea9083eSChangbin Du {
86cea9083eSChangbin Du 	struct intel_vgpu *vgpu = s->private;
87cea9083eSChangbin Du 	struct intel_gvt *gvt = vgpu->gvt;
88cea9083eSChangbin Du 	struct mmio_diff_param param = {
89cea9083eSChangbin Du 		.vgpu = vgpu,
90cea9083eSChangbin Du 		.total = 0,
91cea9083eSChangbin Du 		.diff = 0,
92cea9083eSChangbin Du 	};
93cea9083eSChangbin Du 	struct diff_mmio *node, *next;
94cea9083eSChangbin Du 
95cea9083eSChangbin Du 	INIT_LIST_HEAD(&param.diff_mmio_list);
96cea9083eSChangbin Du 
97cea9083eSChangbin Du 	mutex_lock(&gvt->lock);
98cea9083eSChangbin Du 	spin_lock_bh(&gvt->scheduler.mmio_context_lock);
99cea9083eSChangbin Du 
100a61ac1e7SChris Wilson 	mmio_hw_access_pre(gvt->gt);
101cea9083eSChangbin Du 	/* Recognize all the diff mmios to list. */
102cea9083eSChangbin Du 	intel_gvt_for_each_tracked_mmio(gvt, mmio_diff_handler, &param);
103a61ac1e7SChris Wilson 	mmio_hw_access_post(gvt->gt);
104cea9083eSChangbin Du 
105cea9083eSChangbin Du 	spin_unlock_bh(&gvt->scheduler.mmio_context_lock);
106cea9083eSChangbin Du 	mutex_unlock(&gvt->lock);
107cea9083eSChangbin Du 
108cea9083eSChangbin Du 	/* In an ascending order by mmio offset. */
109cea9083eSChangbin Du 	list_sort(NULL, &param.diff_mmio_list, mmio_offset_compare);
110cea9083eSChangbin Du 
111cea9083eSChangbin Du 	seq_printf(s, "%-8s %-8s %-8s %-8s\n", "Offset", "HW", "vGPU", "Diff");
112cea9083eSChangbin Du 	list_for_each_entry_safe(node, next, &param.diff_mmio_list, node) {
113cea9083eSChangbin Du 		u32 diff = node->preg ^ node->vreg;
114cea9083eSChangbin Du 
115cea9083eSChangbin Du 		seq_printf(s, "%08x %08x %08x %*pbl\n",
116cea9083eSChangbin Du 			   node->offset, node->preg, node->vreg,
117cea9083eSChangbin Du 			   32, &diff);
118cea9083eSChangbin Du 		list_del(&node->node);
119cea9083eSChangbin Du 		kfree(node);
120cea9083eSChangbin Du 	}
121cea9083eSChangbin Du 	seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff);
122cea9083eSChangbin Du 	return 0;
123cea9083eSChangbin Du }
124e4006713SAndy Shevchenko DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff);
125bc7b0be3SChangbin Du 
12696bebe39SZhao Yan static int
vgpu_scan_nonprivbb_get(void * data,u64 * val)12796bebe39SZhao Yan vgpu_scan_nonprivbb_get(void *data, u64 *val)
12896bebe39SZhao Yan {
12996bebe39SZhao Yan 	struct intel_vgpu *vgpu = (struct intel_vgpu *)data;
130aa444fc7SChris Wilson 
13196bebe39SZhao Yan 	*val = vgpu->scan_nonprivbb;
13296bebe39SZhao Yan 	return 0;
13396bebe39SZhao Yan }
13496bebe39SZhao Yan 
13596bebe39SZhao Yan /*
13696bebe39SZhao Yan  * set/unset bit engine_id of vgpu->scan_nonprivbb to turn on/off scanning
13796bebe39SZhao Yan  * of non-privileged batch buffer. e.g.
13896bebe39SZhao Yan  * if vgpu->scan_nonprivbb=3, then it will scan non-privileged batch buffer
13996bebe39SZhao Yan  * on engine 0 and 1.
14096bebe39SZhao Yan  */
14196bebe39SZhao Yan static int
vgpu_scan_nonprivbb_set(void * data,u64 val)14296bebe39SZhao Yan vgpu_scan_nonprivbb_set(void *data, u64 val)
14396bebe39SZhao Yan {
14496bebe39SZhao Yan 	struct intel_vgpu *vgpu = (struct intel_vgpu *)data;
14596bebe39SZhao Yan 
14696bebe39SZhao Yan 	vgpu->scan_nonprivbb = val;
14796bebe39SZhao Yan 	return 0;
14896bebe39SZhao Yan }
14996bebe39SZhao Yan 
150*84edc94eSDeepak R Varma DEFINE_DEBUGFS_ATTRIBUTE(vgpu_scan_nonprivbb_fops,
15196bebe39SZhao Yan 			 vgpu_scan_nonprivbb_get, vgpu_scan_nonprivbb_set,
15296bebe39SZhao Yan 			 "0x%llx\n");
15396bebe39SZhao Yan 
vgpu_status_get(void * data,u64 * val)154a06d4b9eSZhi Wang static int vgpu_status_get(void *data, u64 *val)
155a06d4b9eSZhi Wang {
156a06d4b9eSZhi Wang 	struct intel_vgpu *vgpu = (struct intel_vgpu *)data;
157a06d4b9eSZhi Wang 
158a06d4b9eSZhi Wang 	*val = 0;
159a06d4b9eSZhi Wang 
160a06d4b9eSZhi Wang 	if (test_bit(INTEL_VGPU_STATUS_ATTACHED, vgpu->status))
161a06d4b9eSZhi Wang 		*val |= (1 << INTEL_VGPU_STATUS_ATTACHED);
162a06d4b9eSZhi Wang 	if (test_bit(INTEL_VGPU_STATUS_ACTIVE, vgpu->status))
163a06d4b9eSZhi Wang 		*val |= (1 << INTEL_VGPU_STATUS_ACTIVE);
164a06d4b9eSZhi Wang 
165a06d4b9eSZhi Wang 	return 0;
166a06d4b9eSZhi Wang }
167a06d4b9eSZhi Wang 
168*84edc94eSDeepak R Varma DEFINE_DEBUGFS_ATTRIBUTE(vgpu_status_fops, vgpu_status_get, NULL, "0x%llx\n");
169a06d4b9eSZhi Wang 
170bc7b0be3SChangbin Du /**
171bc7b0be3SChangbin Du  * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU
172bc7b0be3SChangbin Du  * @vgpu: a vGPU
173bc7b0be3SChangbin Du  */
intel_gvt_debugfs_add_vgpu(struct intel_vgpu * vgpu)174f8871ec8SGreg Kroah-Hartman void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu)
175bc7b0be3SChangbin Du {
1764feeea1dSAleksei Gimbitskii 	char name[16] = "";
177bc7b0be3SChangbin Du 
1784feeea1dSAleksei Gimbitskii 	snprintf(name, 16, "vgpu%d", vgpu->id);
179bc7b0be3SChangbin Du 	vgpu->debugfs = debugfs_create_dir(name, vgpu->gvt->debugfs_root);
180bc7b0be3SChangbin Du 
181f8871ec8SGreg Kroah-Hartman 	debugfs_create_file("mmio_diff", 0444, vgpu->debugfs, vgpu,
182f8871ec8SGreg Kroah-Hartman 			    &vgpu_mmio_diff_fops);
183*84edc94eSDeepak R Varma 	debugfs_create_file_unsafe("scan_nonprivbb", 0644, vgpu->debugfs, vgpu,
184f8871ec8SGreg Kroah-Hartman 				   &vgpu_scan_nonprivbb_fops);
185*84edc94eSDeepak R Varma 	debugfs_create_file_unsafe("status", 0644, vgpu->debugfs, vgpu,
186a06d4b9eSZhi Wang 				   &vgpu_status_fops);
187bc7b0be3SChangbin Du }
188bc7b0be3SChangbin Du 
189bc7b0be3SChangbin Du /**
190bc7b0be3SChangbin Du  * intel_gvt_debugfs_remove_vgpu - remove debugfs entries of a vGPU
191bc7b0be3SChangbin Du  * @vgpu: a vGPU
192bc7b0be3SChangbin Du  */
intel_gvt_debugfs_remove_vgpu(struct intel_vgpu * vgpu)193bc7b0be3SChangbin Du void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu)
194bc7b0be3SChangbin Du {
195704f3384SZhenyu Wang 	struct intel_gvt *gvt = vgpu->gvt;
196704f3384SZhenyu Wang 	struct drm_minor *minor = gvt->gt->i915->drm.primary;
197704f3384SZhenyu Wang 
198704f3384SZhenyu Wang 	if (minor->debugfs_root && gvt->debugfs_root) {
199bc7b0be3SChangbin Du 		debugfs_remove_recursive(vgpu->debugfs);
200bc7b0be3SChangbin Du 		vgpu->debugfs = NULL;
201bc7b0be3SChangbin Du 	}
202704f3384SZhenyu Wang }
203bc7b0be3SChangbin Du 
204bc7b0be3SChangbin Du /**
205bc7b0be3SChangbin Du  * intel_gvt_debugfs_init - register gvt debugfs root entry
206bc7b0be3SChangbin Du  * @gvt: GVT device
207bc7b0be3SChangbin Du  */
intel_gvt_debugfs_init(struct intel_gvt * gvt)208f8871ec8SGreg Kroah-Hartman void intel_gvt_debugfs_init(struct intel_gvt *gvt)
209bc7b0be3SChangbin Du {
210a61ac1e7SChris Wilson 	struct drm_minor *minor = gvt->gt->i915->drm.primary;
211bc7b0be3SChangbin Du 
212bc7b0be3SChangbin Du 	gvt->debugfs_root = debugfs_create_dir("gvt", minor->debugfs_root);
213bc7b0be3SChangbin Du 
214f8871ec8SGreg Kroah-Hartman 	debugfs_create_ulong("num_tracked_mmio", 0444, gvt->debugfs_root,
215bc7b0be3SChangbin Du 			     &gvt->mmio.num_tracked_mmio);
216bc7b0be3SChangbin Du }
217bc7b0be3SChangbin Du 
218bc7b0be3SChangbin Du /**
219bc7b0be3SChangbin Du  * intel_gvt_debugfs_clean - remove debugfs entries
220bc7b0be3SChangbin Du  * @gvt: GVT device
221bc7b0be3SChangbin Du  */
intel_gvt_debugfs_clean(struct intel_gvt * gvt)222bc7b0be3SChangbin Du void intel_gvt_debugfs_clean(struct intel_gvt *gvt)
223bc7b0be3SChangbin Du {
224c4b850d1SZhenyu Wang 	struct drm_minor *minor = gvt->gt->i915->drm.primary;
225c4b850d1SZhenyu Wang 
226c4b850d1SZhenyu Wang 	if (minor->debugfs_root) {
227bc7b0be3SChangbin Du 		debugfs_remove_recursive(gvt->debugfs_root);
228bc7b0be3SChangbin Du 		gvt->debugfs_root = NULL;
229bc7b0be3SChangbin Du 	}
230c4b850d1SZhenyu Wang }
231