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 60 static unsigned int config_to_event_id(u64 config) 61 { 62 return FIELD_GET(XE_PMU_EVENT_ID_MASK, config); 63 } 64 65 static unsigned int config_to_function_id(u64 config) 66 { 67 return FIELD_GET(XE_PMU_EVENT_FUNCTION_MASK, config); 68 } 69 70 static unsigned int config_to_engine_class(u64 config) 71 { 72 return FIELD_GET(XE_PMU_EVENT_ENGINE_CLASS_MASK, config); 73 } 74 75 static unsigned int config_to_engine_instance(u64 config) 76 { 77 return FIELD_GET(XE_PMU_EVENT_ENGINE_INSTANCE_MASK, config); 78 } 79 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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