1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <stdio.h>
25bf215546Sopenharmony_ci#include <stdlib.h>
26bf215546Sopenharmony_ci#include <unistd.h>
27bf215546Sopenharmony_ci#include <sys/ioctl.h>
28bf215546Sopenharmony_ci#include <sys/mman.h>
29bf215546Sopenharmony_ci#include <sys/types.h>
30bf215546Sopenharmony_ci#include <sys/socket.h>
31bf215546Sopenharmony_ci#include <sys/time.h>
32bf215546Sopenharmony_ci#include <sys/resource.h>
33bf215546Sopenharmony_ci#include <sys/un.h>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "common/intel_gem.h"
36bf215546Sopenharmony_ci#include "dev/intel_device_info.h"
37bf215546Sopenharmony_ci#include "drm-uapi/i915_drm.h"
38bf215546Sopenharmony_ci#include "drm-shim/drm_shim.h"
39bf215546Sopenharmony_ci#include "util/macros.h"
40bf215546Sopenharmony_ci#include "util/vma.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistruct i915_device {
43bf215546Sopenharmony_ci   struct intel_device_info devinfo;
44bf215546Sopenharmony_ci   uint32_t device_id;
45bf215546Sopenharmony_ci};
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cistruct i915_bo {
48bf215546Sopenharmony_ci   struct shim_bo base;
49bf215546Sopenharmony_ci   uint32_t tiling_mode;
50bf215546Sopenharmony_ci   uint32_t stride;
51bf215546Sopenharmony_ci};
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic struct i915_device i915 = {};
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cibool drm_shim_driver_prefers_first_render_node = true;
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_cistatic int
58bf215546Sopenharmony_cii915_ioctl_noop(int fd, unsigned long request, void *arg)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   return 0;
61bf215546Sopenharmony_ci}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_cistatic int
64bf215546Sopenharmony_cii915_ioctl_gem_set_tiling(int fd, unsigned long request, void *arg)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
67bf215546Sopenharmony_ci   struct drm_i915_gem_set_tiling *tiling_arg = arg;
68bf215546Sopenharmony_ci   struct i915_bo *bo = (struct i915_bo *) drm_shim_bo_lookup(shim_fd, tiling_arg->handle);
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   if (!bo)
71bf215546Sopenharmony_ci      return -1;
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci   bo->tiling_mode = tiling_arg->tiling_mode;
74bf215546Sopenharmony_ci   bo->stride = tiling_arg->stride;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   return 0;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistatic int
80bf215546Sopenharmony_cii915_ioctl_gem_get_tiling(int fd, unsigned long request, void *arg)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
83bf215546Sopenharmony_ci   struct drm_i915_gem_get_tiling *tiling_arg = arg;
84bf215546Sopenharmony_ci   struct i915_bo *bo = (struct i915_bo *) drm_shim_bo_lookup(shim_fd, tiling_arg->handle);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   if (!bo)
87bf215546Sopenharmony_ci      return -1;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   tiling_arg->tiling_mode = bo->tiling_mode;
90bf215546Sopenharmony_ci   tiling_arg->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
91bf215546Sopenharmony_ci   tiling_arg->phys_swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   return 0;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistatic int
97bf215546Sopenharmony_cii915_ioctl_gem_create(int fd, unsigned long request, void *arg)
98bf215546Sopenharmony_ci{
99bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
100bf215546Sopenharmony_ci   struct drm_i915_gem_create *create = arg;
101bf215546Sopenharmony_ci   struct i915_bo *bo = calloc(1, sizeof(*bo));
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   drm_shim_bo_init(&bo->base, create->size);
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   create->handle = drm_shim_bo_get_handle(shim_fd, &bo->base);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   drm_shim_bo_put(&bo->base);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   return 0;
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_cistatic int
113bf215546Sopenharmony_cii915_ioctl_gem_mmap(int fd, unsigned long request, void *arg)
114bf215546Sopenharmony_ci{
115bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
116bf215546Sopenharmony_ci   struct drm_i915_gem_mmap *mmap_arg = arg;
117bf215546Sopenharmony_ci   struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, mmap_arg->handle);
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci   if (!bo)
120bf215546Sopenharmony_ci      return -1;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   if (!bo->map)
123bf215546Sopenharmony_ci      bo->map = drm_shim_mmap(shim_fd, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, -1,
124bf215546Sopenharmony_ci                              drm_shim_bo_get_mmap_offset(shim_fd, bo));
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   mmap_arg->addr_ptr = (uint64_t) (bo->map + mmap_arg->offset);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   return 0;
129bf215546Sopenharmony_ci}
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_cistatic int
132bf215546Sopenharmony_cii915_ioctl_gem_userptr(int fd, unsigned long request, void *arg)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci   struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
135bf215546Sopenharmony_ci   struct drm_i915_gem_userptr *userptr = arg;
136bf215546Sopenharmony_ci   struct i915_bo *bo = calloc(1, sizeof(*bo));
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   drm_shim_bo_init(&bo->base, userptr->user_size);
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   userptr->handle = drm_shim_bo_get_handle(shim_fd, &bo->base);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   drm_shim_bo_put(&bo->base);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   return 0;
145bf215546Sopenharmony_ci}
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_cistatic int
148bf215546Sopenharmony_cii915_ioctl_gem_context_create(int fd, unsigned long request, void *arg)
149bf215546Sopenharmony_ci{
150bf215546Sopenharmony_ci   struct drm_i915_gem_context_create *create = arg;
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   create->ctx_id = 1; /* Just return a fake non zero ID. */
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci   return 0;
155bf215546Sopenharmony_ci}
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_cistatic int
158bf215546Sopenharmony_cii915_ioctl_gem_context_getparam(int fd, unsigned long request, void *arg)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct drm_i915_gem_context_param *param = arg;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   if (param->param ==  I915_CONTEXT_PARAM_GTT_SIZE) {
163bf215546Sopenharmony_ci      if (i915.devinfo.ver >= 8 && i915.devinfo.platform != INTEL_PLATFORM_CHV)
164bf215546Sopenharmony_ci         param->value = 1ull << 48;
165bf215546Sopenharmony_ci      else
166bf215546Sopenharmony_ci         param->value = 1ull << 31;
167bf215546Sopenharmony_ci   } else {
168bf215546Sopenharmony_ci      param->value = 0;
169bf215546Sopenharmony_ci   }
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   return 0;
172bf215546Sopenharmony_ci}
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_cistatic int
175bf215546Sopenharmony_cii915_ioctl_get_param(int fd, unsigned long request, void *arg)
176bf215546Sopenharmony_ci{
177bf215546Sopenharmony_ci   drm_i915_getparam_t *gp = arg;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   switch (gp->param) {
180bf215546Sopenharmony_ci   case I915_PARAM_CHIPSET_ID:
181bf215546Sopenharmony_ci      *gp->value = i915.device_id;
182bf215546Sopenharmony_ci      return 0;
183bf215546Sopenharmony_ci   case I915_PARAM_REVISION:
184bf215546Sopenharmony_ci      *gp->value = 0;
185bf215546Sopenharmony_ci      return 0;
186bf215546Sopenharmony_ci   case I915_PARAM_CS_TIMESTAMP_FREQUENCY:
187bf215546Sopenharmony_ci      *gp->value = i915.devinfo.timestamp_frequency;
188bf215546Sopenharmony_ci      return 0;
189bf215546Sopenharmony_ci   case I915_PARAM_HAS_ALIASING_PPGTT:
190bf215546Sopenharmony_ci      if (i915.devinfo.ver < 6)
191bf215546Sopenharmony_ci         *gp->value = I915_GEM_PPGTT_NONE;
192bf215546Sopenharmony_ci      else if (i915.devinfo.ver <= 7)
193bf215546Sopenharmony_ci         *gp->value = I915_GEM_PPGTT_ALIASING;
194bf215546Sopenharmony_ci      else
195bf215546Sopenharmony_ci         *gp->value = I915_GEM_PPGTT_FULL;
196bf215546Sopenharmony_ci      return 0;
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci   case I915_PARAM_NUM_FENCES_AVAIL:
199bf215546Sopenharmony_ci      *gp->value = 8; /* gfx2/3 value, unused in brw/iris */
200bf215546Sopenharmony_ci      return 0;
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   case I915_PARAM_HAS_BLT:
203bf215546Sopenharmony_ci      *gp->value = 1; /* gfx2/3 value, unused in brw/iris */
204bf215546Sopenharmony_ci      return 0;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   case I915_PARAM_HAS_BSD:
207bf215546Sopenharmony_ci   case I915_PARAM_HAS_LLC:
208bf215546Sopenharmony_ci   case I915_PARAM_HAS_VEBOX:
209bf215546Sopenharmony_ci      *gp->value = 0; /* gfx2/3 value, unused in brw/iris */
210bf215546Sopenharmony_ci      return 0;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   case I915_PARAM_HAS_GEM:
213bf215546Sopenharmony_ci   case I915_PARAM_HAS_RELAXED_DELTA:
214bf215546Sopenharmony_ci   case I915_PARAM_HAS_RELAXED_FENCING:
215bf215546Sopenharmony_ci   case I915_PARAM_HAS_WAIT_TIMEOUT:
216bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXECBUF2:
217bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_SOFTPIN:
218bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_CAPTURE:
219bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_FENCE:
220bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_FENCE_ARRAY:
221bf215546Sopenharmony_ci   case I915_PARAM_HAS_CONTEXT_ISOLATION:
222bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_ASYNC:
223bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_NO_RELOC:
224bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_BATCH_FIRST:
225bf215546Sopenharmony_ci      *gp->value = true;
226bf215546Sopenharmony_ci      return 0;
227bf215546Sopenharmony_ci   case I915_PARAM_HAS_EXEC_TIMELINE_FENCES:
228bf215546Sopenharmony_ci      *gp->value = false;
229bf215546Sopenharmony_ci      return 0;
230bf215546Sopenharmony_ci   case I915_PARAM_CMD_PARSER_VERSION:
231bf215546Sopenharmony_ci      /* Most recent version in drivers/gpu/drm/i915/i915_cmd_parser.c */
232bf215546Sopenharmony_ci      *gp->value = 10;
233bf215546Sopenharmony_ci      return 0;
234bf215546Sopenharmony_ci   case I915_PARAM_MMAP_VERSION:
235bf215546Sopenharmony_ci   case I915_PARAM_MMAP_GTT_VERSION:
236bf215546Sopenharmony_ci      *gp->value = 1;
237bf215546Sopenharmony_ci      return 0;
238bf215546Sopenharmony_ci   case I915_PARAM_SUBSLICE_TOTAL:
239bf215546Sopenharmony_ci      *gp->value = 0;
240bf215546Sopenharmony_ci      for (uint32_t s = 0; s < i915.devinfo.num_slices; s++)
241bf215546Sopenharmony_ci         *gp->value += i915.devinfo.num_subslices[s];
242bf215546Sopenharmony_ci      return 0;
243bf215546Sopenharmony_ci   case I915_PARAM_EU_TOTAL:
244bf215546Sopenharmony_ci      *gp->value = 0;
245bf215546Sopenharmony_ci      for (uint32_t s = 0; s < i915.devinfo.num_slices; s++)
246bf215546Sopenharmony_ci         *gp->value += i915.devinfo.num_subslices[s] * i915.devinfo.max_eus_per_subslice;
247bf215546Sopenharmony_ci      return 0;
248bf215546Sopenharmony_ci   case I915_PARAM_PERF_REVISION:
249bf215546Sopenharmony_ci      *gp->value = 3;
250bf215546Sopenharmony_ci      return 0;
251bf215546Sopenharmony_ci   case I915_PARAM_HAS_USERPTR_PROBE:
252bf215546Sopenharmony_ci      *gp->value = 0;
253bf215546Sopenharmony_ci      return 0;
254bf215546Sopenharmony_ci   default:
255bf215546Sopenharmony_ci      break;
256bf215546Sopenharmony_ci   }
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   fprintf(stderr, "Unknown DRM_IOCTL_I915_GET_PARAM %d\n", gp->param);
259bf215546Sopenharmony_ci   return -1;
260bf215546Sopenharmony_ci}
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_cistatic int
263bf215546Sopenharmony_ciquery_write_topology(struct drm_i915_query_item *item)
264bf215546Sopenharmony_ci{
265bf215546Sopenharmony_ci   struct drm_i915_query_topology_info *info =
266bf215546Sopenharmony_ci      (void *) (uintptr_t) item->data_ptr;
267bf215546Sopenharmony_ci   int32_t length =
268bf215546Sopenharmony_ci      sizeof(*info) +
269bf215546Sopenharmony_ci      DIV_ROUND_UP(i915.devinfo.num_slices, 8) +
270bf215546Sopenharmony_ci      i915.devinfo.num_slices * DIV_ROUND_UP(i915.devinfo.num_subslices[0], 8) +
271bf215546Sopenharmony_ci      i915.devinfo.num_slices * i915.devinfo.num_subslices[0] *
272bf215546Sopenharmony_ci      DIV_ROUND_UP(i915.devinfo.max_eus_per_subslice, 8);
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   if (item->length == 0) {
275bf215546Sopenharmony_ci      item->length = length;
276bf215546Sopenharmony_ci      return 0;
277bf215546Sopenharmony_ci   }
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci   if (item->length < length) {
280bf215546Sopenharmony_ci      fprintf(stderr, "size too small\n");
281bf215546Sopenharmony_ci      return -EINVAL;
282bf215546Sopenharmony_ci   }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   if (info->flags) {
285bf215546Sopenharmony_ci      fprintf(stderr, "invalid topology flags\n");
286bf215546Sopenharmony_ci      return -EINVAL;
287bf215546Sopenharmony_ci   }
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   info->max_slices = i915.devinfo.num_slices;
290bf215546Sopenharmony_ci   info->max_subslices = i915.devinfo.num_subslices[0];
291bf215546Sopenharmony_ci   info->max_eus_per_subslice = i915.devinfo.max_eus_per_subslice;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   info->subslice_offset = DIV_ROUND_UP(i915.devinfo.num_slices, 8);
294bf215546Sopenharmony_ci   info->subslice_stride = DIV_ROUND_UP(i915.devinfo.num_subslices[0], 8);
295bf215546Sopenharmony_ci   info->eu_offset = info->subslice_offset + info->max_slices * info->subslice_stride;
296bf215546Sopenharmony_ci   info->eu_stride = DIV_ROUND_UP(info->max_eus_per_subslice, 8);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   uint32_t slice_mask = (1u << i915.devinfo.num_slices) - 1;
299bf215546Sopenharmony_ci   for (uint32_t i = 0; i < info->subslice_offset; i++)
300bf215546Sopenharmony_ci      info->data[i] = (slice_mask >> (8 * i)) & 0xff;
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   for (uint32_t s = 0; s < i915.devinfo.num_slices; s++) {
303bf215546Sopenharmony_ci      uint32_t subslice_mask = (1u << i915.devinfo.num_subslices[s]) - 1;
304bf215546Sopenharmony_ci      for (uint32_t i = 0; i < info->subslice_stride; i++) {
305bf215546Sopenharmony_ci         info->data[info->subslice_offset + s * info->subslice_stride + i] =
306bf215546Sopenharmony_ci            (subslice_mask >> (8 * i)) & 0xff;
307bf215546Sopenharmony_ci      }
308bf215546Sopenharmony_ci   }
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   for (uint32_t s = 0; s < i915.devinfo.num_slices; s++) {
311bf215546Sopenharmony_ci      for (uint32_t ss = 0; ss < i915.devinfo.num_subslices[s]; ss++) {
312bf215546Sopenharmony_ci         uint32_t eu_mask = (1u << info->max_eus_per_subslice) - 1;
313bf215546Sopenharmony_ci         for (uint32_t i = 0; i < DIV_ROUND_UP(info->max_eus_per_subslice, 8); i++) {
314bf215546Sopenharmony_ci            info->data[info->eu_offset +
315bf215546Sopenharmony_ci                       (s * info->max_subslices + ss) * DIV_ROUND_UP(info->max_eus_per_subslice, 8) + i] =
316bf215546Sopenharmony_ci               (eu_mask >> (8 * i)) & 0xff;
317bf215546Sopenharmony_ci         }
318bf215546Sopenharmony_ci      }
319bf215546Sopenharmony_ci   }
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   return 0;
322bf215546Sopenharmony_ci}
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_cistatic int
325bf215546Sopenharmony_cii915_ioctl_query(int fd, unsigned long request, void *arg)
326bf215546Sopenharmony_ci{
327bf215546Sopenharmony_ci   struct drm_i915_query *query = arg;
328bf215546Sopenharmony_ci   struct drm_i915_query_item *items = (void *) (uintptr_t) query->items_ptr;
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   if (query->flags) {
331bf215546Sopenharmony_ci      fprintf(stderr, "invalid query flags\n");
332bf215546Sopenharmony_ci      return -EINVAL;
333bf215546Sopenharmony_ci   }
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_ci   for (uint32_t i = 0; i < query->num_items; i++) {
336bf215546Sopenharmony_ci      struct drm_i915_query_item *item = &items[i];
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci      switch (item->query_id) {
339bf215546Sopenharmony_ci      case DRM_I915_QUERY_TOPOLOGY_INFO: {
340bf215546Sopenharmony_ci         int ret = query_write_topology(item);
341bf215546Sopenharmony_ci         if (ret)
342bf215546Sopenharmony_ci            item->length = ret;
343bf215546Sopenharmony_ci         break;
344bf215546Sopenharmony_ci      }
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci      case DRM_I915_QUERY_ENGINE_INFO: {
347bf215546Sopenharmony_ci         uint32_t num_copy = 1;
348bf215546Sopenharmony_ci         uint32_t num_render = 1;
349bf215546Sopenharmony_ci         uint32_t num_engines = num_copy + num_render;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci         struct drm_i915_query_engine_info *info =
352bf215546Sopenharmony_ci            (struct drm_i915_query_engine_info*)(uintptr_t)item->data_ptr;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci         int32_t data_length =
355bf215546Sopenharmony_ci            sizeof(*info) +
356bf215546Sopenharmony_ci               num_engines * sizeof(info->engines[0]);
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci         if (item->length == 0) {
359bf215546Sopenharmony_ci            item->length = data_length;
360bf215546Sopenharmony_ci            return 0;
361bf215546Sopenharmony_ci         } else if (item->length < data_length) {
362bf215546Sopenharmony_ci            item->length = -EINVAL;
363bf215546Sopenharmony_ci            return -1;
364bf215546Sopenharmony_ci         } else {
365bf215546Sopenharmony_ci            memset(info, 0, data_length);
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci            for (uint32_t e = 0; e < num_render; e++, info->num_engines++) {
368bf215546Sopenharmony_ci               info->engines[info->num_engines].engine.engine_class =
369bf215546Sopenharmony_ci                  I915_ENGINE_CLASS_RENDER;
370bf215546Sopenharmony_ci               info->engines[info->num_engines].engine.engine_instance = e;
371bf215546Sopenharmony_ci            }
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci            for (uint32_t e = 0; e < num_copy; e++, info->num_engines++) {
374bf215546Sopenharmony_ci               info->engines[info->num_engines].engine.engine_class =
375bf215546Sopenharmony_ci                  I915_ENGINE_CLASS_COPY;
376bf215546Sopenharmony_ci               info->engines[info->num_engines].engine.engine_instance = e;
377bf215546Sopenharmony_ci            }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci            assert(info->num_engines == num_engines);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci            if (item->length > data_length)
382bf215546Sopenharmony_ci               item->length = data_length;
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci            return 0;
385bf215546Sopenharmony_ci         }
386bf215546Sopenharmony_ci      }
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci      case DRM_I915_QUERY_PERF_CONFIG:
389bf215546Sopenharmony_ci         /* This is known but not supported by the shim.  Handling this here
390bf215546Sopenharmony_ci          * suppresses some spurious warning messages in shader-db runs.
391bf215546Sopenharmony_ci          */
392bf215546Sopenharmony_ci         item->length = -EINVAL;
393bf215546Sopenharmony_ci         break;
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci      case DRM_I915_QUERY_MEMORY_REGIONS: {
396bf215546Sopenharmony_ci         uint32_t num_regions = i915.devinfo.has_local_mem ? 2 : 1;
397bf215546Sopenharmony_ci         struct drm_i915_query_memory_regions *info =
398bf215546Sopenharmony_ci            (struct drm_i915_query_memory_regions*)(uintptr_t)item->data_ptr;
399bf215546Sopenharmony_ci         size_t data_length = sizeof(struct drm_i915_query_memory_regions) +
400bf215546Sopenharmony_ci            num_regions * sizeof(struct drm_i915_memory_region_info);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci         if (item->length == 0) {
403bf215546Sopenharmony_ci            item->length = data_length;
404bf215546Sopenharmony_ci            return 0;
405bf215546Sopenharmony_ci         } else if (item->length < (int32_t)data_length) {
406bf215546Sopenharmony_ci            item->length = -EINVAL;
407bf215546Sopenharmony_ci            return -1;
408bf215546Sopenharmony_ci         } else {
409bf215546Sopenharmony_ci            memset(info, 0, data_length);
410bf215546Sopenharmony_ci            info->num_regions = num_regions;
411bf215546Sopenharmony_ci            info->regions[0].region.memory_class = I915_MEMORY_CLASS_SYSTEM;
412bf215546Sopenharmony_ci            info->regions[0].region.memory_instance = 0;
413bf215546Sopenharmony_ci            /* Report 4Gb even if it's not actually true, it looks more like a
414bf215546Sopenharmony_ci             * real device.
415bf215546Sopenharmony_ci             */
416bf215546Sopenharmony_ci            info->regions[0].probed_size = 4ull * 1024 * 1024 * 1024;
417bf215546Sopenharmony_ci            info->regions[0].unallocated_size = -1ll;
418bf215546Sopenharmony_ci            if (i915.devinfo.has_local_mem) {
419bf215546Sopenharmony_ci               info->regions[1].region.memory_class = I915_MEMORY_CLASS_DEVICE;
420bf215546Sopenharmony_ci               info->regions[1].region.memory_instance = 0;
421bf215546Sopenharmony_ci               info->regions[1].probed_size = 4ull * 1024 * 1024 * 1024;
422bf215546Sopenharmony_ci               info->regions[1].unallocated_size = -1ll;
423bf215546Sopenharmony_ci            }
424bf215546Sopenharmony_ci            return 0;
425bf215546Sopenharmony_ci         }
426bf215546Sopenharmony_ci         break;
427bf215546Sopenharmony_ci      }
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci      default:
430bf215546Sopenharmony_ci         fprintf(stderr, "Unknown drm_i915_query_item id=%lli\n", item->query_id);
431bf215546Sopenharmony_ci         item->length = -EINVAL;
432bf215546Sopenharmony_ci         break;
433bf215546Sopenharmony_ci      }
434bf215546Sopenharmony_ci   }
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   return 0;
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_cistatic int
440bf215546Sopenharmony_cii915_gem_get_aperture(int fd, unsigned long request, void *arg)
441bf215546Sopenharmony_ci{
442bf215546Sopenharmony_ci   struct drm_i915_gem_get_aperture *aperture = arg;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   if (i915.devinfo.ver >= 8 &&
445bf215546Sopenharmony_ci       i915.devinfo.platform != INTEL_PLATFORM_CHV) {
446bf215546Sopenharmony_ci      aperture->aper_size = 1ull << 48;
447bf215546Sopenharmony_ci      aperture->aper_available_size = 1ull << 48;
448bf215546Sopenharmony_ci   } else {
449bf215546Sopenharmony_ci      aperture->aper_size = 1ull << 31;
450bf215546Sopenharmony_ci      aperture->aper_size = 1ull << 31;
451bf215546Sopenharmony_ci   }
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci   return 0;
454bf215546Sopenharmony_ci}
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_cistatic ioctl_fn_t driver_ioctls[] = {
457bf215546Sopenharmony_ci   [DRM_I915_GETPARAM] = i915_ioctl_get_param,
458bf215546Sopenharmony_ci   [DRM_I915_QUERY] = i915_ioctl_query,
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci   [DRM_I915_GET_RESET_STATS] = i915_ioctl_noop,
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci   [DRM_I915_GEM_CREATE] = i915_ioctl_gem_create,
463bf215546Sopenharmony_ci   [DRM_I915_GEM_MMAP] = i915_ioctl_gem_mmap,
464bf215546Sopenharmony_ci   [DRM_I915_GEM_SET_TILING] = i915_ioctl_gem_set_tiling,
465bf215546Sopenharmony_ci   [DRM_I915_GEM_CONTEXT_CREATE] = i915_ioctl_gem_context_create,
466bf215546Sopenharmony_ci   [DRM_I915_GEM_CONTEXT_DESTROY] = i915_ioctl_noop,
467bf215546Sopenharmony_ci   [DRM_I915_GEM_CONTEXT_GETPARAM] = i915_ioctl_gem_context_getparam,
468bf215546Sopenharmony_ci   [DRM_I915_GEM_CONTEXT_SETPARAM] = i915_ioctl_noop,
469bf215546Sopenharmony_ci   [DRM_I915_GEM_EXECBUFFER2] = i915_ioctl_noop,
470bf215546Sopenharmony_ci   /* [DRM_I915_GEM_EXECBUFFER2_WR] = i915_ioctl_noop,
471bf215546Sopenharmony_ci       same value as DRM_I915_GEM_EXECBUFFER2. */
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci   [DRM_I915_GEM_USERPTR] = i915_ioctl_gem_userptr,
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci   [DRM_I915_GEM_GET_APERTURE] = i915_gem_get_aperture,
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   [DRM_I915_REG_READ] = i915_ioctl_noop,
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   [DRM_I915_GEM_SET_DOMAIN] = i915_ioctl_noop,
480bf215546Sopenharmony_ci   [DRM_I915_GEM_GET_CACHING] = i915_ioctl_noop,
481bf215546Sopenharmony_ci   [DRM_I915_GEM_SET_CACHING] = i915_ioctl_noop,
482bf215546Sopenharmony_ci   [DRM_I915_GEM_GET_TILING] = i915_ioctl_gem_get_tiling,
483bf215546Sopenharmony_ci   [DRM_I915_GEM_MADVISE] = i915_ioctl_noop,
484bf215546Sopenharmony_ci   [DRM_I915_GEM_WAIT] = i915_ioctl_noop,
485bf215546Sopenharmony_ci   [DRM_I915_GEM_BUSY] = i915_ioctl_noop,
486bf215546Sopenharmony_ci};
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_civoid
489bf215546Sopenharmony_cidrm_shim_driver_init(void)
490bf215546Sopenharmony_ci{
491bf215546Sopenharmony_ci   const char *user_platform = getenv("INTEL_STUB_GPU_PLATFORM");
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci   /* Use SKL if nothing is specified. */
494bf215546Sopenharmony_ci   i915.device_id = intel_device_name_to_pci_device_id(user_platform ?: "skl");
495bf215546Sopenharmony_ci   if (!intel_get_device_info_from_pci_id(i915.device_id, &i915.devinfo))
496bf215546Sopenharmony_ci      return;
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci   shim_device.bus_type = DRM_BUS_PCI;
499bf215546Sopenharmony_ci   shim_device.driver_name = "i915";
500bf215546Sopenharmony_ci   shim_device.driver_ioctls = driver_ioctls;
501bf215546Sopenharmony_ci   shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls);
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   char uevent_content[1024];
504bf215546Sopenharmony_ci   snprintf(uevent_content, sizeof(uevent_content),
505bf215546Sopenharmony_ci            "DRIVER=i915\n"
506bf215546Sopenharmony_ci            "PCI_CLASS=30000\n"
507bf215546Sopenharmony_ci            "PCI_ID=8086:%x\n"
508bf215546Sopenharmony_ci            "PCI_SUBSYS_ID=1028:075B\n"
509bf215546Sopenharmony_ci            "PCI_SLOT_NAME=0000:00:02.0\n"
510bf215546Sopenharmony_ci            "MODALIAS=pci:v00008086d00005916sv00001028sd0000075Bbc03sc00i00\n",
511bf215546Sopenharmony_ci            i915.device_id);
512bf215546Sopenharmony_ci   drm_shim_override_file(uevent_content,
513bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/uevent",
514bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
515bf215546Sopenharmony_ci   drm_shim_override_file("0x0\n",
516bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/revision",
517bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
518bf215546Sopenharmony_ci   char device_content[10];
519bf215546Sopenharmony_ci   snprintf(device_content, sizeof(device_content),
520bf215546Sopenharmony_ci            "0x%x\n", i915.device_id);
521bf215546Sopenharmony_ci   drm_shim_override_file("0x8086",
522bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/vendor",
523bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
524bf215546Sopenharmony_ci   drm_shim_override_file("0x8086",
525bf215546Sopenharmony_ci                          "/sys/devices/pci0000:00/0000:00:02.0/vendor");
526bf215546Sopenharmony_ci   drm_shim_override_file(device_content,
527bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/device",
528bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
529bf215546Sopenharmony_ci   drm_shim_override_file(device_content,
530bf215546Sopenharmony_ci                          "/sys/devices/pci0000:00/0000:00:02.0/device");
531bf215546Sopenharmony_ci   drm_shim_override_file("0x1234",
532bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/subsystem_vendor",
533bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
534bf215546Sopenharmony_ci   drm_shim_override_file("0x1234",
535bf215546Sopenharmony_ci                          "/sys/devices/pci0000:00/0000:00:02.0/subsystem_vendor");
536bf215546Sopenharmony_ci   drm_shim_override_file("0x1234",
537bf215546Sopenharmony_ci                          "/sys/dev/char/%d:%d/device/subsystem_device",
538bf215546Sopenharmony_ci                          DRM_MAJOR, render_node_minor);
539bf215546Sopenharmony_ci   drm_shim_override_file("0x1234",
540bf215546Sopenharmony_ci                          "/sys/devices/pci0000:00/0000:00:02.0/subsystem_device");
541bf215546Sopenharmony_ci}
542