Not a fully blown gemfs, just our very own tmpfs kernel mount. Doing so moves us away from the shmemfs shm_mnt, and gives us the much needed flexibility to do things like set our own mount options, namely huge= which should allow us to enable the use of transparent-huge-pages for our shmem backed objects. Signed-off-by: Matthew Auld <matthew.auld@xxxxxxxxx> Cc: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 13 +++ drivers/gpu/drm/i915/i915_gem.c | 30 ++++++- drivers/gpu/drm/i915/i915_gemfs.c | 105 +++++++++++++++++++++++ drivers/gpu/drm/i915/selftests/mock_gem_device.c | 12 ++- 5 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gemfs.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 16dccf550412..1a70af7d51ec 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -46,6 +46,7 @@ i915-y += i915_cmd_parser.o \ i915_gem_tiling.o \ i915_gem_timeline.o \ i915_gem_userptr.o \ + i915_gemfs.o \ i915_trace_points.o \ i915_vma.o \ intel_breadcrumbs.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d2a57493ac2e..ca3196e2566f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2227,6 +2227,9 @@ struct drm_i915_private { DECLARE_HASHTABLE(mm_structs, 7); struct mutex mm_lock; + /* Our tmpfs instance used for shmem backed objects */ + struct vfsmount *gemfs_mnt; + /* The hw wants to have a stable context identifier for the lifetime * of the context (for OA, PASID, faults, etc). This is limited * in execlists to 21 bits. @@ -4169,4 +4172,14 @@ static inline bool i915_gem_object_is_coherent(struct drm_i915_gem_object *obj) HAS_LLC(to_i915(obj->base.dev))); } +/* i915_gemfs.c */ +struct vfsmount *i915_gemfs_create(void); + +void i915_gemfs_destroy(struct vfsmount *gemfs_mnt); + +struct file *i915_gemfs_file_setup(struct vfsmount *gemfs_mnt, + const char *name, size_t size); + +int i915_gemfs_unlink(struct file *filp); + #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7ab47a84671f..30f9af590969 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4245,6 +4245,24 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .pwrite = i915_gem_object_pwrite_gtt, }; +static int i915_drm_gem_object_init(struct drm_device *dev, + struct drm_gem_object *obj, + size_t size) +{ + struct drm_i915_private *i915 = to_i915(dev); + struct file *filp; + + drm_gem_private_object_init(dev, obj, size); + + filp = i915_gemfs_file_setup(i915->gemfs_mnt, "i915 mm object", size); + if (IS_ERR(filp)) + return PTR_ERR(filp); + + obj->filp = filp; + + return 0; +} + struct drm_i915_gem_object * i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) { @@ -4268,7 +4286,7 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) if (obj == NULL) return ERR_PTR(-ENOMEM); - ret = drm_gem_object_init(&dev_priv->drm, &obj->base, size); + ret = i915_drm_gem_object_init(&dev_priv->drm, &obj->base, size); if (ret) goto fail; @@ -4383,6 +4401,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, drm_prime_gem_destroy(&obj->base, NULL); reservation_object_fini(&obj->__builtin_resv); + + if (obj->base.filp) + i915_gemfs_unlink(obj->base.filp); drm_gem_object_release(&obj->base); i915_gem_info_remove_obj(i915, obj->base.size); @@ -4843,6 +4864,10 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) { int err = -ENOMEM; + dev_priv->gemfs_mnt = i915_gemfs_create(); + if (IS_ERR(dev_priv->gemfs_mnt)) + return PTR_ERR(dev_priv->gemfs_mnt); + dev_priv->objects = KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN); if (!dev_priv->objects) goto err_out; @@ -4908,6 +4933,7 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) err_objects: kmem_cache_destroy(dev_priv->objects); err_out: + i915_gemfs_destroy(dev_priv->gemfs_mnt); return err; } @@ -4930,6 +4956,8 @@ void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) /* And ensure that our DESTROY_BY_RCU slabs are truly destroyed */ rcu_barrier(); + + i915_gemfs_destroy(dev_priv->gemfs_mnt); } int i915_gem_freeze(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_gemfs.c b/drivers/gpu/drm/i915/i915_gemfs.c new file mode 100644 index 000000000000..e1b2af1d9946 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gemfs.c @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 Intel Corporation + * + * 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 <linux/fs.h> +#include <linux/file.h> +#include <linux/mount.h> + +static const struct dentry_operations anon_ops = { + .d_dname = simple_dname +}; + +struct vfsmount *i915_gemfs_create(void) +{ + struct file_system_type *type; + struct vfsmount *gemfs_mnt; + + type = get_fs_type("tmpfs"); + if (!type) + return ERR_PTR(-EINVAL); + + gemfs_mnt = kern_mount(type); + + return gemfs_mnt; +} + +void i915_gemfs_destroy(struct vfsmount *gemfs_mnt) +{ + kern_unmount(gemfs_mnt); +} + +struct file *i915_gemfs_file_setup(struct vfsmount *gemfs_mnt, + const char *name, size_t size) +{ + struct super_block *sb = gemfs_mnt->mnt_sb; + struct inode *dir = d_inode(sb->s_root); + struct inode *inode; + struct path path; + struct qstr this; + struct file *res; + int ret; + + if (size < 0 || size > MAX_LFS_FILESIZE) + return ERR_PTR(-EINVAL); + + this.name = name; + this.len = strlen(name); + this.hash = 0; + + path.mnt = mntget(gemfs_mnt); + path.dentry = d_alloc_pseudo(sb, &this); + if (!path.dentry) { + res = ERR_PTR(-ENOMEM); + goto put_path; + } + d_set_d_op(path.dentry, &anon_ops); + + ret = dir->i_op->create(dir, path.dentry, S_IFREG | S_IRWXUGO, false); + if (ret) { + res = ERR_PTR(ret); + goto put_path; + } + + inode = d_inode(path.dentry); + inode->i_size = size; + + res = alloc_file(&path, FMODE_WRITE | FMODE_READ, inode->i_fop); + if (IS_ERR(res)) + goto unlink; + + return res; + +unlink: + dir->i_op->unlink(dir, path.dentry); +put_path: + path_put(&path); + return res; +} + +int i915_gemfs_unlink(struct file *filp) +{ + struct inode *dir = d_inode(filp->f_inode->i_sb->s_root); + + return dir->i_op->unlink(dir, filp->f_path.dentry); +} diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 627e2aa09766..7f038ea15ef5 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -80,6 +80,8 @@ static void mock_device_release(struct drm_device *dev) kmem_cache_destroy(i915->vmas); kmem_cache_destroy(i915->objects); + i915_gemfs_destroy(i915->gemfs_mnt); + drm_dev_fini(&i915->drm); put_device(&i915->drm.pdev->dev); } @@ -167,9 +169,15 @@ struct drm_i915_private *mock_gem_device(void) i915->gt.awake = true; + i915->gemfs_mnt = i915_gemfs_create(); + if (IS_ERR(i915->gemfs_mnt)) { + err = PTR_ERR(i915->gemfs_mnt); + goto err_wq; + } + i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN); if (!i915->objects) - goto err_wq; + goto err_gemfs; i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN); if (!i915->vmas) @@ -227,6 +235,8 @@ struct drm_i915_private *mock_gem_device(void) kmem_cache_destroy(i915->vmas); err_objects: kmem_cache_destroy(i915->objects); +err_gemfs: + i915_gemfs_destroy(i915->gemfs_mnt); err_wq: destroy_workqueue(i915->wq); put_device: -- 2.9.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx