2 * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include <linux/debugfs.h>
24 #include <linux/list_sort.h>
28 struct mmio_diff_param
{
29 struct intel_vgpu
*vgpu
;
32 struct list_head diff_mmio_list
;
36 struct list_head node
;
42 /* Compare two diff_mmio items. */
43 static int mmio_offset_compare(void *priv
,
44 struct list_head
*a
, struct list_head
*b
)
49 ma
= container_of(a
, struct diff_mmio
, node
);
50 mb
= container_of(b
, struct diff_mmio
, node
);
51 if (ma
->offset
< mb
->offset
)
53 else if (ma
->offset
> mb
->offset
)
58 static inline int mmio_diff_handler(struct intel_gvt
*gvt
,
59 u32 offset
, void *data
)
61 struct mmio_diff_param
*param
= data
;
62 struct diff_mmio
*node
;
65 preg
= intel_uncore_read_notrace(gvt
->gt
->uncore
, _MMIO(offset
));
66 vreg
= vgpu_vreg(param
->vgpu
, offset
);
69 node
= kmalloc(sizeof(*node
), GFP_ATOMIC
);
73 node
->offset
= offset
;
76 list_add(&node
->node
, ¶m
->diff_mmio_list
);
83 /* Show the all the different values of tracked mmio. */
84 static int vgpu_mmio_diff_show(struct seq_file
*s
, void *unused
)
86 struct intel_vgpu
*vgpu
= s
->private;
87 struct intel_gvt
*gvt
= vgpu
->gvt
;
88 struct mmio_diff_param param
= {
93 struct diff_mmio
*node
, *next
;
95 INIT_LIST_HEAD(¶m
.diff_mmio_list
);
97 mutex_lock(&gvt
->lock
);
98 spin_lock_bh(&gvt
->scheduler
.mmio_context_lock
);
100 mmio_hw_access_pre(gvt
->gt
);
101 /* Recognize all the diff mmios to list. */
102 intel_gvt_for_each_tracked_mmio(gvt
, mmio_diff_handler
, ¶m
);
103 mmio_hw_access_post(gvt
->gt
);
105 spin_unlock_bh(&gvt
->scheduler
.mmio_context_lock
);
106 mutex_unlock(&gvt
->lock
);
108 /* In an ascending order by mmio offset. */
109 list_sort(NULL
, ¶m
.diff_mmio_list
, mmio_offset_compare
);
111 seq_printf(s
, "%-8s %-8s %-8s %-8s\n", "Offset", "HW", "vGPU", "Diff");
112 list_for_each_entry_safe(node
, next
, ¶m
.diff_mmio_list
, node
) {
113 u32 diff
= node
->preg
^ node
->vreg
;
115 seq_printf(s
, "%08x %08x %08x %*pbl\n",
116 node
->offset
, node
->preg
, node
->vreg
,
118 list_del(&node
->node
);
121 seq_printf(s
, "Total: %d, Diff: %d\n", param
.total
, param
.diff
);
124 DEFINE_SHOW_ATTRIBUTE(vgpu_mmio_diff
);
127 vgpu_scan_nonprivbb_get(void *data
, u64
*val
)
129 struct intel_vgpu
*vgpu
= (struct intel_vgpu
*)data
;
131 *val
= vgpu
->scan_nonprivbb
;
136 * set/unset bit engine_id of vgpu->scan_nonprivbb to turn on/off scanning
137 * of non-privileged batch buffer. e.g.
138 * if vgpu->scan_nonprivbb=3, then it will scan non-privileged batch buffer
142 vgpu_scan_nonprivbb_set(void *data
, u64 val
)
144 struct intel_vgpu
*vgpu
= (struct intel_vgpu
*)data
;
146 vgpu
->scan_nonprivbb
= val
;
150 DEFINE_SIMPLE_ATTRIBUTE(vgpu_scan_nonprivbb_fops
,
151 vgpu_scan_nonprivbb_get
, vgpu_scan_nonprivbb_set
,
155 * intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU
158 void intel_gvt_debugfs_add_vgpu(struct intel_vgpu
*vgpu
)
162 snprintf(name
, 16, "vgpu%d", vgpu
->id
);
163 vgpu
->debugfs
= debugfs_create_dir(name
, vgpu
->gvt
->debugfs_root
);
165 debugfs_create_bool("active", 0444, vgpu
->debugfs
, &vgpu
->active
);
166 debugfs_create_file("mmio_diff", 0444, vgpu
->debugfs
, vgpu
,
167 &vgpu_mmio_diff_fops
);
168 debugfs_create_file("scan_nonprivbb", 0644, vgpu
->debugfs
, vgpu
,
169 &vgpu_scan_nonprivbb_fops
);
173 * intel_gvt_debugfs_remove_vgpu - remove debugfs entries of a vGPU
176 void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu
*vgpu
)
178 debugfs_remove_recursive(vgpu
->debugfs
);
179 vgpu
->debugfs
= NULL
;
183 * intel_gvt_debugfs_init - register gvt debugfs root entry
186 void intel_gvt_debugfs_init(struct intel_gvt
*gvt
)
188 struct drm_minor
*minor
= gvt
->gt
->i915
->drm
.primary
;
190 gvt
->debugfs_root
= debugfs_create_dir("gvt", minor
->debugfs_root
);
192 debugfs_create_ulong("num_tracked_mmio", 0444, gvt
->debugfs_root
,
193 &gvt
->mmio
.num_tracked_mmio
);
197 * intel_gvt_debugfs_clean - remove debugfs entries
200 void intel_gvt_debugfs_clean(struct intel_gvt
*gvt
)
202 debugfs_remove_recursive(gvt
->debugfs_root
);
203 gvt
->debugfs_root
= NULL
;