1/*
2 * Copyright © 2021 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26
27#include "drm-uapi/i915_drm.h"
28#include "intel_device_info.h"
29#include "intel_hwconfig.h"
30#include "intel_hwconfig_types.h"
31#include "intel/common/intel_gem.h"
32
33#include "util/log.h"
34
35#ifdef NDEBUG
36#define DEBUG_BUILD false
37#else
38#define DEBUG_BUILD true
39#endif
40
41struct hwconfig {
42   uint32_t key;
43   uint32_t len;
44   uint32_t val[];
45};
46
47static char *
48key_to_name(uint32_t key)
49{
50#define HANDLE(key_name) case key_name: return #key_name
51   switch (key) {
52      HANDLE(INTEL_HWCONFIG_MAX_SLICES_SUPPORTED);
53      HANDLE(INTEL_HWCONFIG_MAX_DUAL_SUBSLICES_SUPPORTED);
54      HANDLE(INTEL_HWCONFIG_MAX_NUM_EU_PER_DSS);
55      HANDLE(INTEL_HWCONFIG_NUM_PIXEL_PIPES);
56      HANDLE(INTEL_HWCONFIG_DEPRECATED_MAX_NUM_GEOMETRY_PIPES);
57      HANDLE(INTEL_HWCONFIG_DEPRECATED_L3_CACHE_SIZE_IN_KB);
58      HANDLE(INTEL_HWCONFIG_DEPRECATED_L3_BANK_COUNT);
59      HANDLE(INTEL_HWCONFIG_L3_CACHE_WAYS_SIZE_IN_BYTES);
60      HANDLE(INTEL_HWCONFIG_L3_CACHE_WAYS_PER_SECTOR);
61      HANDLE(INTEL_HWCONFIG_MAX_MEMORY_CHANNELS);
62      HANDLE(INTEL_HWCONFIG_MEMORY_TYPE);
63      HANDLE(INTEL_HWCONFIG_CACHE_TYPES);
64      HANDLE(INTEL_HWCONFIG_LOCAL_MEMORY_PAGE_SIZES_SUPPORTED);
65      HANDLE(INTEL_HWCONFIG_DEPRECATED_SLM_SIZE_IN_KB);
66      HANDLE(INTEL_HWCONFIG_NUM_THREADS_PER_EU);
67      HANDLE(INTEL_HWCONFIG_TOTAL_VS_THREADS);
68      HANDLE(INTEL_HWCONFIG_TOTAL_GS_THREADS);
69      HANDLE(INTEL_HWCONFIG_TOTAL_HS_THREADS);
70      HANDLE(INTEL_HWCONFIG_TOTAL_DS_THREADS);
71      HANDLE(INTEL_HWCONFIG_TOTAL_VS_THREADS_POCS);
72      HANDLE(INTEL_HWCONFIG_TOTAL_PS_THREADS);
73      HANDLE(INTEL_HWCONFIG_DEPRECATED_MAX_FILL_RATE);
74      HANDLE(INTEL_HWCONFIG_MAX_RCS);
75      HANDLE(INTEL_HWCONFIG_MAX_CCS);
76      HANDLE(INTEL_HWCONFIG_MAX_VCS);
77      HANDLE(INTEL_HWCONFIG_MAX_VECS);
78      HANDLE(INTEL_HWCONFIG_MAX_COPY_CS);
79      HANDLE(INTEL_HWCONFIG_DEPRECATED_URB_SIZE_IN_KB);
80      HANDLE(INTEL_HWCONFIG_MIN_VS_URB_ENTRIES);
81      HANDLE(INTEL_HWCONFIG_MAX_VS_URB_ENTRIES);
82      HANDLE(INTEL_HWCONFIG_MIN_PCS_URB_ENTRIES);
83      HANDLE(INTEL_HWCONFIG_MAX_PCS_URB_ENTRIES);
84      HANDLE(INTEL_HWCONFIG_MIN_HS_URB_ENTRIES);
85      HANDLE(INTEL_HWCONFIG_MAX_HS_URB_ENTRIES);
86      HANDLE(INTEL_HWCONFIG_MIN_GS_URB_ENTRIES);
87      HANDLE(INTEL_HWCONFIG_MAX_GS_URB_ENTRIES);
88      HANDLE(INTEL_HWCONFIG_MIN_DS_URB_ENTRIES);
89      HANDLE(INTEL_HWCONFIG_MAX_DS_URB_ENTRIES);
90      HANDLE(INTEL_HWCONFIG_PUSH_CONSTANT_URB_RESERVED_SIZE);
91      HANDLE(INTEL_HWCONFIG_POCS_PUSH_CONSTANT_URB_RESERVED_SIZE);
92      HANDLE(INTEL_HWCONFIG_URB_REGION_ALIGNMENT_SIZE_IN_BYTES);
93      HANDLE(INTEL_HWCONFIG_URB_ALLOCATION_SIZE_UNITS_IN_BYTES);
94      HANDLE(INTEL_HWCONFIG_MAX_URB_SIZE_CCS_IN_BYTES);
95      HANDLE(INTEL_HWCONFIG_VS_MIN_DEREF_BLOCK_SIZE_HANDLE_COUNT);
96      HANDLE(INTEL_HWCONFIG_DS_MIN_DEREF_BLOCK_SIZE_HANDLE_COUNT);
97      HANDLE(INTEL_HWCONFIG_NUM_RT_STACKS_PER_DSS);
98      HANDLE(INTEL_HWCONFIG_MAX_URB_STARTING_ADDRESS);
99      HANDLE(INTEL_HWCONFIG_MIN_CS_URB_ENTRIES);
100      HANDLE(INTEL_HWCONFIG_MAX_CS_URB_ENTRIES);
101      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_URB);
102      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_REST);
103      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_DC);
104      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_RO);
105      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_Z);
106      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_COLOR);
107      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_UNIFIED_TILE_CACHE);
108      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_COMMAND_BUFFER);
109      HANDLE(INTEL_HWCONFIG_L3_ALLOC_PER_BANK_RW);
110      HANDLE(INTEL_HWCONFIG_MAX_NUM_L3_CONFIGS);
111      HANDLE(INTEL_HWCONFIG_BINDLESS_SURFACE_OFFSET_BIT_COUNT);
112      HANDLE(INTEL_HWCONFIG_RESERVED_CCS_WAYS);
113      HANDLE(INTEL_HWCONFIG_CSR_SIZE_IN_MB);
114      HANDLE(INTEL_HWCONFIG_GEOMETRY_PIPES_PER_SLICE);
115      HANDLE(INTEL_HWCONFIG_L3_BANK_SIZE_IN_KB);
116      HANDLE(INTEL_HWCONFIG_SLM_SIZE_PER_DSS);
117      HANDLE(INTEL_HWCONFIG_MAX_PIXEL_FILL_RATE_PER_SLICE);
118      HANDLE(INTEL_HWCONFIG_MAX_PIXEL_FILL_RATE_PER_DSS);
119      HANDLE(INTEL_HWCONFIG_URB_SIZE_PER_SLICE_IN_KB);
120      HANDLE(INTEL_HWCONFIG_URB_SIZE_PER_L3_BANK_COUNT_IN_KB);
121      HANDLE(INTEL_HWCONFIG_MAX_SUBSLICE);
122      HANDLE(INTEL_HWCONFIG_MAX_EU_PER_SUBSLICE);
123      HANDLE(INTEL_HWCONFIG_RAMBO_L3_BANK_SIZE_IN_KB);
124      HANDLE(INTEL_HWCONFIG_SLM_SIZE_PER_SS_IN_KB);
125#undef HANDLE
126   }
127   return "UNKNOWN_INTEL_HWCONFIG";
128}
129
130typedef void (*hwconfig_item_cb)(struct intel_device_info *devinfo,
131                                 const struct hwconfig *item);
132
133static void
134intel_process_hwconfig_table(struct intel_device_info *devinfo,
135                             const struct hwconfig *hwconfig,
136                             int32_t hwconfig_len,
137                             hwconfig_item_cb item_callback_func)
138{
139   assert(hwconfig);
140   assert(hwconfig_len % 4 == 0);
141   const struct hwconfig *current = hwconfig;
142   const struct hwconfig *end =
143      (struct hwconfig*)(((uint32_t*)hwconfig) + (hwconfig_len / 4));
144   while (current < end) {
145      assert(current + 1 < end);
146      struct hwconfig *next =
147         (struct hwconfig*)((uint32_t*)current + 2 + current->len);
148      assert(next <= end);
149      item_callback_func(devinfo, current);
150      current = next;
151   }
152   assert(current == end);
153}
154
155/* If devinfo->apply_hwconfig is true, then we apply the hwconfig value.
156 *
157 * For debug builds, if devinfo->apply_hwconfig is false, we will compare the
158 * hwconfig value with the current value in the devinfo and log a warning
159 * message if they differ. This should help to make sure the values in our
160 * devinfo structures match what hwconfig is specified.
161 */
162#define DEVINFO_HWCONFIG(F, V)                                          \
163   do {                                                                 \
164      if (devinfo->apply_hwconfig)                                      \
165         devinfo->F = V;                                                \
166      else if (DEBUG_BUILD && devinfo->F != (V))                        \
167         mesa_logw("%s (%u) != devinfo->%s (%u)",                       \
168                   key_to_name(item->key), (V), #F,                     \
169                   devinfo->F);                                         \
170   } while (0)
171
172static void
173apply_hwconfig_item(struct intel_device_info *devinfo,
174                    const struct hwconfig *item)
175{
176   switch (item->key) {
177   case INTEL_HWCONFIG_MAX_SLICES_SUPPORTED:
178   case INTEL_HWCONFIG_MAX_DUAL_SUBSLICES_SUPPORTED:
179   case INTEL_HWCONFIG_NUM_PIXEL_PIPES:
180   case INTEL_HWCONFIG_DEPRECATED_MAX_NUM_GEOMETRY_PIPES:
181   case INTEL_HWCONFIG_DEPRECATED_L3_CACHE_SIZE_IN_KB:
182   case INTEL_HWCONFIG_DEPRECATED_L3_BANK_COUNT:
183   case INTEL_HWCONFIG_L3_CACHE_WAYS_SIZE_IN_BYTES:
184   case INTEL_HWCONFIG_L3_CACHE_WAYS_PER_SECTOR:
185   case INTEL_HWCONFIG_MAX_MEMORY_CHANNELS:
186   case INTEL_HWCONFIG_MEMORY_TYPE:
187   case INTEL_HWCONFIG_CACHE_TYPES:
188   case INTEL_HWCONFIG_LOCAL_MEMORY_PAGE_SIZES_SUPPORTED:
189   case INTEL_HWCONFIG_DEPRECATED_SLM_SIZE_IN_KB:
190      break; /* ignore */
191   case INTEL_HWCONFIG_MAX_NUM_EU_PER_DSS:
192      DEVINFO_HWCONFIG(max_eus_per_subslice, item->val[0]);
193      break;
194   case INTEL_HWCONFIG_NUM_THREADS_PER_EU:
195      DEVINFO_HWCONFIG(num_thread_per_eu, item->val[0]);
196      break;
197   case INTEL_HWCONFIG_TOTAL_VS_THREADS:
198      DEVINFO_HWCONFIG(max_vs_threads, item->val[0]);
199      break;
200   case INTEL_HWCONFIG_TOTAL_GS_THREADS:
201      DEVINFO_HWCONFIG(max_gs_threads, item->val[0]);
202      break;
203   case INTEL_HWCONFIG_TOTAL_HS_THREADS:
204      DEVINFO_HWCONFIG(max_tcs_threads, item->val[0]);
205      break;
206   case INTEL_HWCONFIG_TOTAL_DS_THREADS:
207      DEVINFO_HWCONFIG(max_tes_threads, item->val[0]);
208      break;
209   case INTEL_HWCONFIG_TOTAL_VS_THREADS_POCS:
210      break; /* ignore */
211   case INTEL_HWCONFIG_TOTAL_PS_THREADS:
212      DEVINFO_HWCONFIG(max_threads_per_psd, item->val[0] / 2);
213      break;
214   case INTEL_HWCONFIG_URB_SIZE_PER_SLICE_IN_KB:
215      DEVINFO_HWCONFIG(urb.size, item->val[0]);
216      break;
217   case INTEL_HWCONFIG_DEPRECATED_MAX_FILL_RATE:
218   case INTEL_HWCONFIG_MAX_RCS:
219   case INTEL_HWCONFIG_MAX_CCS:
220   case INTEL_HWCONFIG_MAX_VCS:
221   case INTEL_HWCONFIG_MAX_VECS:
222   case INTEL_HWCONFIG_MAX_COPY_CS:
223   case INTEL_HWCONFIG_DEPRECATED_URB_SIZE_IN_KB:
224   case INTEL_HWCONFIG_MIN_VS_URB_ENTRIES:
225   case INTEL_HWCONFIG_MAX_VS_URB_ENTRIES:
226   case INTEL_HWCONFIG_MIN_PCS_URB_ENTRIES:
227   case INTEL_HWCONFIG_MAX_PCS_URB_ENTRIES:
228   case INTEL_HWCONFIG_MIN_HS_URB_ENTRIES:
229   case INTEL_HWCONFIG_MAX_HS_URB_ENTRIES:
230   case INTEL_HWCONFIG_MIN_GS_URB_ENTRIES:
231   case INTEL_HWCONFIG_MAX_GS_URB_ENTRIES:
232   case INTEL_HWCONFIG_MIN_DS_URB_ENTRIES:
233   case INTEL_HWCONFIG_MAX_DS_URB_ENTRIES:
234   case INTEL_HWCONFIG_PUSH_CONSTANT_URB_RESERVED_SIZE:
235   case INTEL_HWCONFIG_POCS_PUSH_CONSTANT_URB_RESERVED_SIZE:
236   case INTEL_HWCONFIG_URB_REGION_ALIGNMENT_SIZE_IN_BYTES:
237   case INTEL_HWCONFIG_URB_ALLOCATION_SIZE_UNITS_IN_BYTES:
238   case INTEL_HWCONFIG_MAX_URB_SIZE_CCS_IN_BYTES:
239   case INTEL_HWCONFIG_VS_MIN_DEREF_BLOCK_SIZE_HANDLE_COUNT:
240   case INTEL_HWCONFIG_DS_MIN_DEREF_BLOCK_SIZE_HANDLE_COUNT:
241   case INTEL_HWCONFIG_NUM_RT_STACKS_PER_DSS:
242   case INTEL_HWCONFIG_MAX_URB_STARTING_ADDRESS:
243   case INTEL_HWCONFIG_MIN_CS_URB_ENTRIES:
244   case INTEL_HWCONFIG_MAX_CS_URB_ENTRIES:
245   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_URB:
246   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_REST:
247   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_DC:
248   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_RO:
249   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_Z:
250   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_COLOR:
251   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_UNIFIED_TILE_CACHE:
252   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_COMMAND_BUFFER:
253   case INTEL_HWCONFIG_L3_ALLOC_PER_BANK_RW:
254   case INTEL_HWCONFIG_MAX_NUM_L3_CONFIGS:
255   case INTEL_HWCONFIG_BINDLESS_SURFACE_OFFSET_BIT_COUNT:
256   case INTEL_HWCONFIG_RESERVED_CCS_WAYS:
257   case INTEL_HWCONFIG_CSR_SIZE_IN_MB:
258   case INTEL_HWCONFIG_GEOMETRY_PIPES_PER_SLICE:
259   case INTEL_HWCONFIG_L3_BANK_SIZE_IN_KB:
260   case INTEL_HWCONFIG_SLM_SIZE_PER_DSS:
261   case INTEL_HWCONFIG_MAX_PIXEL_FILL_RATE_PER_SLICE:
262   case INTEL_HWCONFIG_MAX_PIXEL_FILL_RATE_PER_DSS:
263   case INTEL_HWCONFIG_URB_SIZE_PER_L3_BANK_COUNT_IN_KB:
264   case INTEL_HWCONFIG_MAX_SUBSLICE:
265   case INTEL_HWCONFIG_MAX_EU_PER_SUBSLICE:
266   case INTEL_HWCONFIG_RAMBO_L3_BANK_SIZE_IN_KB:
267   case INTEL_HWCONFIG_SLM_SIZE_PER_SS_IN_KB:
268   default:
269      break; /* ignore */
270   }
271}
272
273bool
274intel_get_and_process_hwconfig_table(int fd,
275                                     struct intel_device_info *devinfo)
276{
277   struct hwconfig *hwconfig;
278   int32_t hwconfig_len = 0;
279   hwconfig = intel_i915_query_alloc(fd, DRM_I915_QUERY_HWCONFIG_BLOB,
280                                     &hwconfig_len);
281   if (hwconfig) {
282      intel_process_hwconfig_table(devinfo, hwconfig, hwconfig_len,
283                                   apply_hwconfig_item);
284      free(hwconfig);
285      if (devinfo->apply_hwconfig)
286         return true;
287   }
288
289   return false;
290}
291
292static void
293print_hwconfig_item(struct intel_device_info *devinfo,
294                    const struct hwconfig *item)
295{
296   printf("%s: ", key_to_name(item->key));
297   for (int i = 0; i < item->len; i++)
298      printf(i ? ", 0x%x (%d)" : "0x%x (%d)", item->val[i],
299              item->val[i]);
300   printf("\n");
301}
302
303static void
304intel_print_hwconfig_table(const struct hwconfig *hwconfig,
305                           int32_t hwconfig_len)
306{
307   intel_process_hwconfig_table(NULL, hwconfig, hwconfig_len,
308                                print_hwconfig_item);
309}
310
311void
312intel_get_and_print_hwconfig_table(int fd)
313{
314   struct hwconfig *hwconfig;
315   int32_t hwconfig_len = 0;
316   hwconfig = intel_i915_query_alloc(fd, DRM_I915_QUERY_HWCONFIG_BLOB,
317                                     &hwconfig_len);
318   if (hwconfig) {
319      intel_print_hwconfig_table(hwconfig, hwconfig_len);
320      free(hwconfig);
321   }
322}
323