xref: /linux/drivers/gpu/drm/xe/xe_gt_stats.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2024 Intel Corporation
4  */
5 
6 #include <drm/drm_managed.h>
7 #include <drm/drm_print.h>
8 
9 #include "xe_device.h"
10 #include "xe_gt_stats.h"
11 
12 /**
13  * DOC: Xe GT Statistics
14  *
15  * Overview
16  * ========
17  *
18  * The Xe driver exposes per-GT statistics through the debugfs filesystem at::
19  *
20  *   /sys/kernel/debug/dri/<device>/gt<id>/stats
21  *
22  * This interface requires the kernel to be built with ``CONFIG_DEBUG_FS=y``.
23  *
24  * Reading statistics
25  * ==================
26  *
27  * Reading the file prints all available statistics, one per line, in
28  * ``name: value`` format::
29  *
30  *   $ cat /sys/kernel/debug/dri/0/gt0/stats
31  *   svm_pagefault_count: 0
32  *   tlb_inval_count: 1234
33  *   ...
34  *
35  * All values are 64-bit unsigned integers aggregated across all CPUs.
36  * Counters accumulate since the driver was loaded or since the last explicit
37  * reset.  Timing counters use microseconds as their unit; data volume counters
38  * use KiB.
39  *
40  * Resetting statistics
41  * ====================
42  *
43  * Writing a boolean true value to the file resets all counters to zero::
44  *
45  *   echo 1 > /sys/kernel/debug/dri/0/gt0/stats
46  *
47  * Any value accepted by ``kstrtobool()`` (e.g. ``1``, ``y``, ``yes``,
48  * ``on``) triggers the reset.  Resetting while the GPU is active may yield
49  * unpredictable intermediate values; it is recommended to reset only when
50  * the GPU is idle.
51  */
52 
53 static void xe_gt_stats_fini(struct drm_device *drm, void *arg)
54 {
55 	struct xe_gt *gt = arg;
56 
57 	free_percpu(gt->stats);
58 }
59 
60 /**
61  * xe_gt_stats_init() - Initialize GT statistics
62  * @gt: GT structure
63  *
64  * Allocate per-CPU GT statistics. Using per-CPU stats allows increments
65  * to occur without cross-CPU atomics.
66  *
67  * Return: 0 on success, -ENOMEM on failure.
68  */
69 int xe_gt_stats_init(struct xe_gt *gt)
70 {
71 	gt->stats = alloc_percpu(struct xe_gt_stats);
72 	if (!gt->stats)
73 		return -ENOMEM;
74 
75 	return drmm_add_action_or_reset(&gt_to_xe(gt)->drm, xe_gt_stats_fini,
76 					gt);
77 }
78 
79 /**
80  * xe_gt_stats_incr - Increments the specified stats counter
81  * @gt: GT structure
82  * @id: xe_gt_stats_id type id that needs to be incremented
83  * @incr: value to be incremented with
84  *
85  * Increments the specified stats counter.
86  */
87 void xe_gt_stats_incr(struct xe_gt *gt, const enum xe_gt_stats_id id, int incr)
88 {
89 	if (id >= __XE_GT_STATS_NUM_IDS)
90 		return;
91 
92 	this_cpu_add(gt->stats->counters[id], incr);
93 }
94 
95 #define DEF_STAT_STR(ID, name) [XE_GT_STATS_ID_##ID] = name
96 
97 static const char *const stat_description[__XE_GT_STATS_NUM_IDS] = {
98 	DEF_STAT_STR(SVM_PAGEFAULT_COUNT, "svm_pagefault_count"),
99 	DEF_STAT_STR(TLB_INVAL, "tlb_inval_count"),
100 	DEF_STAT_STR(SVM_TLB_INVAL_COUNT, "svm_tlb_inval_count"),
101 	DEF_STAT_STR(SVM_TLB_INVAL_US, "svm_tlb_inval_us"),
102 	DEF_STAT_STR(VMA_PAGEFAULT_COUNT, "vma_pagefault_count"),
103 	DEF_STAT_STR(VMA_PAGEFAULT_KB, "vma_pagefault_kb"),
104 	DEF_STAT_STR(INVALID_PREFETCH_PAGEFAULT_COUNT, "invalid_prefetch_pagefault_count"),
105 	DEF_STAT_STR(SVM_4K_PAGEFAULT_COUNT, "svm_4K_pagefault_count"),
106 	DEF_STAT_STR(SVM_64K_PAGEFAULT_COUNT, "svm_64K_pagefault_count"),
107 	DEF_STAT_STR(SVM_2M_PAGEFAULT_COUNT, "svm_2M_pagefault_count"),
108 	DEF_STAT_STR(SVM_4K_VALID_PAGEFAULT_COUNT, "svm_4K_valid_pagefault_count"),
109 	DEF_STAT_STR(SVM_64K_VALID_PAGEFAULT_COUNT, "svm_64K_valid_pagefault_count"),
110 	DEF_STAT_STR(SVM_2M_VALID_PAGEFAULT_COUNT, "svm_2M_valid_pagefault_count"),
111 	DEF_STAT_STR(SVM_4K_PAGEFAULT_US, "svm_4K_pagefault_us"),
112 	DEF_STAT_STR(SVM_64K_PAGEFAULT_US, "svm_64K_pagefault_us"),
113 	DEF_STAT_STR(SVM_2M_PAGEFAULT_US, "svm_2M_pagefault_us"),
114 	DEF_STAT_STR(SVM_4K_MIGRATE_COUNT, "svm_4K_migrate_count"),
115 	DEF_STAT_STR(SVM_64K_MIGRATE_COUNT, "svm_64K_migrate_count"),
116 	DEF_STAT_STR(SVM_2M_MIGRATE_COUNT, "svm_2M_migrate_count"),
117 	DEF_STAT_STR(SVM_4K_MIGRATE_US, "svm_4K_migrate_us"),
118 	DEF_STAT_STR(SVM_64K_MIGRATE_US, "svm_64K_migrate_us"),
119 	DEF_STAT_STR(SVM_2M_MIGRATE_US, "svm_2M_migrate_us"),
120 	DEF_STAT_STR(SVM_DEVICE_COPY_US, "svm_device_copy_us"),
121 	DEF_STAT_STR(SVM_4K_DEVICE_COPY_US, "svm_4K_device_copy_us"),
122 	DEF_STAT_STR(SVM_64K_DEVICE_COPY_US, "svm_64K_device_copy_us"),
123 	DEF_STAT_STR(SVM_2M_DEVICE_COPY_US, "svm_2M_device_copy_us"),
124 	DEF_STAT_STR(SVM_CPU_COPY_US, "svm_cpu_copy_us"),
125 	DEF_STAT_STR(SVM_4K_CPU_COPY_US, "svm_4K_cpu_copy_us"),
126 	DEF_STAT_STR(SVM_64K_CPU_COPY_US, "svm_64K_cpu_copy_us"),
127 	DEF_STAT_STR(SVM_2M_CPU_COPY_US, "svm_2M_cpu_copy_us"),
128 	DEF_STAT_STR(SVM_DEVICE_COPY_KB, "svm_device_copy_kb"),
129 	DEF_STAT_STR(SVM_4K_DEVICE_COPY_KB, "svm_4K_device_copy_kb"),
130 	DEF_STAT_STR(SVM_64K_DEVICE_COPY_KB, "svm_64K_device_copy_kb"),
131 	DEF_STAT_STR(SVM_2M_DEVICE_COPY_KB, "svm_2M_device_copy_kb"),
132 	DEF_STAT_STR(SVM_CPU_COPY_KB, "svm_cpu_copy_kb"),
133 	DEF_STAT_STR(SVM_4K_CPU_COPY_KB, "svm_4K_cpu_copy_kb"),
134 	DEF_STAT_STR(SVM_64K_CPU_COPY_KB, "svm_64K_cpu_copy_kb"),
135 	DEF_STAT_STR(SVM_2M_CPU_COPY_KB, "svm_2M_cpu_copy_kb"),
136 	DEF_STAT_STR(SVM_4K_GET_PAGES_US, "svm_4K_get_pages_us"),
137 	DEF_STAT_STR(SVM_64K_GET_PAGES_US, "svm_64K_get_pages_us"),
138 	DEF_STAT_STR(SVM_2M_GET_PAGES_US, "svm_2M_get_pages_us"),
139 	DEF_STAT_STR(SVM_4K_BIND_US, "svm_4K_bind_us"),
140 	DEF_STAT_STR(SVM_64K_BIND_US, "svm_64K_bind_us"),
141 	DEF_STAT_STR(SVM_2M_BIND_US, "svm_2M_bind_us"),
142 	DEF_STAT_STR(HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT,
143 		     "hw_engine_group_suspend_lr_queue_count"),
144 	DEF_STAT_STR(HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT,
145 		     "hw_engine_group_skip_lr_queue_count"),
146 	DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT,
147 		     "hw_engine_group_wait_dma_queue_count"),
148 	DEF_STAT_STR(HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US,
149 		     "hw_engine_group_suspend_lr_queue_us"),
150 	DEF_STAT_STR(HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US,
151 		     "hw_engine_group_wait_dma_queue_us"),
152 	DEF_STAT_STR(PRL_4K_ENTRY_COUNT, "prl_4k_entry_count"),
153 	DEF_STAT_STR(PRL_64K_ENTRY_COUNT, "prl_64k_entry_count"),
154 	DEF_STAT_STR(PRL_2M_ENTRY_COUNT, "prl_2m_entry_count"),
155 	DEF_STAT_STR(PRL_ISSUED_COUNT, "prl_issued_count"),
156 	DEF_STAT_STR(PRL_ABORTED_COUNT, "prl_aborted_count"),
157 };
158 
159 /**
160  * xe_gt_stats_print_info - Print the GT stats
161  * @gt: GT structure
162  * @p: drm_printer where it will be printed out.
163  *
164  * This prints out all the available GT stats.
165  */
166 int xe_gt_stats_print_info(struct xe_gt *gt, struct drm_printer *p)
167 {
168 	enum xe_gt_stats_id id;
169 
170 	for (id = 0; id < __XE_GT_STATS_NUM_IDS; ++id) {
171 		u64 total = 0;
172 		int cpu;
173 
174 		for_each_possible_cpu(cpu) {
175 			struct xe_gt_stats *s = per_cpu_ptr(gt->stats, cpu);
176 
177 			total += s->counters[id];
178 		}
179 
180 		drm_printf(p, "%s: %lld\n", stat_description[id], total);
181 	}
182 
183 	return 0;
184 }
185 
186 /**
187  * xe_gt_stats_clear() - Clear the GT stats
188  * @gt: GT structure
189  *
190  * Clear (zero) all available GT stats. Note that if the stats are being
191  * updated while this function is running, the results may be unpredictable.
192  * Intended to be called on an idle GPU.
193  */
194 void xe_gt_stats_clear(struct xe_gt *gt)
195 {
196 	int cpu;
197 
198 	for_each_possible_cpu(cpu) {
199 		struct xe_gt_stats *s = per_cpu_ptr(gt->stats, cpu);
200 
201 		memset(s, 0, sizeof(*s));
202 	}
203 }
204