[PATCH v2] tools/gputop/xe_gputop: Adding GPU frequency support
Disantkumar Mistry
disantkumar.isvarbhai.mistry at intel.com
Tue Jul 22 05:14:33 UTC 2025
XE PMU expose GT frequency events to user space via perf interface.
Reading each GT's frequency using PMU interface(gt-actual-frequency,
gt-requested-frequency). Exposing each GT frequency details in gputop
as device description section.
Signed-off-by: Disantkumar Mistry <disantkumar.isvarbhai.mistry at intel.com>
---
tools/gputop/xe_gputop.c | 84 +++++++++++++++++++++++++++++++++++++---
tools/gputop/xe_gputop.h | 3 ++
2 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/tools/gputop/xe_gputop.c b/tools/gputop/xe_gputop.c
index 9757369a8..5b2055a19 100644
--- a/tools/gputop/xe_gputop.c
+++ b/tools/gputop/xe_gputop.c
@@ -47,6 +47,20 @@ void xe_clean_up(void *obj, int len)
if (gputop_dev[i].card)
free(gputop_dev[i].card);
if (gputop_dev[i].pmu_device_obj) {
+ /* Free FDs from GT Frequency PMU counter */
+ for (int j = 0; j < gputop_dev[i].pmu_device_obj->num_gts; j++) {
+ pmu_counter = gputop_dev[i].pmu_device_obj->gt_act_freq[i];
+ if (pmu_counter.present)
+ close(pmu_counter.fd);
+
+ pmu_counter = gputop_dev[i].pmu_device_obj->gt_req_freq[i];
+ if (pmu_counter.present)
+ close(pmu_counter.fd);
+ }
+
+ free(gputop_dev[i].pmu_device_obj->gt_act_freq);
+ free(gputop_dev[i].pmu_device_obj->gt_req_freq);
+
for (int j = 0;
j < gputop_dev[i].pmu_device_obj->num_engines;
j++) {
@@ -127,6 +141,7 @@ void *xe_populate_engines(const void *obj, int index)
struct igt_device_card *card = ptr->card;
uint64_t engine_active_config, engine_total_config;
uint64_t engine_class, engine_instance, gt_shift;
+ uint64_t gt_actual_freq, gt_requested_freq;
struct drm_xe_engine_class_instance *hwe;
struct xe_pmu_device *engines;
char device[30];
@@ -157,7 +172,32 @@ void *xe_populate_engines(const void *obj, int index)
gt_shift = pmu_format_shift(card_fd, "gt");
engine_class = pmu_format_shift(card_fd, "engine_class");
engine_instance = pmu_format_shift(card_fd, "engine_instance");
+
xe_perf_device(card_fd, device, sizeof(device));
+
+ engines->num_gts = xe_number_gt(card_fd);
+
+ engines->gt_act_freq = malloc(sizeof(struct xe_pmu_counter) * engines->num_gts);
+ if (!engines->gt_act_freq)
+ return NULL;
+
+ engines->gt_req_freq = malloc(sizeof(struct xe_pmu_counter) * engines->num_gts);
+ if (!engines->gt_req_freq)
+ return NULL;
+
+ ret = perf_event_config(device, "gt-actual-frequency", >_actual_freq);
+ if (ret < 0)
+ return NULL;
+
+ ret = perf_event_config(device, "gt-requested-frequency", >_requested_freq);
+ if (ret < 0)
+ return NULL;
+
+ for (int i = 0; i < engines->num_gts; i++) {
+ engines->gt_act_freq[i].config = i << gt_shift | gt_actual_freq;
+ engines->gt_req_freq[i].config = i << gt_shift | gt_requested_freq;
+ }
+
engines->device = strdup(device);
ret = perf_event_config(device, "engine-active-ticks", &engine_active_config);
if (ret < 0)
@@ -237,6 +277,11 @@ void xe_pmu_sample(const void *obj, int index)
pmu_read_multi(engines->fd, num_val, val);
+ for (i = 0; i < engines->num_gts; i++) {
+ update_sample(&engines->gt_act_freq[i], val);
+ update_sample(&engines->gt_req_freq[i], val);
+ }
+
for (i = 0; i < engines->num_engines; i++) {
struct xe_engine *engine = engine_ptr(engines, i);
@@ -258,6 +303,20 @@ int xe_pmu_init(const void *obj, int index)
engines->fd = -1;
engines->num_counters = 0;
+ for (i = 0; i < engines->num_gts; i++) {
+ fd = _open_pmu(type, &engines->num_counters,
+ &engines->gt_act_freq[i],
+ &engines->fd);
+ if (fd < 0)
+ return -1;
+
+ fd = _open_pmu(type, &engines->num_counters,
+ &engines->gt_req_freq[i],
+ &engines->fd);
+ if (fd < 0)
+ return -1;
+ }
+
for (i = 0; i < engines->num_engines; i++) {
engine = engine_ptr(engines, i);
fd = _open_pmu(type, &engines->num_counters, &engine->engine_active_ticks,
@@ -287,18 +346,33 @@ static double pmu_active_percentage(struct xe_engine *engine)
static int
print_device_description(const void *obj, int lines, int w, int h)
{
- char *desc;
- int len;
+ char *desc, *gt_freq = NULL;
+ int len = 0, counter = 0;
+ struct igt_device_card *card = ((struct xe_gputop *)obj)->card;
+ struct xe_pmu_device *device = ((struct xe_gputop *)obj)->pmu_device_obj;
+
+ for (int i = 0; i < device->num_gts; i++) {
+ long act_freq = device->gt_act_freq[i].val.cur - device->gt_act_freq[i].val.prev;
+ long req_freq = device->gt_req_freq[i].val.cur - device->gt_req_freq[i].val.prev;
+
+ len += snprintf(NULL, 0, "FREQ-GT%d: %lu/%lu ", i, act_freq, req_freq);
+ gt_freq = (char *)realloc(gt_freq, (len + 1) * sizeof(char));
+
+ sprintf(gt_freq + counter, "FREQ-GT%d: %lu/%lu ", i, act_freq, req_freq);
+ counter = len;
+ }
- len = asprintf(&desc, "DRIVER: %s || BDF: %s",
- ((struct xe_gputop *)obj)->card->driver,
- ((struct xe_gputop *)obj)->card->pci_slot_name);
+ len = asprintf(&desc, "DRIVER: %s || BDF: %s || %s",
+ card->driver,
+ card->pci_slot_name,
+ gt_freq);
printf("\033[7m%s%*s\033[0m\n",
desc,
(int)(w - len), " ");
lines++;
free(desc);
+ free(gt_freq);
return lines;
}
diff --git a/tools/gputop/xe_gputop.h b/tools/gputop/xe_gputop.h
index 1e3856071..baea232fc 100644
--- a/tools/gputop/xe_gputop.h
+++ b/tools/gputop/xe_gputop.h
@@ -39,8 +39,11 @@ struct xe_engine {
struct xe_pmu_device {
unsigned int num_engines;
unsigned int num_counters;
+ unsigned int num_gts;
int fd;
char *device;
+ struct xe_pmu_counter *gt_act_freq;
+ struct xe_pmu_counter *gt_req_freq;
struct xe_engine engine;
};
--
2.34.1
More information about the igt-dev
mailing list