Lines Matching +full:- +full:gt
1 // SPDX-License-Identifier: MIT
22 * Expose events/counters like GT-C6 residency, GT frequency and per-class-engine
27 * $ ls -ld /sys/bus/event_source/devices/xe_*
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
39 * For engine specific events (engine-*), gt, engine_class and engine_instance parameters must be
42 * For gt specific events (gt-*) gt parameter must be passed. All other parameters will be 0.
47 * $ perf list | grep gt-c6
49 * To sample a specific event for a GT at regular intervals:
51 * $ perf stat -e <event_name,gt=> -I <interval>
93 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in event_to_gt()
94 u64 gt = config_to_gt_id(event->attr.config); in event_to_gt() local
96 return xe_device_get_gt(xe, gt); in event_to_gt()
101 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in event_to_hwe()
103 u64 config = event->attr.config; in event_to_hwe()
127 u32 id = config_to_event_id(event->attr.config); in is_gt_frequency_event()
135 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in event_gt_forcewake()
136 u64 config = event->attr.config; in event_gt_forcewake()
137 struct xe_gt *gt; in event_gt_forcewake() local
143 gt = xe_device_get_gt(xe, config_to_gt_id(config)); in event_gt_forcewake()
149 *fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); in event_gt_forcewake()
155 event->pmu_private = fw_ref; in event_gt_forcewake()
164 struct xe_gt *gt = xe_device_get_gt(xe, gt_id); in event_supported() local
166 if (!gt) in event_supported()
169 return id < sizeof(pmu->supported_events) * BITS_PER_BYTE && in event_supported()
170 pmu->supported_events & BIT_ULL(id); in event_supported()
175 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in event_param_valid()
177 u64 config = event->attr.config; in event_param_valid()
178 struct xe_gt *gt; in event_param_valid() local
180 gt = xe_device_get_gt(xe, config_to_gt_id(config)); in event_param_valid()
181 if (!gt) in event_param_valid()
216 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_destroy()
217 struct xe_gt *gt; in xe_pmu_event_destroy() local
218 unsigned int *fw_ref = event->pmu_private; in xe_pmu_event_destroy()
221 gt = xe_device_get_gt(xe, config_to_gt_id(event->attr.config)); in xe_pmu_event_destroy()
222 xe_force_wake_put(gt_to_fw(gt), *fw_ref); in xe_pmu_event_destroy()
224 event->pmu_private = NULL; in xe_pmu_event_destroy()
227 drm_WARN_ON(&xe->drm, event->parent); in xe_pmu_event_destroy()
229 drm_dev_put(&xe->drm); in xe_pmu_event_destroy()
234 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_init()
235 struct xe_pmu *pmu = &xe->pmu; in xe_pmu_event_init()
236 unsigned int id, gt; in xe_pmu_event_init() local
238 if (!pmu->registered) in xe_pmu_event_init()
239 return -ENODEV; in xe_pmu_event_init()
241 if (event->attr.type != event->pmu->type) in xe_pmu_event_init()
242 return -ENOENT; in xe_pmu_event_init()
245 if (event->attr.sample_period) /* no sampling */ in xe_pmu_event_init()
246 return -EINVAL; in xe_pmu_event_init()
248 if (event->cpu < 0) in xe_pmu_event_init()
249 return -EINVAL; in xe_pmu_event_init()
251 gt = config_to_gt_id(event->attr.config); in xe_pmu_event_init()
252 id = config_to_event_id(event->attr.config); in xe_pmu_event_init()
253 if (!event_supported(pmu, gt, id)) in xe_pmu_event_init()
254 return -ENOENT; in xe_pmu_event_init()
257 return -EOPNOTSUPP; in xe_pmu_event_init()
260 return -ENOENT; in xe_pmu_event_init()
262 if (!event->parent) { in xe_pmu_event_init()
263 drm_dev_get(&xe->drm); in xe_pmu_event_init()
267 drm_dev_put(&xe->drm); in xe_pmu_event_init()
268 return -EINVAL; in xe_pmu_event_init()
270 event->destroy = xe_pmu_event_destroy; in xe_pmu_event_init()
276 static u64 read_engine_events(struct xe_gt *gt, struct perf_event *event) in read_engine_events() argument
282 config = event->attr.config; in read_engine_events()
287 val = xe_guc_engine_activity_active_ticks(>->uc.guc, hwe, function_id); in read_engine_events()
289 val = xe_guc_engine_activity_total_ticks(>->uc.guc, hwe, function_id); in read_engine_events()
296 struct xe_gt *gt = event_to_gt(event); in __xe_pmu_event_read() local
298 if (!gt) in __xe_pmu_event_read()
301 switch (config_to_event_id(event->attr.config)) { in __xe_pmu_event_read()
303 return xe_gt_idle_residency_msec(>->gtidle); in __xe_pmu_event_read()
306 return read_engine_events(gt, event); in __xe_pmu_event_read()
308 return xe_guc_pc_get_act_freq(>->uc.guc.pc); in __xe_pmu_event_read()
310 return xe_guc_pc_get_cur_freq_fw(>->uc.guc.pc); in __xe_pmu_event_read()
318 struct hw_perf_event *hwc = &event->hw; in xe_pmu_event_update()
321 prev = local64_read(&hwc->prev_count); in xe_pmu_event_update()
324 } while (!local64_try_cmpxchg(&hwc->prev_count, &prev, new)); in xe_pmu_event_update()
327 * GT frequency is not a monotonically increasing counter, so add the in xe_pmu_event_update()
331 local64_add(new, &event->count); in xe_pmu_event_update()
333 local64_add(new - prev, &event->count); in xe_pmu_event_update()
338 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_read()
339 struct xe_pmu *pmu = &xe->pmu; in xe_pmu_event_read()
341 if (!pmu->registered) { in xe_pmu_event_read()
342 event->hw.state = PERF_HES_STOPPED; in xe_pmu_event_read()
354 * an existing non-zero value. in xe_pmu_enable()
356 local64_set(&event->hw.prev_count, __xe_pmu_event_read(event)); in xe_pmu_enable()
361 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_start()
362 struct xe_pmu *pmu = &xe->pmu; in xe_pmu_event_start()
364 if (!pmu->registered) in xe_pmu_event_start()
368 event->hw.state = 0; in xe_pmu_event_start()
373 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_stop()
374 struct xe_pmu *pmu = &xe->pmu; in xe_pmu_event_stop()
376 if (pmu->registered) in xe_pmu_event_stop()
380 event->hw.state = PERF_HES_STOPPED; in xe_pmu_event_stop()
385 struct xe_device *xe = container_of(event->pmu, typeof(*xe), pmu.base); in xe_pmu_event_add()
386 struct xe_pmu *pmu = &xe->pmu; in xe_pmu_event_add()
388 if (!pmu->registered) in xe_pmu_event_add()
389 return -ENODEV; in xe_pmu_event_add()
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");
428 return sprintf(buf, "event=%#04llx\n", pmu_attr->id); in event_attr_show()
452 return event_supported(pmu, 0, id_) ? attr->mode : 0; \
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,
475 XE_EVENT_ATTR_SIMPLE(gt-requested-frequency, gt_requested_frequency,
479 /* Empty - all events are added as groups with .attr_update() */
500 struct xe_gt *gt = xe_device_get_gt(xe, 0); in set_supported_events() local
502 if (!xe->info.skip_guc_pc) { in set_supported_events()
503 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY); in set_supported_events()
504 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_ACTUAL_FREQUENCY); in set_supported_events()
505 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_REQUESTED_FREQUENCY); in set_supported_events()
508 if (xe_guc_engine_activity_supported(>->uc.guc)) { in set_supported_events()
509 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_ENGINE_ACTIVE_TICKS); in set_supported_events()
510 pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_ENGINE_TOTAL_TICKS); in set_supported_events()
515 * xe_pmu_unregister() - Remove/cleanup PMU registration
523 if (!pmu->registered) in xe_pmu_unregister()
526 pmu->registered = false; in xe_pmu_unregister()
528 perf_pmu_unregister(&pmu->base); in xe_pmu_unregister()
529 kfree(pmu->name); in xe_pmu_unregister()
533 * xe_pmu_register() - Define basic PMU properties for Xe and add event callbacks.
546 int ret = -ENOMEM; in xe_pmu_register()
555 dev_name(xe->drm.dev)); in xe_pmu_register()
562 pmu->name = name; in xe_pmu_register()
563 pmu->base.attr_groups = attr_groups; in xe_pmu_register()
564 pmu->base.attr_update = pmu_events_attr_update; in xe_pmu_register()
565 pmu->base.scope = PERF_PMU_SCOPE_SYS_WIDE; in xe_pmu_register()
566 pmu->base.module = THIS_MODULE; in xe_pmu_register()
567 pmu->base.task_ctx_nr = perf_invalid_context; in xe_pmu_register()
568 pmu->base.event_init = xe_pmu_event_init; in xe_pmu_register()
569 pmu->base.add = xe_pmu_event_add; in xe_pmu_register()
570 pmu->base.del = xe_pmu_event_del; in xe_pmu_register()
571 pmu->base.start = xe_pmu_event_start; in xe_pmu_register()
572 pmu->base.stop = xe_pmu_event_stop; in xe_pmu_register()
573 pmu->base.read = xe_pmu_event_read; in xe_pmu_register()
577 ret = perf_pmu_register(&pmu->base, pmu->name, -1); in xe_pmu_register()
581 pmu->registered = true; in xe_pmu_register()
583 return devm_add_action_or_reset(xe->drm.dev, xe_pmu_unregister, pmu); in xe_pmu_register()
588 drm_err(&xe->drm, "Failed to register PMU (ret=%d)!\n", ret); in xe_pmu_register()