xref: /aosp_15_r20/external/mesa3d/src/intel/dev/i915/intel_device_info.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2023 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 <string.h>
25 
26 #include "intel/dev/i915/intel_device_info.h"
27 #include "intel/dev/intel_device_info.h"
28 
29 #include "intel/dev/intel_hwconfig.h"
30 #include "intel/common/intel_gem.h"
31 #include "intel/common/i915/intel_gem.h"
32 
33 #include "util/bitscan.h"
34 #include "util/log.h"
35 #include "util/os_misc.h"
36 
37 #include "drm-uapi/i915_drm.h"
38 
39 /* At some point in time, some people decided to redefine what topology means,
40  * from useful HW related information (slice, subslice, etc...), to much less
41  * useful generic stuff that no one cares about (a single slice with lots of
42  * subslices). Of course all of this was done without asking the people who
43  * defined the topology query in the first place, to solve a lack of
44  * information Gfx10+. This function is here to workaround the fact it's not
45  * possible to change people's mind even before this stuff goes upstream. Sad
46  * times...
47  */
48 static void
update_from_single_slice_topology(struct intel_device_info * devinfo,const struct drm_i915_query_topology_info * topology,const struct drm_i915_query_topology_info * geom_topology)49 update_from_single_slice_topology(struct intel_device_info *devinfo,
50                                   const struct drm_i915_query_topology_info *topology,
51                                   const struct drm_i915_query_topology_info *geom_topology)
52 {
53    /* An array of bit masks of the subslices available for 3D
54     * workloads, analogous to intel_device_info::subslice_masks.  This
55     * may differ from the set of enabled subslices on XeHP+ platforms
56     * with compute-only subslices.
57     */
58    uint8_t geom_subslice_masks[ARRAY_SIZE(devinfo->subslice_masks)] = { 0 };
59 
60    assert(devinfo->verx10 >= 125);
61 
62    intel_device_info_topology_reset_masks(devinfo);
63 
64    assert(topology->max_slices == 1);
65    assert(topology->max_subslices > 0);
66    assert(topology->max_eus_per_subslice > 0);
67 
68    /* i915 gives us only one slice so we have to rebuild that out of groups of
69     * 4 dualsubslices.
70     */
71    devinfo->max_subslices_per_slice = 4;
72    devinfo->max_eus_per_subslice = 16;
73    devinfo->subslice_slice_stride = 1;
74    devinfo->eu_slice_stride = DIV_ROUND_UP(16 * 4, 8);
75    devinfo->eu_subslice_stride = DIV_ROUND_UP(16, 8);
76 
77    for (uint32_t ss_idx = 0; ss_idx < topology->max_subslices; ss_idx++) {
78       const uint32_t s = ss_idx / 4;
79       const uint32_t ss = ss_idx % 4;
80 
81       /* Determine whether ss_idx is enabled (ss_idx_available) and
82        * available for 3D workloads (geom_ss_idx_available), which may
83        * differ on XeHP+ if ss_idx is a compute-only DSS.
84        */
85       const bool ss_idx_available =
86          (topology->data[topology->subslice_offset + ss_idx / 8] >>
87           (ss_idx % 8)) & 1;
88       const bool geom_ss_idx_available =
89          (geom_topology->data[geom_topology->subslice_offset + ss_idx / 8] >>
90           (ss_idx % 8)) & 1;
91 
92       if (geom_ss_idx_available) {
93          assert(ss_idx_available);
94          geom_subslice_masks[s * devinfo->subslice_slice_stride +
95                              ss / 8] |= 1u << (ss % 8);
96       }
97 
98       if (!ss_idx_available)
99          continue;
100 
101       devinfo->max_slices = MAX2(devinfo->max_slices, s + 1);
102       devinfo->slice_masks |= 1u << s;
103 
104       devinfo->subslice_masks[s * devinfo->subslice_slice_stride +
105                               ss / 8] |= 1u << (ss % 8);
106 
107       for (uint32_t eu = 0; eu < devinfo->max_eus_per_subslice; eu++) {
108          const bool eu_available =
109             (topology->data[topology->eu_offset +
110                             ss_idx * topology->eu_stride +
111                             eu / 8] >> (eu % 8)) & 1;
112 
113          if (!eu_available)
114             continue;
115 
116          devinfo->eu_masks[s * devinfo->eu_slice_stride +
117                            ss * devinfo->eu_subslice_stride +
118                            eu / 8] |= 1u << (eu % 8);
119       }
120    }
121 
122    intel_device_info_topology_update_counts(devinfo);
123    intel_device_info_update_pixel_pipes(devinfo, geom_subslice_masks);
124    intel_device_info_update_l3_banks(devinfo);
125 }
126 
127 static void
update_from_topology(struct intel_device_info * devinfo,const struct drm_i915_query_topology_info * topology)128 update_from_topology(struct intel_device_info *devinfo,
129                      const struct drm_i915_query_topology_info *topology)
130 {
131    intel_device_info_topology_reset_masks(devinfo);
132 
133    assert(topology->max_slices > 0);
134    assert(topology->max_subslices > 0);
135    assert(topology->max_eus_per_subslice > 0);
136 
137    devinfo->subslice_slice_stride = topology->subslice_stride;
138 
139    devinfo->eu_subslice_stride = DIV_ROUND_UP(topology->max_eus_per_subslice, 8);
140    devinfo->eu_slice_stride = topology->max_subslices * devinfo->eu_subslice_stride;
141 
142    assert(sizeof(devinfo->slice_masks) >= DIV_ROUND_UP(topology->max_slices, 8));
143    memcpy(&devinfo->slice_masks, topology->data, DIV_ROUND_UP(topology->max_slices, 8));
144    devinfo->max_slices = topology->max_slices;
145    devinfo->max_subslices_per_slice = topology->max_subslices;
146    devinfo->max_eus_per_subslice = topology->max_eus_per_subslice;
147 
148    uint32_t subslice_mask_len =
149       topology->max_slices * topology->subslice_stride;
150    assert(sizeof(devinfo->subslice_masks) >= subslice_mask_len);
151    memcpy(devinfo->subslice_masks, &topology->data[topology->subslice_offset],
152           subslice_mask_len);
153 
154    uint32_t eu_mask_len =
155       topology->eu_stride * topology->max_subslices * topology->max_slices;
156    assert(sizeof(devinfo->eu_masks) >= eu_mask_len);
157    memcpy(devinfo->eu_masks, &topology->data[topology->eu_offset], eu_mask_len);
158 
159    /* Now that all the masks are in place, update the counts. */
160    intel_device_info_topology_update_counts(devinfo);
161    intel_device_info_update_pixel_pipes(devinfo, devinfo->subslice_masks);
162    intel_device_info_update_l3_banks(devinfo);
163 }
164 
165 /* Generate detailed mask from the I915_PARAM_SLICE_MASK,
166  * I915_PARAM_SUBSLICE_MASK & I915_PARAM_EU_TOTAL getparam.
167  */
168 bool
intel_device_info_i915_update_from_masks(struct intel_device_info * devinfo,uint32_t slice_mask,uint32_t subslice_mask,uint32_t n_eus)169 intel_device_info_i915_update_from_masks(struct intel_device_info *devinfo, uint32_t slice_mask,
170                        uint32_t subslice_mask, uint32_t n_eus)
171 {
172    struct drm_i915_query_topology_info *topology;
173 
174    assert((slice_mask & 0xff) == slice_mask);
175 
176    size_t data_length = 100;
177 
178    topology = calloc(1, sizeof(*topology) + data_length);
179    if (!topology)
180       return false;
181 
182    topology->max_slices = util_last_bit(slice_mask);
183    topology->max_subslices = util_last_bit(subslice_mask);
184 
185    topology->subslice_offset = DIV_ROUND_UP(topology->max_slices, 8);
186    topology->subslice_stride = DIV_ROUND_UP(topology->max_subslices, 8);
187 
188    uint32_t n_subslices = __builtin_popcount(slice_mask) *
189       __builtin_popcount(subslice_mask);
190    uint32_t max_eus_per_subslice = DIV_ROUND_UP(n_eus, n_subslices);
191    uint32_t eu_mask = (1U << max_eus_per_subslice) - 1;
192 
193    topology->max_eus_per_subslice = max_eus_per_subslice;
194    topology->eu_offset = topology->subslice_offset +
195       topology->max_slices * DIV_ROUND_UP(topology->max_subslices, 8);
196    topology->eu_stride = DIV_ROUND_UP(max_eus_per_subslice, 8);
197 
198    /* Set slice mask in topology */
199    for (int b = 0; b < topology->subslice_offset; b++)
200       topology->data[b] = (slice_mask >> (b * 8)) & 0xff;
201 
202    for (int s = 0; s < topology->max_slices; s++) {
203 
204       /* Set subslice mask in topology */
205       for (int b = 0; b < topology->subslice_stride; b++) {
206          int subslice_offset = topology->subslice_offset +
207             s * topology->subslice_stride + b;
208 
209          topology->data[subslice_offset] = (subslice_mask >> (b * 8)) & 0xff;
210       }
211 
212       /* Set eu mask in topology */
213       for (int ss = 0; ss < topology->max_subslices; ss++) {
214          for (int b = 0; b < topology->eu_stride; b++) {
215             int eu_offset = topology->eu_offset +
216                (s * topology->max_subslices + ss) * topology->eu_stride + b;
217 
218             topology->data[eu_offset] = (eu_mask >> (b * 8)) & 0xff;
219          }
220       }
221    }
222 
223    update_from_topology(devinfo, topology);
224    free(topology);
225 
226    return true;
227 }
228 
229 static bool
getparam(int fd,uint32_t param,int * value)230 getparam(int fd, uint32_t param, int *value)
231 {
232    int tmp;
233 
234    struct drm_i915_getparam gp = {
235       .param = param,
236       .value = &tmp,
237    };
238 
239    int ret = intel_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
240    if (ret != 0)
241       return false;
242 
243    *value = tmp;
244    return true;
245 }
246 
247 static bool
get_context_param(int fd,uint32_t context,uint32_t param,uint64_t * value)248 get_context_param(int fd, uint32_t context, uint32_t param, uint64_t *value)
249 {
250    struct drm_i915_gem_context_param gp = {
251       .ctx_id = context,
252       .param = param,
253    };
254 
255    int ret = intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &gp);
256    if (ret != 0)
257       return false;
258 
259    *value = gp.value;
260    return true;
261 }
262 
263 /**
264  * for gfx8/gfx9, SLICE_MASK/SUBSLICE_MASK can be used to compute the topology
265  * (kernel 4.13+)
266  */
267 static bool
getparam_topology(struct intel_device_info * devinfo,int fd)268 getparam_topology(struct intel_device_info *devinfo, int fd)
269 {
270    int slice_mask = 0;
271    if (!getparam(fd, I915_PARAM_SLICE_MASK, &slice_mask))
272       goto maybe_warn;
273 
274    int n_eus;
275    if (!getparam(fd, I915_PARAM_EU_TOTAL, &n_eus))
276       goto maybe_warn;
277 
278    int subslice_mask = 0;
279    if (!getparam(fd, I915_PARAM_SUBSLICE_MASK, &subslice_mask))
280       goto maybe_warn;
281 
282    return intel_device_info_i915_update_from_masks(devinfo, slice_mask, subslice_mask, n_eus);
283 
284  maybe_warn:
285    /* Only with Gfx8+ are we starting to see devices with fusing that can only
286     * be detected at runtime.
287     */
288    if (devinfo->ver >= 8)
289       mesa_logw("Kernel 4.1 required to properly query GPU properties.");
290 
291    return false;
292 }
293 
294 /**
295  * preferred API for updating the topology in devinfo (kernel 4.17+)
296  */
297 static bool
query_topology(struct intel_device_info * devinfo,int fd)298 query_topology(struct intel_device_info *devinfo, int fd)
299 {
300    struct drm_i915_query_topology_info *topo_info =
301       intel_i915_query_alloc(fd, DRM_I915_QUERY_TOPOLOGY_INFO, NULL);
302    if (topo_info == NULL)
303       return false;
304 
305    if (devinfo->verx10 >= 125) {
306       struct drm_i915_query_topology_info *geom_topo_info =
307          intel_i915_query_alloc(fd, DRM_I915_QUERY_GEOMETRY_SUBSLICES, NULL);
308       if (geom_topo_info == NULL) {
309          free(topo_info);
310          return false;
311       }
312 
313       update_from_single_slice_topology(devinfo, topo_info, geom_topo_info);
314       free(geom_topo_info);
315    } else {
316       update_from_topology(devinfo, topo_info);
317    }
318 
319    free(topo_info);
320 
321    return true;
322 
323 }
324 
325 /**
326  * Reports memory region info, and allows buffers to target system-memory,
327  * and/or device local memory.
328  */
329 bool
intel_device_info_i915_query_regions(struct intel_device_info * devinfo,int fd,bool update)330 intel_device_info_i915_query_regions(struct intel_device_info *devinfo, int fd, bool update)
331 {
332    struct drm_i915_query_memory_regions *meminfo =
333       intel_i915_query_alloc(fd, DRM_I915_QUERY_MEMORY_REGIONS, NULL);
334 
335    if (meminfo == NULL) {
336       /* If the memory region uAPI query is not available, try to generate some
337        * numbers out of os_* utils for sram only.
338        */
339       bool ret = intel_device_info_compute_system_memory(devinfo, false);
340       devinfo->mem.sram.mappable.size /= 2;
341       return ret;
342    }
343 
344    for (int i = 0; i < meminfo->num_regions; i++) {
345       const struct drm_i915_memory_region_info *mem = &meminfo->regions[i];
346       switch (mem->region.memory_class) {
347       case I915_MEMORY_CLASS_SYSTEM: {
348          if (!update) {
349             devinfo->mem.sram.mem.klass = mem->region.memory_class;
350             devinfo->mem.sram.mem.instance = mem->region.memory_instance;
351             /* i915 reports the whole RAM as SRAM size but Xe KMD only reports
352              * half, so adjusting i915 to follow Xe KMD.
353              */
354             devinfo->mem.sram.mappable.size = mem->probed_size / 2;
355          } else {
356             assert(devinfo->mem.sram.mem.klass == mem->region.memory_class);
357             assert(devinfo->mem.sram.mem.instance == mem->region.memory_instance);
358             assert(devinfo->mem.sram.mappable.size == mem->probed_size / 2);
359          }
360          /* if running without elevated privileges i915 reports
361           * unallocated_size == probed_size
362           */
363          devinfo->mem.sram.mappable.free = mem->unallocated_size;
364          break;
365       }
366       case I915_MEMORY_CLASS_DEVICE:
367          if (!update) {
368             devinfo->mem.vram.mem.klass = mem->region.memory_class;
369             devinfo->mem.vram.mem.instance = mem->region.memory_instance;
370             if (mem->probed_cpu_visible_size > 0) {
371                devinfo->mem.vram.mappable.size = mem->probed_cpu_visible_size;
372                devinfo->mem.vram.unmappable.size =
373                   mem->probed_size - mem->probed_cpu_visible_size;
374             } else {
375                /* We are running on an older kernel without support for the
376                 * small-bar uapi. These kernels only support systems where the
377                 * entire vram is mappable.
378                 */
379                devinfo->mem.vram.mappable.size = mem->probed_size;
380                devinfo->mem.vram.unmappable.size = 0;
381             }
382          } else {
383             assert(devinfo->mem.vram.mem.klass == mem->region.memory_class);
384             assert(devinfo->mem.vram.mem.instance == mem->region.memory_instance);
385             assert((devinfo->mem.vram.mappable.size +
386                     devinfo->mem.vram.unmappable.size) == mem->probed_size);
387          }
388          if (mem->unallocated_cpu_visible_size > 0) {
389             if (mem->unallocated_size != -1) {
390                devinfo->mem.vram.mappable.free = mem->unallocated_cpu_visible_size;
391                devinfo->mem.vram.unmappable.free =
392                   mem->unallocated_size - mem->unallocated_cpu_visible_size;
393             }
394          } else {
395             /* We are running on an older kernel without support for the
396              * small-bar uapi. These kernels only support systems where the
397              * entire vram is mappable.
398              */
399             if (mem->unallocated_size != -1) {
400                devinfo->mem.vram.mappable.free = mem->unallocated_size;
401                devinfo->mem.vram.unmappable.free = 0;
402             }
403          }
404          break;
405       default:
406          break;
407       }
408    }
409 
410    free(meminfo);
411    devinfo->mem.use_class_instance = true;
412    return true;
413 }
414 
415 static int
intel_get_aperture_size(int fd,uint64_t * size)416 intel_get_aperture_size(int fd, uint64_t *size)
417 {
418    struct drm_i915_gem_get_aperture aperture = { 0 };
419 
420    int ret = intel_ioctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
421    if (ret == 0 && size)
422       *size = aperture.aper_size;
423 
424    return ret;
425 }
426 
427 static bool
has_bit6_swizzle(int fd)428 has_bit6_swizzle(int fd)
429 {
430    struct drm_gem_close close;
431 
432    struct drm_i915_gem_create gem_create = {
433       .size = 4096,
434    };
435 
436    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create)) {
437       unreachable("Failed to create GEM BO");
438       return false;
439    }
440 
441    bool swizzled = false;
442 
443    /* set_tiling overwrites the input on the error path, so we have to open
444     * code intel_ioctl.
445     */
446    struct drm_i915_gem_set_tiling set_tiling = {
447       .handle = gem_create.handle,
448       .tiling_mode = I915_TILING_X,
449       .stride = 512,
450    };
451 
452    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling)) {
453       unreachable("Failed to set BO tiling");
454       goto close_and_return;
455    }
456 
457    struct drm_i915_gem_get_tiling get_tiling = {
458       .handle = gem_create.handle,
459    };
460 
461    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) {
462       unreachable("Failed to get BO tiling");
463       goto close_and_return;
464    }
465 
466    assert(get_tiling.tiling_mode == I915_TILING_X);
467    swizzled = get_tiling.swizzle_mode != I915_BIT_6_SWIZZLE_NONE;
468 
469 close_and_return:
470    memset(&close, 0, sizeof(close));
471    close.handle = gem_create.handle;
472    intel_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
473 
474    return swizzled;
475 }
476 
477 static bool
has_get_tiling(int fd)478 has_get_tiling(int fd)
479 {
480    int ret;
481 
482    struct drm_i915_gem_create gem_create = {
483       .size = 4096,
484    };
485 
486    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create)) {
487       unreachable("Failed to create GEM BO");
488       return false;
489    }
490 
491    struct drm_i915_gem_get_tiling get_tiling = {
492       .handle = gem_create.handle,
493    };
494    ret = intel_ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &get_tiling);
495 
496    struct drm_gem_close close = {
497       .handle = gem_create.handle,
498    };
499    intel_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close);
500 
501    return ret == 0;
502 }
503 
504 static void
fixup_chv_device_info(struct intel_device_info * devinfo)505 fixup_chv_device_info(struct intel_device_info *devinfo)
506 {
507    assert(devinfo->platform == INTEL_PLATFORM_CHV);
508 
509    /* Cherryview is annoying.  The number of EUs is depending on fusing and
510     * isn't determinable from the PCI ID alone.  We default to the minimum
511     * available for that PCI ID and then compute the real value from the
512     * subslice information we get from the kernel.
513     */
514    const uint32_t subslice_total = intel_device_info_subslice_total(devinfo);
515    const uint32_t eu_total = intel_device_info_eu_total(devinfo);
516 
517    /* Logical CS threads = EUs per subslice * num threads per EU */
518    uint32_t max_cs_threads =
519       eu_total / subslice_total * devinfo->num_thread_per_eu;
520 
521    /* Fuse configurations may give more threads than expected, never less. */
522    if (max_cs_threads > devinfo->max_cs_threads)
523       devinfo->max_cs_threads = max_cs_threads;
524 
525    intel_device_info_update_cs_workgroup_threads(devinfo);
526 
527    /* Braswell is even more annoying.  Its marketing name isn't determinable
528     * from the PCI ID and is also dependent on fusing.
529     */
530    if (devinfo->pci_device_id != 0x22B1)
531       return;
532 
533    char *bsw_model;
534    switch (eu_total) {
535    case 16: bsw_model = "405"; break;
536    case 12: bsw_model = "400"; break;
537    default: bsw_model = "   "; break;
538    }
539 
540    char *needle = strstr(devinfo->name, "XXX");
541    assert(needle);
542    if (needle)
543       memcpy(needle, bsw_model, 3);
544 }
545 
546 void *
intel_device_info_i915_query_hwconfig(int fd,int32_t * len)547 intel_device_info_i915_query_hwconfig(int fd, int32_t *len)
548 {
549    return intel_i915_query_alloc(fd, DRM_I915_QUERY_HWCONFIG_BLOB, len);
550 }
551 
intel_device_info_i915_get_info_from_fd(int fd,struct intel_device_info * devinfo)552 bool intel_device_info_i915_get_info_from_fd(int fd, struct intel_device_info *devinfo)
553 {
554    void *hwconfig_blob;
555    int32_t len;
556 
557    hwconfig_blob = intel_device_info_i915_query_hwconfig(fd, &len);
558    if (hwconfig_blob) {
559       if (intel_hwconfig_process_table(devinfo, hwconfig_blob, len))
560          intel_device_info_update_after_hwconfig(devinfo);
561 
562       free(hwconfig_blob);
563    }
564 
565    int val;
566    if (getparam(fd, I915_PARAM_CS_TIMESTAMP_FREQUENCY, &val))
567       devinfo->timestamp_frequency = val;
568    else if (devinfo->ver >= 10) {
569       mesa_loge("Kernel 4.15 required to read the CS timestamp frequency.");
570       return false;
571    }
572 
573    if (!getparam(fd, I915_PARAM_REVISION, &devinfo->revision))
574       devinfo->revision = 0;
575 
576    if (!query_topology(devinfo, fd)) {
577       if (devinfo->ver >= 10) {
578          /* topology uAPI required for CNL+ (kernel 4.17+) */
579          return false;
580       }
581 
582       /* else use the kernel 4.13+ api for gfx8+.  For older kernels, topology
583        * will be wrong, affecting GPU metrics. In this case, fail silently.
584        */
585       getparam_topology(devinfo, fd);
586    }
587 
588    intel_device_info_i915_query_regions(devinfo, fd, false);
589 
590    if (devinfo->platform == INTEL_PLATFORM_CHV)
591       fixup_chv_device_info(devinfo);
592 
593    /* Broadwell PRM says:
594     *
595     *   "Before Gfx8, there was a historical configuration control field to
596     *    swizzle address bit[6] for in X/Y tiling modes. This was set in three
597     *    different places: TILECTL[1:0], ARB_MODE[5:4], and
598     *    DISP_ARB_CTL[14:13].
599     *
600     *    For Gfx8 and subsequent generations, the swizzle fields are all
601     *    reserved, and the CPU's memory controller performs all address
602     *    swizzling modifications."
603     */
604    devinfo->has_bit6_swizzle = devinfo->ver < 8 && has_bit6_swizzle(fd);
605 
606    intel_get_aperture_size(fd, &devinfo->aperture_bytes);
607    get_context_param(fd, 0, I915_CONTEXT_PARAM_GTT_SIZE, &devinfo->gtt_size);
608    devinfo->has_tiling_uapi = has_get_tiling(fd);
609    devinfo->has_caching_uapi =
610       devinfo->platform < INTEL_PLATFORM_DG2_START && !devinfo->has_local_mem;
611    if (devinfo->ver > 12 || intel_device_info_is_mtl_or_arl(devinfo))
612       devinfo->has_set_pat_uapi = true;
613 
614    if (getparam(fd, I915_PARAM_MMAP_GTT_VERSION, &val))
615       devinfo->has_mmap_offset = val >= 4;
616    if (getparam(fd, I915_PARAM_HAS_USERPTR_PROBE, &val))
617       devinfo->has_userptr_probe = val;
618    if (getparam(fd, I915_PARAM_HAS_CONTEXT_ISOLATION, &val))
619       devinfo->has_context_isolation = val;
620 
621    /* TODO: We might be able to reduce alignment to 4Kb on DG1. */
622    if (devinfo->verx10 >= 125)
623       devinfo->mem_alignment = 64 * 1024;
624    else if (devinfo->has_local_mem)
625       devinfo->mem_alignment = 64 * 1024;
626    else
627       devinfo->mem_alignment = 4096;
628 
629    return true;
630 }
631