xref: /linux/drivers/gpu/drm/xe/xe_pmu.c (revision 2de3f38fbf89d3cb96d1237aa7a10c0f6480f450)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <drm/drm_drv.h>
7 #include <linux/device.h>
8 
9 #include "xe_device.h"
10 #include "xe_force_wake.h"
11 #include "xe_gt_idle.h"
12 #include "xe_guc_engine_activity.h"
13 #include "xe_hw_engine.h"
14 #include "xe_pm.h"
15 #include "xe_pmu.h"
16 
17 /**
18  * DOC: Xe PMU (Performance Monitoring Unit)
19  *
20  * Expose events/counters like GT-C6 residency, GT frequency and per-class-engine
21  * activity to user land via the perf interface. Events are per device.
22  *
23  * All events are listed in sysfs:
24  *
25  *     $ ls -ld /sys/bus/event_source/devices/xe_*
26  *     $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/events/
27  *     $ ls /sys/bus/event_source/devices/xe_0000_00_02.0/format/
28  *
29  * The following format parameters are available to read events,
30  * but only few are valid with each event:
31  *
32  *	gt[60:63]		Selects gt for the event
33  *	engine_class[20:27]	Selects engine-class for event
34  *	engine_instance[12:19]	Selects the engine-instance for the event
35  *
36  * For engine specific events (engine-*), gt, engine_class and engine_instance parameters must be
37  * set as populated by DRM_XE_DEVICE_QUERY_ENGINES.
38  *
39  * For gt specific events (gt-*) gt parameter must be passed. All other parameters will be 0.
40  *
41  * The standard perf tool can be used to grep for a certain event as well.
42  * Example:
43  *
44  *     $ perf list | grep gt-c6
45  *
46  * To sample a specific event for a GT at regular intervals:
47  *
48  *     $ perf stat -e <event_name,gt=> -I <interval>
49  */
50 
51 #define XE_PMU_EVENT_GT_MASK			GENMASK_ULL(63, 60)
52 #define XE_PMU_EVENT_ENGINE_CLASS_MASK		GENMASK_ULL(27, 20)
53 #define XE_PMU_EVENT_ENGINE_INSTANCE_MASK	GENMASK_ULL(19, 12)
54 #define XE_PMU_EVENT_ID_MASK			GENMASK_ULL(11, 0)
55 
56 static unsigned int config_to_event_id(u64 config)
57 {
58 	return FIELD_GET(XE_PMU_EVENT_ID_MASK, config);
59 }
60 
61 static unsigned int config_to_engine_class(u64 config)
62 {
63 	return FIELD_GET(XE_PMU_EVENT_ENGINE_CLASS_MASK, config);
64 }
65 
66 static unsigned int config_to_engine_instance(u64 config)
67 {
68 	return FIELD_GET(XE_PMU_EVENT_ENGINE_INSTANCE_MASK, config);
69 }
70 
71 static unsigned int config_to_gt_id(u64 config)
72 {
73 	return FIELD_GET(XE_PMU_EVENT_GT_MASK, config);
74 }
75 
76 #define XE_PMU_EVENT_GT_C6_RESIDENCY		0x01
77 #define XE_PMU_EVENT_ENGINE_ACTIVE_TICKS	0x02
78 #define XE_PMU_EVENT_ENGINE_TOTAL_TICKS		0x03
79 
80 static struct xe_gt *event_to_gt(struct perf_event *event)
81 {
82 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
83 	u64 gt = config_to_gt_id(event->attr.config);
84 
85 	return xe_device_get_gt(xe, gt);
86 }
87 
88 static struct xe_hw_engine *event_to_hwe(struct perf_event *event)
89 {
90 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
91 	struct drm_xe_engine_class_instance eci;
92 	u64 config = event->attr.config;
93 	struct xe_hw_engine *hwe;
94 
95 	eci.engine_class = config_to_engine_class(config);
96 	eci.engine_instance = config_to_engine_instance(config);
97 	eci.gt_id = config_to_gt_id(config);
98 
99 	hwe = xe_hw_engine_lookup(xe, eci);
100 	if (!hwe || xe_hw_engine_is_reserved(hwe))
101 		return NULL;
102 
103 	return hwe;
104 }
105 
106 static bool is_engine_event(u64 config)
107 {
108 	unsigned int event_id = config_to_event_id(config);
109 
110 	return (event_id == XE_PMU_EVENT_ENGINE_TOTAL_TICKS ||
111 		event_id == XE_PMU_EVENT_ENGINE_ACTIVE_TICKS);
112 }
113 
114 static bool event_gt_forcewake(struct perf_event *event)
115 {
116 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
117 	u64 config = event->attr.config;
118 	struct xe_gt *gt;
119 	unsigned int *fw_ref;
120 
121 	if (!is_engine_event(config))
122 		return true;
123 
124 	gt = xe_device_get_gt(xe, config_to_gt_id(config));
125 
126 	fw_ref = kzalloc(sizeof(*fw_ref), GFP_KERNEL);
127 	if (!fw_ref)
128 		return false;
129 
130 	*fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
131 	if (!*fw_ref) {
132 		kfree(fw_ref);
133 		return false;
134 	}
135 
136 	event->pmu_private = fw_ref;
137 
138 	return true;
139 }
140 
141 static bool event_supported(struct xe_pmu *pmu, unsigned int gt,
142 			    unsigned int id)
143 {
144 	if (gt >= XE_MAX_GT_PER_TILE)
145 		return false;
146 
147 	return id < sizeof(pmu->supported_events) * BITS_PER_BYTE &&
148 		pmu->supported_events & BIT_ULL(id);
149 }
150 
151 static bool event_param_valid(struct perf_event *event)
152 {
153 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
154 	unsigned int engine_class, engine_instance;
155 	u64 config = event->attr.config;
156 	struct xe_gt *gt;
157 
158 	gt = xe_device_get_gt(xe, config_to_gt_id(config));
159 	if (!gt)
160 		return false;
161 
162 	engine_class = config_to_engine_class(config);
163 	engine_instance = config_to_engine_instance(config);
164 
165 	switch (config_to_event_id(config)) {
166 	case XE_PMU_EVENT_GT_C6_RESIDENCY:
167 		if (engine_class || engine_instance)
168 			return false;
169 		break;
170 	case XE_PMU_EVENT_ENGINE_ACTIVE_TICKS:
171 	case XE_PMU_EVENT_ENGINE_TOTAL_TICKS:
172 		if (!event_to_hwe(event))
173 			return false;
174 		break;
175 	}
176 
177 	return true;
178 }
179 
180 static void xe_pmu_event_destroy(struct perf_event *event)
181 {
182 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
183 	struct xe_gt *gt;
184 	unsigned int *fw_ref = event->pmu_private;
185 
186 	if (fw_ref) {
187 		gt = xe_device_get_gt(xe, config_to_gt_id(event->attr.config));
188 		xe_force_wake_put(gt_to_fw(gt), *fw_ref);
189 		kfree(fw_ref);
190 		event->pmu_private = NULL;
191 	}
192 
193 	drm_WARN_ON(&xe->drm, event->parent);
194 	xe_pm_runtime_put(xe);
195 	drm_dev_put(&xe->drm);
196 }
197 
198 static int xe_pmu_event_init(struct perf_event *event)
199 {
200 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
201 	struct xe_pmu *pmu = &xe->pmu;
202 	unsigned int id, gt;
203 
204 	if (!pmu->registered)
205 		return -ENODEV;
206 
207 	if (event->attr.type != event->pmu->type)
208 		return -ENOENT;
209 
210 	/* unsupported modes and filters */
211 	if (event->attr.sample_period) /* no sampling */
212 		return -EINVAL;
213 
214 	if (event->cpu < 0)
215 		return -EINVAL;
216 
217 	gt = config_to_gt_id(event->attr.config);
218 	id = config_to_event_id(event->attr.config);
219 	if (!event_supported(pmu, gt, id))
220 		return -ENOENT;
221 
222 	if (has_branch_stack(event))
223 		return -EOPNOTSUPP;
224 
225 	if (!event_param_valid(event))
226 		return -ENOENT;
227 
228 	if (!event->parent) {
229 		drm_dev_get(&xe->drm);
230 		xe_pm_runtime_get(xe);
231 		if (!event_gt_forcewake(event)) {
232 			xe_pm_runtime_put(xe);
233 			drm_dev_put(&xe->drm);
234 			return -EINVAL;
235 		}
236 		event->destroy = xe_pmu_event_destroy;
237 	}
238 
239 	return 0;
240 }
241 
242 static u64 read_engine_events(struct xe_gt *gt, struct perf_event *event)
243 {
244 	struct xe_hw_engine *hwe;
245 	u64 val = 0;
246 
247 	hwe = event_to_hwe(event);
248 
249 	if (config_to_event_id(event->attr.config) == XE_PMU_EVENT_ENGINE_ACTIVE_TICKS)
250 		val = xe_guc_engine_activity_active_ticks(&gt->uc.guc, hwe, 0);
251 	else
252 		val = xe_guc_engine_activity_total_ticks(&gt->uc.guc, hwe, 0);
253 
254 	return val;
255 }
256 
257 static u64 __xe_pmu_event_read(struct perf_event *event)
258 {
259 	struct xe_gt *gt = event_to_gt(event);
260 
261 	if (!gt)
262 		return 0;
263 
264 	switch (config_to_event_id(event->attr.config)) {
265 	case XE_PMU_EVENT_GT_C6_RESIDENCY:
266 		return xe_gt_idle_residency_msec(&gt->gtidle);
267 	case XE_PMU_EVENT_ENGINE_ACTIVE_TICKS:
268 	case XE_PMU_EVENT_ENGINE_TOTAL_TICKS:
269 		return read_engine_events(gt, event);
270 	}
271 
272 	return 0;
273 }
274 
275 static void xe_pmu_event_update(struct perf_event *event)
276 {
277 	struct hw_perf_event *hwc = &event->hw;
278 	u64 prev, new;
279 
280 	prev = local64_read(&hwc->prev_count);
281 	do {
282 		new = __xe_pmu_event_read(event);
283 	} while (!local64_try_cmpxchg(&hwc->prev_count, &prev, new));
284 
285 	local64_add(new - prev, &event->count);
286 }
287 
288 static void xe_pmu_event_read(struct perf_event *event)
289 {
290 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
291 	struct xe_pmu *pmu = &xe->pmu;
292 
293 	if (!pmu->registered) {
294 		event->hw.state = PERF_HES_STOPPED;
295 		return;
296 	}
297 
298 	xe_pmu_event_update(event);
299 }
300 
301 static void xe_pmu_enable(struct perf_event *event)
302 {
303 	/*
304 	 * Store the current counter value so we can report the correct delta
305 	 * for all listeners. Even when the event was already enabled and has
306 	 * an existing non-zero value.
307 	 */
308 	local64_set(&event->hw.prev_count, __xe_pmu_event_read(event));
309 }
310 
311 static void xe_pmu_event_start(struct perf_event *event, int flags)
312 {
313 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
314 	struct xe_pmu *pmu = &xe->pmu;
315 
316 	if (!pmu->registered)
317 		return;
318 
319 	xe_pmu_enable(event);
320 	event->hw.state = 0;
321 }
322 
323 static void xe_pmu_event_stop(struct perf_event *event, int flags)
324 {
325 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
326 	struct xe_pmu *pmu = &xe->pmu;
327 
328 	if (pmu->registered)
329 		if (flags & PERF_EF_UPDATE)
330 			xe_pmu_event_update(event);
331 
332 	event->hw.state = PERF_HES_STOPPED;
333 }
334 
335 static int xe_pmu_event_add(struct perf_event *event, int flags)
336 {
337 	struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base);
338 	struct xe_pmu *pmu = &xe->pmu;
339 
340 	if (!pmu->registered)
341 		return -ENODEV;
342 
343 	if (flags & PERF_EF_START)
344 		xe_pmu_event_start(event, flags);
345 
346 	return 0;
347 }
348 
349 static void xe_pmu_event_del(struct perf_event *event, int flags)
350 {
351 	xe_pmu_event_stop(event, PERF_EF_UPDATE);
352 }
353 
354 PMU_FORMAT_ATTR(gt,			"config:60-63");
355 PMU_FORMAT_ATTR(engine_class,		"config:20-27");
356 PMU_FORMAT_ATTR(engine_instance,	"config:12-19");
357 PMU_FORMAT_ATTR(event,			"config:0-11");
358 
359 static struct attribute *pmu_format_attrs[] = {
360 	&format_attr_event.attr,
361 	&format_attr_engine_class.attr,
362 	&format_attr_engine_instance.attr,
363 	&format_attr_gt.attr,
364 	NULL,
365 };
366 
367 static const struct attribute_group pmu_format_attr_group = {
368 	.name = "format",
369 	.attrs = pmu_format_attrs,
370 };
371 
372 static ssize_t event_attr_show(struct device *dev,
373 			       struct device_attribute *attr, char *buf)
374 {
375 	struct perf_pmu_events_attr *pmu_attr =
376 		container_of(attr, struct perf_pmu_events_attr, attr);
377 
378 	return sprintf(buf, "event=%#04llx\n", pmu_attr->id);
379 }
380 
381 #define XE_EVENT_ATTR(name_, v_, id_)					\
382 	PMU_EVENT_ATTR(name_, pmu_event_ ## v_, id_, event_attr_show)
383 
384 #define XE_EVENT_ATTR_UNIT(name_, v_, unit_)				\
385 	PMU_EVENT_ATTR_STRING(name_.unit, pmu_event_unit_ ## v_, unit_)
386 
387 #define XE_EVENT_ATTR_GROUP(v_, id_, ...)				\
388 	static struct attribute *pmu_attr_ ##v_[] = {			\
389 		__VA_ARGS__,						\
390 		NULL							\
391 	};								\
392 	static umode_t is_visible_##v_(struct kobject *kobj,		\
393 				       struct attribute *attr, int idx) \
394 	{								\
395 		struct perf_pmu_events_attr *pmu_attr;			\
396 		struct xe_pmu *pmu;					\
397 									\
398 		pmu_attr = container_of(attr, typeof(*pmu_attr), attr.attr); \
399 		pmu = container_of(dev_get_drvdata(kobj_to_dev(kobj)),	\
400 				   typeof(*pmu), base);			\
401 									\
402 		return event_supported(pmu, 0, id_) ? attr->mode : 0;	\
403 	}								\
404 	static const struct attribute_group pmu_group_ ##v_ = {		\
405 		.name = "events",					\
406 		.attrs = pmu_attr_ ## v_,				\
407 		.is_visible = is_visible_ ## v_,			\
408 	}
409 
410 #define XE_EVENT_ATTR_SIMPLE(name_, v_, id_, unit_)			\
411 	XE_EVENT_ATTR(name_, v_, id_)					\
412 	XE_EVENT_ATTR_UNIT(name_, v_, unit_)				\
413 	XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr,	\
414 			    &pmu_event_unit_ ##v_.attr.attr)
415 
416 #define XE_EVENT_ATTR_NOUNIT(name_, v_, id_)				\
417 	XE_EVENT_ATTR(name_, v_, id_)					\
418 	XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr)
419 
420 XE_EVENT_ATTR_SIMPLE(gt-c6-residency, gt_c6_residency, XE_PMU_EVENT_GT_C6_RESIDENCY, "ms");
421 XE_EVENT_ATTR_NOUNIT(engine-active-ticks, engine_active_ticks, XE_PMU_EVENT_ENGINE_ACTIVE_TICKS);
422 XE_EVENT_ATTR_NOUNIT(engine-total-ticks, engine_total_ticks, XE_PMU_EVENT_ENGINE_TOTAL_TICKS);
423 
424 static struct attribute *pmu_empty_event_attrs[] = {
425 	/* Empty - all events are added as groups with .attr_update() */
426 	NULL,
427 };
428 
429 static const struct attribute_group pmu_events_attr_group = {
430 	.name = "events",
431 	.attrs = pmu_empty_event_attrs,
432 };
433 
434 static const struct attribute_group *pmu_events_attr_update[] = {
435 	&pmu_group_gt_c6_residency,
436 	&pmu_group_engine_active_ticks,
437 	&pmu_group_engine_total_ticks,
438 	NULL,
439 };
440 
441 static void set_supported_events(struct xe_pmu *pmu)
442 {
443 	struct xe_device *xe = container_of(pmu, typeof(*xe), pmu);
444 	struct xe_gt *gt = xe_device_get_gt(xe, 0);
445 
446 	if (!xe->info.skip_guc_pc)
447 		pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY);
448 
449 	if (xe_guc_engine_activity_supported(&gt->uc.guc)) {
450 		pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_ENGINE_ACTIVE_TICKS);
451 		pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_ENGINE_TOTAL_TICKS);
452 	}
453 }
454 
455 /**
456  * xe_pmu_unregister() - Remove/cleanup PMU registration
457  * @arg: Ptr to pmu
458  */
459 static void xe_pmu_unregister(void *arg)
460 {
461 	struct xe_pmu *pmu = arg;
462 	struct xe_device *xe = container_of(pmu, typeof(*xe), pmu);
463 
464 	if (!pmu->registered)
465 		return;
466 
467 	pmu->registered = false;
468 
469 	perf_pmu_unregister(&pmu->base);
470 	kfree(pmu->name);
471 }
472 
473 /**
474  * xe_pmu_register() - Define basic PMU properties for Xe and add event callbacks.
475  * @pmu: the PMU object
476  *
477  * Returns 0 on success and an appropriate error code otherwise
478  */
479 int xe_pmu_register(struct xe_pmu *pmu)
480 {
481 	struct xe_device *xe = container_of(pmu, typeof(*xe), pmu);
482 	static const struct attribute_group *attr_groups[] = {
483 		&pmu_format_attr_group,
484 		&pmu_events_attr_group,
485 		NULL
486 	};
487 	int ret = -ENOMEM;
488 	char *name;
489 
490 	BUILD_BUG_ON(XE_MAX_GT_PER_TILE != XE_PMU_MAX_GT);
491 
492 	if (IS_SRIOV_VF(xe))
493 		return 0;
494 
495 	name = kasprintf(GFP_KERNEL, "xe_%s",
496 			 dev_name(xe->drm.dev));
497 	if (!name)
498 		goto err;
499 
500 	/* tools/perf reserves colons as special. */
501 	strreplace(name, ':', '_');
502 
503 	pmu->name		= name;
504 	pmu->base.attr_groups	= attr_groups;
505 	pmu->base.attr_update	= pmu_events_attr_update;
506 	pmu->base.scope		= PERF_PMU_SCOPE_SYS_WIDE;
507 	pmu->base.module	= THIS_MODULE;
508 	pmu->base.task_ctx_nr	= perf_invalid_context;
509 	pmu->base.event_init	= xe_pmu_event_init;
510 	pmu->base.add		= xe_pmu_event_add;
511 	pmu->base.del		= xe_pmu_event_del;
512 	pmu->base.start		= xe_pmu_event_start;
513 	pmu->base.stop		= xe_pmu_event_stop;
514 	pmu->base.read		= xe_pmu_event_read;
515 
516 	set_supported_events(pmu);
517 
518 	ret = perf_pmu_register(&pmu->base, pmu->name, -1);
519 	if (ret)
520 		goto err_name;
521 
522 	pmu->registered = true;
523 
524 	return devm_add_action_or_reset(xe->drm.dev, xe_pmu_unregister, pmu);
525 
526 err_name:
527 	kfree(name);
528 err:
529 	drm_err(&xe->drm, "Failed to register PMU (ret=%d)!\n", ret);
530 
531 	return ret;
532 }
533