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