2 * Copyright © 2020 Intel Corporation
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:
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
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
21 * DEALINGS IN THE SOFTWARE.
27 #include <sys/ioctl.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
32 #include <sys/resource.h>
35 #include "common/gen_gem.h"
36 #include "dev/gen_device_info.h"
37 #include "drm-uapi/i915_drm.h"
38 #include "drm-shim/drm_shim.h"
39 #include "util/macros.h"
43 struct gen_device_info devinfo
;
51 static struct i915_device i915
= {};
53 bool drm_shim_driver_prefers_first_render_node
= true;
56 i915_ioctl_noop(int fd
, unsigned long request
, void *arg
)
62 i915_ioctl_gem_create(int fd
, unsigned long request
, void *arg
)
64 struct shim_fd
*shim_fd
= drm_shim_fd_lookup(fd
);
65 struct drm_i915_gem_create
*create
= arg
;
66 struct i915_bo
*bo
= calloc(1, sizeof(*bo
));
68 drm_shim_bo_init(&bo
->base
, create
->size
);
70 create
->handle
= drm_shim_bo_get_handle(shim_fd
, &bo
->base
);
72 drm_shim_bo_put(&bo
->base
);
78 i915_ioctl_gem_mmap(int fd
, unsigned long request
, void *arg
)
80 struct shim_fd
*shim_fd
= drm_shim_fd_lookup(fd
);
81 struct drm_i915_gem_mmap
*mmap_arg
= arg
;
82 struct shim_bo
*bo
= drm_shim_bo_lookup(shim_fd
, mmap_arg
->handle
);
88 bo
->map
= drm_shim_mmap(shim_fd
, bo
->size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, -1, (uintptr_t)bo
);
90 mmap_arg
->addr_ptr
= (uint64_t) (bo
->map
+ mmap_arg
->offset
);
96 i915_ioctl_gem_context_create(int fd
, unsigned long request
, void *arg
)
98 struct drm_i915_gem_context_create
*create
= arg
;
100 create
->ctx_id
= 1; /* Just return a fake non zero ID. */
106 i915_ioctl_gem_context_getparam(int fd
, unsigned long request
, void *arg
)
108 struct drm_i915_gem_context_param
*param
= arg
;
110 if (param
->param
== I915_CONTEXT_PARAM_GTT_SIZE
) {
111 if (i915
.devinfo
.gen
>= 8 && !i915
.devinfo
.is_cherryview
)
112 param
->value
= 1ull << 48;
114 param
->value
= 1ull << 31;
123 i915_ioctl_get_param(int fd
, unsigned long request
, void *arg
)
125 drm_i915_getparam_t
*gp
= arg
;
128 case I915_PARAM_CHIPSET_ID
:
129 *gp
->value
= i915
.device_id
;
131 case I915_PARAM_REVISION
:
134 case I915_PARAM_CS_TIMESTAMP_FREQUENCY
:
135 *gp
->value
= i915
.devinfo
.timestamp_frequency
;
137 case I915_PARAM_HAS_ALIASING_PPGTT
:
138 if (i915
.devinfo
.gen
< 6)
139 *gp
->value
= I915_GEM_PPGTT_NONE
;
140 else if (i915
.devinfo
.gen
<= 7)
141 *gp
->value
= I915_GEM_PPGTT_ALIASING
;
143 *gp
->value
= I915_GEM_PPGTT_FULL
;
145 case I915_PARAM_HAS_WAIT_TIMEOUT
:
146 case I915_PARAM_HAS_EXECBUF2
:
147 case I915_PARAM_HAS_EXEC_SOFTPIN
:
148 case I915_PARAM_HAS_EXEC_CAPTURE
:
149 case I915_PARAM_HAS_EXEC_FENCE
:
150 case I915_PARAM_HAS_EXEC_FENCE_ARRAY
:
151 case I915_PARAM_HAS_CONTEXT_ISOLATION
:
152 case I915_PARAM_HAS_EXEC_ASYNC
:
153 case I915_PARAM_HAS_EXEC_NO_RELOC
:
154 case I915_PARAM_HAS_EXEC_BATCH_FIRST
:
157 case I915_PARAM_CMD_PARSER_VERSION
:
158 /* Most recent version in drivers/gpu/drm/i915/i915_cmd_parser.c */
161 case I915_PARAM_MMAP_VERSION
:
162 case I915_PARAM_MMAP_GTT_VERSION
:
165 case I915_PARAM_SUBSLICE_TOTAL
:
167 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++)
168 *gp
->value
+= i915
.devinfo
.num_subslices
[s
];
170 case I915_PARAM_EU_TOTAL
:
172 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++)
173 *gp
->value
+= i915
.devinfo
.num_subslices
[s
] * i915
.devinfo
.num_eu_per_subslice
;
175 case I915_PARAM_PERF_REVISION
:
182 fprintf(stderr
, "Unknown DRM_IOCTL_I915_GET_PARAM %d\n", gp
->param
);
187 query_write_topology(struct drm_i915_query_item
*item
)
189 struct drm_i915_query_topology_info
*info
=
190 (void *) (uintptr_t) item
->data_ptr
;
193 DIV_ROUND_UP(i915
.devinfo
.num_slices
, 8) +
194 i915
.devinfo
.num_slices
* DIV_ROUND_UP(i915
.devinfo
.num_subslices
[0], 8) +
195 i915
.devinfo
.num_slices
* i915
.devinfo
.num_subslices
[0] *
196 DIV_ROUND_UP(i915
.devinfo
.num_eu_per_subslice
, 8);
198 if (item
->length
== 0) {
199 item
->length
= length
;
203 if (item
->length
< length
) {
204 fprintf(stderr
, "size too small\n");
209 fprintf(stderr
, "invalid topology flags\n");
213 info
->max_slices
= i915
.devinfo
.num_slices
;
214 info
->max_subslices
= i915
.devinfo
.num_subslices
[0];
215 info
->max_eus_per_subslice
= i915
.devinfo
.num_eu_per_subslice
;
217 info
->subslice_offset
= DIV_ROUND_UP(i915
.devinfo
.num_slices
, 8);
218 info
->subslice_stride
= DIV_ROUND_UP(i915
.devinfo
.num_subslices
[0], 8);
219 info
->eu_offset
= info
->subslice_offset
+ info
->max_slices
* info
->subslice_stride
;
221 uint32_t slice_mask
= (1u << i915
.devinfo
.num_slices
) - 1;
222 for (uint32_t i
= 0; i
< info
->subslice_offset
; i
++)
223 info
->data
[i
] = (slice_mask
>> (8 * i
)) & 0xff;
225 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++) {
226 uint32_t subslice_mask
= (1u << i915
.devinfo
.num_subslices
[s
]) - 1;
227 for (uint32_t i
= 0; i
< info
->subslice_stride
; i
++) {
228 info
->data
[info
->subslice_offset
+ s
* info
->subslice_stride
+ i
] =
229 (subslice_mask
>> (8 * i
)) & 0xff;
233 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++) {
234 for (uint32_t ss
= 0; ss
< i915
.devinfo
.num_subslices
[s
]; ss
++) {
235 uint32_t eu_mask
= (1u << info
->max_eus_per_subslice
) - 1;
236 for (uint32_t i
= 0; i
< DIV_ROUND_UP(info
->max_eus_per_subslice
, 8); i
++) {
237 info
->data
[info
->eu_offset
+
238 (s
* info
->max_subslices
+ ss
) * DIV_ROUND_UP(info
->max_eus_per_subslice
, 8) + i
] =
239 (eu_mask
>> (8 * i
)) & 0xff;
248 i915_ioctl_query(int fd
, unsigned long request
, void *arg
)
250 struct drm_i915_query
*query
= arg
;
251 struct drm_i915_query_item
*items
= (void *) (uintptr_t) query
->items_ptr
;
254 fprintf(stderr
, "invalid query flags\n");
258 for (uint32_t i
= 0; i
< query
->num_items
; i
++) {
259 struct drm_i915_query_item
*item
= &items
[i
];
261 switch (item
->query_id
) {
262 case DRM_I915_QUERY_TOPOLOGY_INFO
: {
263 int ret
= query_write_topology(item
);
270 fprintf(stderr
, "Unknown drm_i915_query_item id=%lli\n", item
->query_id
);
271 item
->length
= -EINVAL
;
280 i915_gem_get_aperture(int fd
, unsigned long request
, void *arg
)
282 struct drm_i915_gem_get_aperture
*aperture
= arg
;
284 if (i915
.devinfo
.gen
>= 8 &&
285 !i915
.devinfo
.is_cherryview
) {
286 aperture
->aper_size
= 1ull << 48;
287 aperture
->aper_available_size
= 1ull << 48;
289 aperture
->aper_size
= 1ull << 31;
290 aperture
->aper_size
= 1ull << 31;
296 static ioctl_fn_t driver_ioctls
[] = {
297 [DRM_I915_GETPARAM
] = i915_ioctl_get_param
,
298 [DRM_I915_QUERY
] = i915_ioctl_query
,
300 [DRM_I915_GET_RESET_STATS
] = i915_ioctl_noop
,
302 [DRM_I915_GEM_CREATE
] = i915_ioctl_gem_create
,
303 [DRM_I915_GEM_MMAP
] = i915_ioctl_gem_mmap
,
304 [DRM_I915_GEM_SET_TILING
] = i915_ioctl_noop
,
305 [DRM_I915_GEM_CONTEXT_CREATE
] = i915_ioctl_gem_context_create
,
306 [DRM_I915_GEM_CONTEXT_DESTROY
] = i915_ioctl_noop
,
307 [DRM_I915_GEM_CONTEXT_GETPARAM
] = i915_ioctl_gem_context_getparam
,
308 [DRM_I915_GEM_CONTEXT_SETPARAM
] = i915_ioctl_noop
,
309 [DRM_I915_GEM_EXECBUFFER2
] = i915_ioctl_noop
,
310 [DRM_I915_GEM_EXECBUFFER2_WR
] = i915_ioctl_noop
,
312 [DRM_I915_GEM_GET_APERTURE
] = i915_gem_get_aperture
,
314 [DRM_I915_REG_READ
] = i915_ioctl_noop
,
316 [DRM_I915_GEM_SET_DOMAIN
] = i915_ioctl_noop
,
317 [DRM_I915_GEM_GET_CACHING
] = i915_ioctl_noop
,
318 [DRM_I915_GEM_SET_CACHING
] = i915_ioctl_noop
,
319 [DRM_I915_GEM_MADVISE
] = i915_ioctl_noop
,
320 [DRM_I915_GEM_WAIT
] = i915_ioctl_noop
,
321 [DRM_I915_GEM_BUSY
] = i915_ioctl_noop
,
325 drm_shim_driver_init(void)
327 const char *user_platform
= getenv("INTEL_STUB_GPU_PLATFORM");
329 /* Use SKL if nothing is specified. */
330 i915
.device_id
= gen_device_name_to_pci_device_id(user_platform
?: "skl");
331 if (!gen_get_device_info_from_pci_id(i915
.device_id
, &i915
.devinfo
))
334 shim_device
.bus_type
= DRM_BUS_PCI
;
335 shim_device
.driver_name
= "i915";
336 shim_device
.driver_ioctls
= driver_ioctls
;
337 shim_device
.driver_ioctl_count
= ARRAY_SIZE(driver_ioctls
);
339 char uevent_content
[1024];
340 snprintf(uevent_content
, sizeof(uevent_content
),
344 "PCI_SUBSYS_ID=1028:075B\n"
345 "PCI_SLOT_NAME=0000:00:02.0\n"
346 "MODALIAS=pci:v00008086d00005916sv00001028sd0000075Bbc03sc00i00\n",
348 drm_shim_override_file(uevent_content
,
349 "/sys/dev/char/%d:%d/device/uevent",
350 DRM_MAJOR
, render_node_minor
);
351 drm_shim_override_file("0x0\n",
352 "/sys/dev/char/%d:%d/device/revision",
353 DRM_MAJOR
, render_node_minor
);
354 char device_content
[10];
355 snprintf(device_content
, sizeof(device_content
),
356 "0x%x\n", i915
.device_id
);
357 drm_shim_override_file("0x8086",
358 "/sys/dev/char/%d:%d/device/vendor",
359 DRM_MAJOR
, render_node_minor
);
360 drm_shim_override_file("0x8086",
361 "/sys/devices/pci0000:00/0000:00:02.0/vendor");
362 drm_shim_override_file(device_content
,
363 "/sys/dev/char/%d:%d/device/device",
364 DRM_MAJOR
, render_node_minor
);
365 drm_shim_override_file(device_content
,
366 "/sys/devices/pci0000:00/0000:00:02.0/device");
367 drm_shim_override_file("0x1234",
368 "/sys/dev/char/%d:%d/device/subsystem_vendor",
369 DRM_MAJOR
, render_node_minor
);
370 drm_shim_override_file("0x1234",
371 "/sys/devices/pci0000:00/0000:00:02.0/subsystem_vendor");
372 drm_shim_override_file("0x1234",
373 "/sys/dev/char/%d:%d/device/subsystem_device",
374 DRM_MAJOR
, render_node_minor
);
375 drm_shim_override_file("0x1234",
376 "/sys/devices/pci0000:00/0000:00:02.0/subsystem_device");