diff options
-rw-r--r-- | src/meson.build | 3 | ||||
-rw-r--r-- | src/nouveau/drm-shim/README.md | 28 | ||||
-rw-r--r-- | src/nouveau/drm-shim/meson.build | 29 | ||||
-rw-r--r-- | src/nouveau/drm-shim/nouveau_noop.c | 255 | ||||
-rw-r--r-- | src/nouveau/meson.build | 23 |
5 files changed, 338 insertions, 0 deletions
diff --git a/src/meson.build b/src/meson.build index 38101edace6..84a990358a3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -95,6 +95,9 @@ endif if with_microsoft_clc or with_gallium_d3d12 or with_spirv_to_dxil subdir('microsoft') endif +if with_gallium_nouveau + subdir('nouveau') +endif subdir('mesa') subdir('loader') if with_platform_haiku diff --git a/src/nouveau/drm-shim/README.md b/src/nouveau/drm-shim/README.md new file mode 100644 index 00000000000..01d8ce76a63 --- /dev/null +++ b/src/nouveau/drm-shim/README.md @@ -0,0 +1,28 @@ +### nouveau_noop backend + +This implements the minimum of nouveau in order to make shader-db work. +The submit ioctl is stubbed out to not execute anything. + +Export `MESA_LOADER_DRIVER_OVERRIDE=nouveau +LD_PRELOAD=$prefix/lib/libnouveau_noop_drm_shim.so`. + +By default, GK110 is exposed. The chip can be selected with an environment +variable like `NOUVEAU_CHIPSET=f0`. Some chips of note with the appropriate +chipset ids: + +| ID | Chip Name | Sample Marketing Name | Comment | +| --- | --------- | --------------------- | ------- | +| 30 | NV30 | GeForce FX 5500 | DX9 | +| 40 | NV40 | GeForce 6800 | DX9c, better control flow | +| 50 | G80 | GeForce 8800 GTS | SM 1.0, 128 regs | +| 84 | G84 | GeForce 8600 GS | SM 1.1 | +| a0 | GT200 | GeForce GTX 280 | SM 1.2 + fp64 | +| a3 | GT215 | GeForce GT 240 | DX10.1 ops | +| c0 | GF100 | GeForce GTX 480 | SM 2.0, 64 regs | +| e4 | GK104 | GeForce GTX 680 | SM 3.0, 64 regs | +| f0 | GK110 | GeForce GTX 780 | SM 3.5, 256 regs | +| 117 | GM107 | GeForce GTX 750 | SM 5.0 | +| 124 | GM204 | GeForce GTX 980 | SM 5.2 | +| 134 | GP104 | GeForce GTX 1080 | SM 6.0 | +| 140 | GV100 | TITAN V | SM 7.0 | +| 162 | TU102 | GeForce RTX 2080 | SM 7.5 | diff --git a/src/nouveau/drm-shim/meson.build b/src/nouveau/drm-shim/meson.build new file mode 100644 index 00000000000..42d9bfbdc1b --- /dev/null +++ b/src/nouveau/drm-shim/meson.build @@ -0,0 +1,29 @@ +# Copyright © 2021 Ilia Mirkin +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +libnouveau_noop_drm_shim = shared_library( + ['nouveau_noop_drm_shim'], + 'nouveau_noop.c', + include_directories: [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux], + dependencies: dep_drm_shim, + gnu_symbol_visibility : 'hidden', + install : true, +) diff --git a/src/nouveau/drm-shim/nouveau_noop.c b/src/nouveau/drm-shim/nouveau_noop.c new file mode 100644 index 00000000000..a93563abc87 --- /dev/null +++ b/src/nouveau/drm-shim/nouveau_noop.c @@ -0,0 +1,255 @@ +/* + * Copyright © 2021 Ilia Mirkin + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <limits.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <nouveau_drm.h> +#include "drm-shim/drm_shim.h" +#include "util//u_math.h" + +bool drm_shim_driver_prefers_first_render_node = true; + +struct nouveau_device { + uint64_t next_offset; +}; + +static struct nouveau_device nouveau = { + .next_offset = 0x1000, +}; + +struct nouveau_shim_bo { + struct shim_bo base; + uint64_t offset; +}; + +static struct nouveau_shim_bo * +nouveau_shim_bo(struct shim_bo *bo) +{ + return (struct nouveau_shim_bo *)bo; +} + +struct nouveau_device_info { + uint32_t chip_id; +}; + +static struct nouveau_device_info device_info; + +static int +nouveau_ioctl_noop(int fd, unsigned long request, void *arg) +{ + return 0; +} + +static int +nouveau_ioctl_gem_new(int fd, unsigned long request, void *arg) +{ + struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); + struct drm_nouveau_gem_new *create = arg; + struct nouveau_shim_bo *bo = calloc(1, sizeof(*bo)); + + drm_shim_bo_init(&bo->base, create->info.size); + + assert(ULONG_MAX - nouveau.next_offset > create->info.size); + + create->info.handle = drm_shim_bo_get_handle(shim_fd, &bo->base); + create->info.map_handle = drm_shim_bo_get_mmap_offset(shim_fd, &bo->base); + + if (create->align != 0) + nouveau.next_offset = align64(nouveau.next_offset, create->align); + create->info.offset = nouveau.next_offset; + nouveau.next_offset += create->info.size; + + bo->offset = create->info.offset; + + drm_shim_bo_put(&bo->base); + + return 0; +} + +static int +nouveau_ioctl_gem_info(int fd, unsigned long request, void *arg) +{ + struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); + struct drm_nouveau_gem_info *info = arg; + struct nouveau_shim_bo *bo = + nouveau_shim_bo(drm_shim_bo_lookup(shim_fd, info->handle)); + info->map_handle = drm_shim_bo_get_mmap_offset(shim_fd, &bo->base); + info->offset = bo->offset; + info->size = bo->base.size; + + drm_shim_bo_put(&bo->base); + + return 0; +} + +static int +nouveau_ioctl_gem_pushbuf(int fd, unsigned long request, void *arg) +{ + struct drm_nouveau_gem_pushbuf *submit = arg; + submit->vram_available = 3ULL << 30; + submit->gart_available = 1ULL << 40; + return 0; +} + +static int +nouveau_ioctl_channel_alloc(int fd, unsigned long request, void *arg) +{ + struct shim_fd *shim_fd = drm_shim_fd_lookup(fd); + struct drm_nouveau_channel_alloc *alloc = arg; + if (device_info.chip_id == 0x50 || device_info.chip_id >= 0x80) + alloc->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART; + else + alloc->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; + + /* NOTE: this will get leaked since we don't handle the channel + * free. However only one channel is created per screen, so impact should + * be limited. */ + struct nouveau_shim_bo *notify = calloc(1, sizeof(*notify)); + drm_shim_bo_init(¬ify->base, 0x1000); + notify->offset = nouveau.next_offset; + nouveau.next_offset += 0x1000; + alloc->notifier_handle = drm_shim_bo_get_handle(shim_fd, ¬ify->base); + + drm_shim_bo_put(¬ify->base); + + return 0; +} + +static int +nouveau_ioctl_get_param(int fd, unsigned long request, void *arg) +{ + struct drm_nouveau_getparam *gp = arg; + + switch (gp->param) { + case NOUVEAU_GETPARAM_CHIPSET_ID: + gp->value = device_info.chip_id; + return 0; + case NOUVEAU_GETPARAM_PCI_VENDOR: + gp->value = 0x10de; + return 0; + case NOUVEAU_GETPARAM_PCI_DEVICE: + gp->value = 0x1004; + return 0; + case NOUVEAU_GETPARAM_BUS_TYPE: + gp->value = 2 /* NV_PCIE */; + return 0; + case NOUVEAU_GETPARAM_FB_SIZE: + gp->value = 3ULL << 30; + return 0; + case NOUVEAU_GETPARAM_AGP_SIZE: + gp->value = 1ULL << 40; + return 0; + case NOUVEAU_GETPARAM_PTIMER_TIME: + gp->value = 0; + return 0; + case NOUVEAU_GETPARAM_HAS_BO_USAGE: + gp->value = 1; + return 0; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + gp->value = 0x01000001; + return 0; + default: + fprintf(stderr, "Unknown DRM_IOCTL_NOUVEAU_GETPARAM %llu\n", + (long long unsigned)gp->param); + return -1; + } +} + +static ioctl_fn_t driver_ioctls[] = { + [DRM_NOUVEAU_GETPARAM] = nouveau_ioctl_get_param, + [DRM_NOUVEAU_CHANNEL_ALLOC] = nouveau_ioctl_channel_alloc, + [DRM_NOUVEAU_CHANNEL_FREE] = nouveau_ioctl_noop, + [DRM_NOUVEAU_GROBJ_ALLOC] = nouveau_ioctl_noop, + [DRM_NOUVEAU_NOTIFIEROBJ_ALLOC] = nouveau_ioctl_noop, + [DRM_NOUVEAU_GPUOBJ_FREE] = nouveau_ioctl_noop, + [DRM_NOUVEAU_GEM_NEW] = nouveau_ioctl_gem_new, + [DRM_NOUVEAU_GEM_PUSHBUF] = nouveau_ioctl_gem_pushbuf, + [DRM_NOUVEAU_GEM_CPU_PREP] = nouveau_ioctl_noop, + [DRM_NOUVEAU_GEM_INFO] = nouveau_ioctl_gem_info, +}; + +static void +nouveau_driver_get_device_info(void) +{ + const char *env = getenv("NOUVEAU_CHIPSET"); + + if (!env) { + device_info.chip_id = 0xf0; + return; + } + + device_info.chip_id = strtol(env, NULL, 16); +} + +void +drm_shim_driver_init(void) +{ + shim_device.bus_type = DRM_BUS_PCI; + shim_device.driver_name = "nouveau"; + shim_device.driver_ioctls = driver_ioctls; + shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls); + + shim_device.version_major = 1; + shim_device.version_minor = 0; + shim_device.version_patchlevel = 1; + + nouveau_driver_get_device_info(); + + /* nothing looks at the pci id, so fix it to a GTX 780 */ + static const char uevent_content[] = + "DRIVER=nouveau\n" + "PCI_CLASS=30000\n" + "PCI_ID=10de:1004\n" + "PCI_SUBSYS_ID=1028:075B\n" + "PCI_SLOT_NAME=0000:01:00.0\n" + "MODALIAS=pci:v000010ded00005916sv00001028sd0000075Bbc03sc00i00\n"; + drm_shim_override_file(uevent_content, + "/sys/dev/char/%d:%d/device/uevent", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x0\n", + "/sys/dev/char/%d:%d/device/revision", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x10de", + "/sys/dev/char/%d:%d/device/vendor", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x10de", + "/sys/devices/pci0000:00/0000:01:00.0/vendor"); + drm_shim_override_file("0x1004", + "/sys/dev/char/%d:%d/device/device", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x1004", + "/sys/devices/pci0000:00/0000:01:00.0/device"); + drm_shim_override_file("0x1234", + "/sys/dev/char/%d:%d/device/subsystem_vendor", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x1234", + "/sys/devices/pci0000:00/0000:01:00.0/subsystem_vendor"); + drm_shim_override_file("0x1234", + "/sys/dev/char/%d:%d/device/subsystem_device", + DRM_MAJOR, render_node_minor); + drm_shim_override_file("0x1234", + "/sys/devices/pci0000:00/0000:01:00.0/subsystem_device"); +} diff --git a/src/nouveau/meson.build b/src/nouveau/meson.build new file mode 100644 index 00000000000..0da4b76c6b2 --- /dev/null +++ b/src/nouveau/meson.build @@ -0,0 +1,23 @@ +# Copyright © 2021 Ilia Mirkin + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if with_tools.contains('drm-shim') + subdir('drm-shim') +endif |