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 *gp
->value
= i915
.devinfo
.is_haswell
|| i915
.devinfo
.gen
>= 8;
140 case I915_PARAM_HAS_WAIT_TIMEOUT
:
141 case I915_PARAM_HAS_EXECBUF2
:
142 case I915_PARAM_HAS_EXEC_SOFTPIN
:
143 case I915_PARAM_HAS_EXEC_CAPTURE
:
144 case I915_PARAM_HAS_EXEC_FENCE
:
145 case I915_PARAM_HAS_EXEC_FENCE_ARRAY
:
146 case I915_PARAM_HAS_CONTEXT_ISOLATION
:
147 case I915_PARAM_HAS_EXEC_ASYNC
:
148 case I915_PARAM_HAS_EXEC_NO_RELOC
:
149 case I915_PARAM_HAS_EXEC_BATCH_FIRST
:
152 case I915_PARAM_CMD_PARSER_VERSION
:
153 /* Most recent version in drivers/gpu/drm/i915/i915_cmd_parser.c */
156 case I915_PARAM_MMAP_VERSION
:
157 case I915_PARAM_MMAP_GTT_VERSION
:
160 case I915_PARAM_SUBSLICE_TOTAL
:
162 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++)
163 *gp
->value
+= i915
.devinfo
.num_subslices
[s
];
165 case I915_PARAM_EU_TOTAL
:
167 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++)
168 *gp
->value
+= i915
.devinfo
.num_subslices
[s
] * i915
.devinfo
.num_eu_per_subslice
;
170 case I915_PARAM_PERF_REVISION
:
177 fprintf(stderr
, "Unknown DRM_IOCTL_I915_GET_PARAM %d\n", gp
->param
);
182 query_write_topology(struct drm_i915_query_item
*item
)
184 struct drm_i915_query_topology_info
*info
=
185 (void *) (uintptr_t) item
->data_ptr
;
188 DIV_ROUND_UP(i915
.devinfo
.num_slices
, 8) +
189 i915
.devinfo
.num_slices
* DIV_ROUND_UP(i915
.devinfo
.num_subslices
[0], 8) +
190 i915
.devinfo
.num_slices
* i915
.devinfo
.num_subslices
[0] *
191 DIV_ROUND_UP(i915
.devinfo
.num_eu_per_subslice
, 8);
193 if (item
->length
== 0) {
194 item
->length
= length
;
198 if (item
->length
< length
) {
199 fprintf(stderr
, "size too small\n");
204 fprintf(stderr
, "invalid topology flags\n");
208 info
->max_slices
= i915
.devinfo
.num_slices
;
209 info
->max_subslices
= i915
.devinfo
.num_subslices
[0];
210 info
->max_eus_per_subslice
= i915
.devinfo
.num_eu_per_subslice
;
212 info
->subslice_offset
= DIV_ROUND_UP(i915
.devinfo
.num_slices
, 8);
213 info
->subslice_stride
= DIV_ROUND_UP(i915
.devinfo
.num_subslices
[0], 8);
214 info
->eu_offset
= info
->subslice_offset
+ info
->max_slices
* info
->subslice_stride
;
216 uint32_t slice_mask
= (1u << i915
.devinfo
.num_slices
) - 1;
217 for (uint32_t i
= 0; i
< info
->subslice_offset
; i
++)
218 info
->data
[i
] = (slice_mask
>> (8 * i
)) & 0xff;
220 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++) {
221 uint32_t subslice_mask
= (1u << i915
.devinfo
.num_subslices
[s
]) - 1;
222 for (uint32_t i
= 0; i
< info
->subslice_stride
; i
++) {
223 info
->data
[info
->subslice_offset
+ s
* info
->subslice_stride
+ i
] =
224 (subslice_mask
>> (8 * i
)) & 0xff;
228 for (uint32_t s
= 0; s
< i915
.devinfo
.num_slices
; s
++) {
229 for (uint32_t ss
= 0; ss
< i915
.devinfo
.num_subslices
[s
]; ss
++) {
230 uint32_t eu_mask
= (1u << info
->max_eus_per_subslice
) - 1;
231 for (uint32_t i
= 0; i
< DIV_ROUND_UP(info
->max_eus_per_subslice
, 8); i
++) {
232 info
->data
[info
->eu_offset
+
233 (s
* info
->max_subslices
+ ss
) * DIV_ROUND_UP(info
->max_eus_per_subslice
, 8) + i
] =
234 (eu_mask
>> (8 * i
)) & 0xff;
243 i915_ioctl_query(int fd
, unsigned long request
, void *arg
)
245 struct drm_i915_query
*query
= arg
;
246 struct drm_i915_query_item
*items
= (void *) (uintptr_t) query
->items_ptr
;
249 fprintf(stderr
, "invalid query flags\n");
253 for (uint32_t i
= 0; i
< query
->num_items
; i
++) {
254 struct drm_i915_query_item
*item
= &items
[i
];
256 switch (item
->query_id
) {
257 case DRM_I915_QUERY_TOPOLOGY_INFO
: {
258 int ret
= query_write_topology(item
);
265 fprintf(stderr
, "Unknown drm_i915_query_item id=%lli\n", item
->query_id
);
266 item
->length
= -EINVAL
;
275 i915_gem_get_aperture(int fd
, unsigned long request
, void *arg
)
277 struct drm_i915_gem_get_aperture
*aperture
= arg
;
279 if (i915
.devinfo
.gen
>= 8 &&
280 !i915
.devinfo
.is_cherryview
) {
281 aperture
->aper_size
= 1ull << 48;
282 aperture
->aper_available_size
= 1ull << 48;
284 aperture
->aper_size
= 1ull << 31;
285 aperture
->aper_size
= 1ull << 31;
291 static ioctl_fn_t driver_ioctls
[] = {
292 [DRM_I915_GETPARAM
] = i915_ioctl_get_param
,
293 [DRM_I915_QUERY
] = i915_ioctl_query
,
295 [DRM_I915_GET_RESET_STATS
] = i915_ioctl_noop
,
297 [DRM_I915_GEM_CREATE
] = i915_ioctl_gem_create
,
298 [DRM_I915_GEM_MMAP
] = i915_ioctl_gem_mmap
,
299 [DRM_I915_GEM_CONTEXT_CREATE
] = i915_ioctl_gem_context_create
,
300 [DRM_I915_GEM_CONTEXT_DESTROY
] = i915_ioctl_noop
,
301 [DRM_I915_GEM_CONTEXT_GETPARAM
] = i915_ioctl_gem_context_getparam
,
302 [DRM_I915_GEM_CONTEXT_SETPARAM
] = i915_ioctl_noop
,
303 [DRM_I915_GEM_EXECBUFFER2
] = i915_ioctl_noop
,
304 [DRM_I915_GEM_EXECBUFFER2_WR
] = i915_ioctl_noop
,
306 [DRM_I915_GEM_GET_APERTURE
] = i915_gem_get_aperture
,
308 [DRM_I915_REG_READ
] = i915_ioctl_noop
,
310 [DRM_I915_GEM_SET_DOMAIN
] = i915_ioctl_noop
,
311 [DRM_I915_GEM_GET_CACHING
] = i915_ioctl_noop
,
312 [DRM_I915_GEM_SET_CACHING
] = i915_ioctl_noop
,
313 [DRM_I915_GEM_MADVISE
] = i915_ioctl_noop
,
314 [DRM_I915_GEM_WAIT
] = i915_ioctl_noop
,
315 [DRM_I915_GEM_BUSY
] = i915_ioctl_noop
,
319 drm_shim_driver_init(void)
321 const char *user_platform
= getenv("INTEL_STUB_GPU_PLATFORM");
323 /* Use SKL if nothing is specified. */
324 i915
.device_id
= gen_device_name_to_pci_device_id(user_platform
?: "skl");
325 if (!gen_get_device_info_from_pci_id(i915
.device_id
, &i915
.devinfo
))
328 shim_device
.bus_type
= DRM_BUS_PCI
;
329 shim_device
.driver_name
= "i915";
330 shim_device
.driver_ioctls
= driver_ioctls
;
331 shim_device
.driver_ioctl_count
= ARRAY_SIZE(driver_ioctls
);
333 char uevent_content
[1024];
334 snprintf(uevent_content
, sizeof(uevent_content
),
338 "PCI_SUBSYS_ID=1028:075B\n"
339 "PCI_SLOT_NAME=0000:00:02.0\n"
340 "MODALIAS=pci:v00008086d00005916sv00001028sd0000075Bbc03sc00i00\n",
342 drm_shim_override_file(uevent_content
,
343 "/sys/dev/char/%d:%d/device/uevent",
344 DRM_MAJOR
, render_node_minor
);
345 drm_shim_override_file("0x0\n",
346 "/sys/dev/char/%d:%d/device/revision",
347 DRM_MAJOR
, render_node_minor
);
348 char device_content
[10];
349 snprintf(device_content
, sizeof(device_content
),
350 "0x%x\n", i915
.device_id
);
351 drm_shim_override_file("0x8086",
352 "/sys/dev/char/%d:%d/device/vendor",
353 DRM_MAJOR
, render_node_minor
);
354 drm_shim_override_file("0x8086",
355 "/sys/devices/pci0000:00/0000:00:02.0/vendor");
356 drm_shim_override_file(device_content
,
357 "/sys/dev/char/%d:%d/device/device",
358 DRM_MAJOR
, render_node_minor
);
359 drm_shim_override_file(device_content
,
360 "/sys/devices/pci0000:00/0000:00:02.0/device");
361 drm_shim_override_file("0x1234",
362 "/sys/dev/char/%d:%d/device/subsystem_vendor",
363 DRM_MAJOR
, render_node_minor
);
364 drm_shim_override_file("0x1234",
365 "/sys/devices/pci0000:00/0000:00:02.0/subsystem_vendor");
366 drm_shim_override_file("0x1234",
367 "/sys/dev/char/%d:%d/device/subsystem_device",
368 DRM_MAJOR
, render_node_minor
);
369 drm_shim_override_file("0x1234",
370 "/sys/devices/pci0000:00/0000:00:02.0/subsystem_device");