xref: /linux/drivers/gpu/drm/xe/xe_psmi.c (revision 55a42f78ffd386e01a5404419f8c5ded7db70a21)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <linux/debugfs.h>
7 
8 #include "xe_bo.h"
9 #include "xe_device.h"
10 #include "xe_configfs.h"
11 #include "xe_psmi.h"
12 
13 /*
14  * PSMI capture support
15  *
16  * Requirement for PSMI capture is to have a physically contiguous buffer.  The
17  * PSMI tool owns doing all necessary configuration (MMIO register writes are
18  * done from user-space). However, KMD needs to provide the PSMI tool with the
19  * required physical address of the base of PSMI buffer in case of VRAM.
20  *
21  * VRAM backed PSMI buffer:
22  * Buffer is allocated as GEM object and with XE_BO_CREATE_PINNED_BIT flag which
23  * creates a contiguous allocation. The physical address is returned from
24  * psmi_debugfs_capture_addr_show(). PSMI tool can mmap the buffer via the
25  * PCIBAR through sysfs.
26  *
27  * SYSTEM memory backed PSMI buffer:
28  * Interface here does not support allocating from SYSTEM memory region.  The
29  * PSMI tool needs to allocate memory themselves using hugetlbfs. In order to
30  * get the physical address, user-space can query /proc/[pid]/pagemap. As an
31  * alternative, CMA debugfs could also be used to allocate reserved CMA memory.
32  */
33 
34 static bool psmi_enabled(struct xe_device *xe)
35 {
36 	return xe_configfs_get_psmi_enabled(to_pci_dev(xe->drm.dev));
37 }
38 
39 static void psmi_free_object(struct xe_bo *bo)
40 {
41 	xe_bo_lock(bo, NULL);
42 	xe_bo_unpin(bo);
43 	xe_bo_unlock(bo);
44 	xe_bo_put(bo);
45 }
46 
47 /*
48  * Free PSMI capture buffer objects.
49  */
50 static void psmi_cleanup(struct xe_device *xe)
51 {
52 	unsigned long id, region_mask = xe->psmi.region_mask;
53 	struct xe_bo *bo;
54 
55 	for_each_set_bit(id, &region_mask,
56 			 ARRAY_SIZE(xe->psmi.capture_obj)) {
57 		/* smem should never be set */
58 		xe_assert(xe, id);
59 
60 		bo = xe->psmi.capture_obj[id];
61 		if (bo) {
62 			psmi_free_object(bo);
63 			xe->psmi.capture_obj[id] = NULL;
64 		}
65 	}
66 }
67 
68 static struct xe_bo *psmi_alloc_object(struct xe_device *xe,
69 				       unsigned int id, size_t bo_size)
70 {
71 	struct xe_tile *tile;
72 
73 	if (!id || !bo_size)
74 		return NULL;
75 
76 	tile = &xe->tiles[id - 1];
77 
78 	/* VRAM: Allocate GEM object for the capture buffer */
79 	return xe_bo_create_pin_range_novm(xe, tile, bo_size, 0, ~0ull,
80 					   ttm_bo_type_kernel,
81 					   XE_BO_FLAG_VRAM_IF_DGFX(tile) |
82 					   XE_BO_FLAG_PINNED |
83 					   XE_BO_FLAG_PINNED_LATE_RESTORE |
84 					   XE_BO_FLAG_NEEDS_CPU_ACCESS);
85 }
86 
87 /*
88  * Allocate PSMI capture buffer objects (via debugfs set function), based on
89  * which regions the user has selected in region_mask.  @size: size in bytes
90  * (should be power of 2)
91  *
92  * Always release/free the current buffer objects before attempting to allocate
93  * new ones.  Size == 0 will free all current buffers.
94  *
95  * Note, we don't write any registers as the capture tool is already configuring
96  * all PSMI registers itself via mmio space.
97  */
98 static int psmi_resize_object(struct xe_device *xe, size_t size)
99 {
100 	unsigned long id, region_mask = xe->psmi.region_mask;
101 	struct xe_bo *bo = NULL;
102 	int err = 0;
103 
104 	/* if resizing, free currently allocated buffers first */
105 	psmi_cleanup(xe);
106 
107 	/* can set size to 0, in which case, now done */
108 	if (!size)
109 		return 0;
110 
111 	for_each_set_bit(id, &region_mask,
112 			 ARRAY_SIZE(xe->psmi.capture_obj)) {
113 		/* smem should never be set */
114 		xe_assert(xe, id);
115 
116 		bo = psmi_alloc_object(xe, id, size);
117 		if (IS_ERR(bo)) {
118 			err = PTR_ERR(bo);
119 			break;
120 		}
121 		xe->psmi.capture_obj[id] = bo;
122 
123 		drm_info(&xe->drm,
124 			 "PSMI capture size requested: %zu bytes, allocated: %lu:%zu\n",
125 			 size, id, bo ? xe_bo_size(bo) : 0);
126 	}
127 
128 	/* on error, reverse what was allocated */
129 	if (err)
130 		psmi_cleanup(xe);
131 
132 	return err;
133 }
134 
135 /*
136  * Returns an address for the capture tool to use to find start of capture
137  * buffer. Capture tool requires the capability to have a buffer allocated per
138  * each tile (VRAM region), thus we return an address for each region.
139  */
140 static int psmi_debugfs_capture_addr_show(struct seq_file *m, void *data)
141 {
142 	struct xe_device *xe = m->private;
143 	unsigned long id, region_mask;
144 	struct xe_bo *bo;
145 	u64 val;
146 
147 	region_mask = xe->psmi.region_mask;
148 	for_each_set_bit(id, &region_mask,
149 			 ARRAY_SIZE(xe->psmi.capture_obj)) {
150 		/* smem should never be set */
151 		xe_assert(xe, id);
152 
153 		/* VRAM region */
154 		bo = xe->psmi.capture_obj[id];
155 		if (!bo)
156 			continue;
157 
158 		/* pinned, so don't need bo_lock */
159 		val = __xe_bo_addr(bo, 0, PAGE_SIZE);
160 		seq_printf(m, "%ld: 0x%llx\n", id, val);
161 	}
162 
163 	return 0;
164 }
165 
166 /*
167  * Return capture buffer size, using the size from first allocated object that
168  * is found. This works because all objects must be of the same size.
169  */
170 static int psmi_debugfs_capture_size_get(void *data, u64 *val)
171 {
172 	unsigned long id, region_mask;
173 	struct xe_device *xe = data;
174 	struct xe_bo *bo;
175 
176 	region_mask = xe->psmi.region_mask;
177 	for_each_set_bit(id, &region_mask,
178 			 ARRAY_SIZE(xe->psmi.capture_obj)) {
179 		/* smem should never be set */
180 		xe_assert(xe, id);
181 
182 		bo = xe->psmi.capture_obj[id];
183 		if (bo) {
184 			*val = xe_bo_size(bo);
185 			return 0;
186 		}
187 	}
188 
189 	/* no capture objects are allocated */
190 	*val = 0;
191 
192 	return 0;
193 }
194 
195 /*
196  * Set size of PSMI capture buffer. This triggers the allocation of capture
197  * buffer in each memory region as specified with prior write to
198  * psmi_capture_region_mask.
199  */
200 static int psmi_debugfs_capture_size_set(void *data, u64 val)
201 {
202 	struct xe_device *xe = data;
203 
204 	/* user must have specified at least one region */
205 	if (!xe->psmi.region_mask)
206 		return -EINVAL;
207 
208 	return psmi_resize_object(xe, val);
209 }
210 
211 static int psmi_debugfs_capture_region_mask_get(void *data, u64 *val)
212 {
213 	struct xe_device *xe = data;
214 
215 	*val = xe->psmi.region_mask;
216 
217 	return 0;
218 }
219 
220 /*
221  * Select VRAM regions for multi-tile devices, only allowed when buffer is not
222  * currently allocated.
223  */
224 static int psmi_debugfs_capture_region_mask_set(void *data, u64 region_mask)
225 {
226 	struct xe_device *xe = data;
227 	u64 size = 0;
228 
229 	/* SMEM is not supported (see comments at top of file) */
230 	if (region_mask & 0x1)
231 		return -EOPNOTSUPP;
232 
233 	/* input bitmask should contain only valid TTM regions */
234 	if (!region_mask || region_mask & ~xe->info.mem_region_mask)
235 		return -EINVAL;
236 
237 	/* only allow setting mask if buffer is not yet allocated */
238 	psmi_debugfs_capture_size_get(xe, &size);
239 	if (size)
240 		return -EBUSY;
241 
242 	xe->psmi.region_mask = region_mask;
243 
244 	return 0;
245 }
246 
247 DEFINE_SHOW_ATTRIBUTE(psmi_debugfs_capture_addr);
248 
249 DEFINE_DEBUGFS_ATTRIBUTE(psmi_debugfs_capture_region_mask_fops,
250 			 psmi_debugfs_capture_region_mask_get,
251 			 psmi_debugfs_capture_region_mask_set,
252 			 "0x%llx\n");
253 
254 DEFINE_DEBUGFS_ATTRIBUTE(psmi_debugfs_capture_size_fops,
255 			 psmi_debugfs_capture_size_get,
256 			 psmi_debugfs_capture_size_set,
257 			 "%lld\n");
258 
259 void xe_psmi_debugfs_register(struct xe_device *xe)
260 {
261 	struct drm_minor *minor;
262 
263 	if (!psmi_enabled(xe))
264 		return;
265 
266 	minor = xe->drm.primary;
267 	if (!minor->debugfs_root)
268 		return;
269 
270 	debugfs_create_file("psmi_capture_addr",
271 			    0400, minor->debugfs_root, xe,
272 			    &psmi_debugfs_capture_addr_fops);
273 
274 	debugfs_create_file("psmi_capture_region_mask",
275 			    0600, minor->debugfs_root, xe,
276 			    &psmi_debugfs_capture_region_mask_fops);
277 
278 	debugfs_create_file("psmi_capture_size",
279 			    0600, minor->debugfs_root, xe,
280 			    &psmi_debugfs_capture_size_fops);
281 }
282 
283 static void psmi_fini(void *arg)
284 {
285 	psmi_cleanup(arg);
286 }
287 
288 int xe_psmi_init(struct xe_device *xe)
289 {
290 	if (!psmi_enabled(xe))
291 		return 0;
292 
293 	return devm_add_action(xe->drm.dev, psmi_fini, xe);
294 }
295