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(>_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