Skip to contentSkip to conversation

huge gtt pages

PATCH In review Matthew Auld 5 participants 34 messages Sep 25, 2017 – Sep 27, 2017

Subsystems (7)
lore
Share & tools
lore

Matthew Auld

author reviewer
#0 lore raw

cover huge gtt pages

Some minor bits of polish, with the bulk of the changes being the mm/shmem patches.

Matthew Auld (22):
mm/shmem: support passing mnt to shmem_file_setup drm/i915: introduce simple gemfs
mm/shmem: parse mount options for MS_KERNMOUNT drm/i915/gemfs: enable THP
drm/i915: introduce page_sizes field to dev_info drm/i915: push set_pages down to the callers drm/i915: introduce page_size members
drm/i915: introduce vm set_pages/clear_pages drm/i915: align the vma start to the largest gtt page size drm/i915: align 64K objects to 2M
drm/i915: enable IPS bit for 64K pages
drm/i915: disable GTT cache for 2M pages drm/i915: support 2M pages for the 48b PPGTT drm/i915: add support for 64K scratch page drm/i915: support 64K pages for the 48b PPGTT drm/i915: accurate page size tracking for the ppgtt drm/i915/debugfs: include some gtt page size metrics drm/i915/selftests: huge page tests drm/i915/selftests: mix huge pages
drm/i915: disable platform support for vGPU huge gtt pages drm/i915: enable platform support for 64K pages drm/i915: enable platform support for 2M pages

 drivers/gpu/drm/drm_gem.c                          |    2 +-
 drivers/gpu/drm/i915/Makefile                      |    1 +
 drivers/gpu/drm/i915/i915_debugfs.c                |   61 +-
 drivers/gpu/drm/i915/i915_drv.h                    |   11 +-
 drivers/gpu/drm/i915/i915_gem.c                    |  136 +-
 drivers/gpu/drm/i915/i915_gem_dmabuf.c             |   22 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c                |  260 ++-
 drivers/gpu/drm/i915/i915_gem_gtt.h                |   19 +-
 drivers/gpu/drm/i915/i915_gem_internal.c           |   18 +-
 drivers/gpu/drm/i915/i915_gem_object.h             |   31 +-
 drivers/gpu/drm/i915/i915_gem_stolen.c             |   16 +-
 drivers/gpu/drm/i915/i915_gem_userptr.c            |   19 +-
 drivers/gpu/drm/i915/i915_gemfs.c                  |   58 +
 drivers/gpu/drm/i915/i915_gemfs.h                  |   34 +
 drivers/gpu/drm/i915/i915_pci.c                    |   23 +
 drivers/gpu/drm/i915/i915_reg.h                    |    3 +
 drivers/gpu/drm/i915/i915_vma.c                    |   49 +-
 drivers/gpu/drm/i915/i915_vma.h                    |    1 +
 drivers/gpu/drm/i915/intel_pm.c                    |    8 +-
 drivers/gpu/drm/i915/selftests/huge_gem_object.c   |   14 +-
 drivers/gpu/drm/i915/selftests/huge_pages.c        | 1687 ++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c      |   15 +-
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |    1 +
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |    1 +
 drivers/gpu/drm/i915/selftests/mock_gem_device.c   |    9 +
 drivers/gpu/drm/i915/selftests/mock_gtt.c          |   11 +-
 drivers/gpu/drm/i915/selftests/scatterlist.c       |   15 +
 drivers/gpu/drm/ttm/ttm_tt.c                       |    2 +-
 drivers/staging/android/ashmem.c                   |    3 +-
 include/linux/shmem_fs.h                           |    4 +-
 mm/shmem.c                                         |   34 +-
 31 files changed, 2424 insertions(+), 144 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915_gemfs.c
 create mode 100644 drivers/gpu/drm/i915/i915_gemfs.h
 create mode 100644 drivers/gpu/drm/i915/selftests/huge_pages.c
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#1 lore raw

PATCH 1/22 mm/shmem: support passing mnt to shmem_file_setup

We are planning to use our own tmpfs mnt in i915 in place of the shm_mnt such that we can control the mount options, in particular huge=, which we require to support huge-gtt-pages. So rather than roll our own version of __shmem_file_setup, it would be preferred if we could just give shmem our mnt, and let it do the rest.

Based on the patch: https://patchwork.freedesktop.org/patch/178433/

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Arve Hjønnevåg" <[email protected]>
Cc Riley Andrews <[email protected]>
---
 drivers/gpu/drm/drm_gem.c        |  2 +-
 drivers/gpu/drm/ttm/ttm_tt.c     |  2 +-
 drivers/staging/android/ashmem.c |  3 ++-
 include/linux/shmem_fs.h         |  4 +++-
 mm/shmem.c                       | 24 ++++++++++++++----------
 5 files changed, 21 insertions(+), 14 deletions(-)
drivers/gpu/drm/drm_gem.c +1 -1
index 7199bba68c37..12e5fdc90a6f 100644
@@ -138,7 +138,7 @@ int drm_gem_object_init(struct drm_device *dev,
 
 	drm_gem_private_object_init(dev, obj, size);
 
-	filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
+	filp = shmem_file_setup(TMPFS_MNT, "drm mm object", size, VM_NORESERVE);
 	if (IS_ERR(filp))
 		return PTR_ERR(filp);
 
drivers/gpu/drm/ttm/ttm_tt.c +1 -1
index 8ebc8d3560c3..4eef07d8b8ed 100644
@@ -336,7 +336,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 	BUG_ON(ttm->caching_state != tt_cached);
 
 	if (!persistent_swap_storage) {
-		swap_storage = shmem_file_setup("ttm swap",
+		swap_storage = shmem_file_setup(TMPFS_MNT, "ttm swap",
 						ttm->num_pages << PAGE_SHIFT,
 						0);
 		if (IS_ERR(swap_storage)) {
drivers/staging/android/ashmem.c +2 -1
index 0f695df14c9d..184fcbb6d127 100644
@@ -391,7 +391,8 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 			name = asma->name;
 
 		/* ... and allocate the backing shmem file */
-		vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
+		vmfile = shmem_file_setup(TMPFS_MNT, name, asma->size,
+					  vma->vm_flags);
 		if (IS_ERR(vmfile)) {
 			ret = PTR_ERR(vmfile);
 			goto out;
include/linux/shmem_fs.h +3 -1
index b6c3540e07bc..00b199d804ca 100644
@@ -44,12 +44,14 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
 	return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#define TMPFS_MNT NULL
+
 /*
  * Functions in mm/shmem.c called directly from elsewhere:
  */
 extern int shmem_init(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
-extern struct file *shmem_file_setup(const char *name,
+extern struct file *shmem_file_setup(struct vfsmount *mnt, const char *name,
 					loff_t size, unsigned long flags);
 extern struct file *shmem_kernel_file_setup(const char *name, loff_t size,
 					    unsigned long flags);
mm/shmem.c +14 -10
index 07a1d22807be..ae2e46291ffa 100644
@@ -3715,7 +3715,7 @@ SYSCALL_DEFINE2(memfd_create,
 					(flags >> MFD_HUGE_SHIFT) &
 					MFD_HUGE_MASK);
 	} else
-		file = shmem_file_setup(name, 0, VM_NORESERVE);
+		file = shmem_file_setup(TMPFS_MNT, name, 0, VM_NORESERVE);
 	if (IS_ERR(file)) {
 		error = PTR_ERR(file);
 		goto err_fd;
@@ -4183,7 +4183,7 @@ static const struct dentry_operations anon_ops = {
 	.d_dname = simple_dname
 };
 
-static struct file *__shmem_file_setup(const char *name, loff_t size,
+static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size,
 				       unsigned long flags, unsigned int i_flags)
 {
 	struct file *res;
@@ -4192,8 +4192,11 @@ static struct file *__shmem_file_setup(const char *name, loff_t size,
 	struct super_block *sb;
 	struct qstr this;
 
-	if (IS_ERR(shm_mnt))
-		return ERR_CAST(shm_mnt);
+	if (mnt == TMPFS_MNT)
+		mnt = shm_mnt;
+
+	if (IS_ERR(mnt))
+		return ERR_CAST(mnt);
 
 	if (size < 0 || size > MAX_LFS_FILESIZE)
 		return ERR_PTR(-EINVAL);
@@ -4205,8 +4208,8 @@ static struct file *__shmem_file_setup(const char *name, loff_t size,
 	this.name = name;
 	this.len = strlen(name);
 	this.hash = 0; /* will go */
-	sb = shm_mnt->mnt_sb;
-	path.mnt = mntget(shm_mnt);
+	sb = mnt->mnt_sb;
+	path.mnt = mntget(mnt);
 	path.dentry = d_alloc_pseudo(sb, &this);
 	if (!path.dentry)
 		goto put_memory;
@@ -4251,18 +4254,19 @@ static struct file *__shmem_file_setup(const char *name, loff_t size,
  */
 struct file *shmem_kernel_file_setup(const char *name, loff_t size, unsigned long flags)
 {
-	return __shmem_file_setup(name, size, flags, S_PRIVATE);
+	return __shmem_file_setup(TMPFS_MNT, name, size, flags, S_PRIVATE);
 }
 
 /**
  * shmem_file_setup - get an unlinked file living in tmpfs
+ * @mnt: the tmpfs mount where the file will be created
  * @name: name for dentry (to be seen in /proc/<pid>/maps
  * @size: size to be set for the file
  * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
  */
-struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
+struct file *shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size, unsigned long flags)
 {
-	return __shmem_file_setup(name, size, flags, 0);
+	return __shmem_file_setup(mnt, name, size, flags, 0);
 }
 EXPORT_SYMBOL_GPL(shmem_file_setup);
 
@@ -4281,7 +4285,7 @@ int shmem_zero_setup(struct vm_area_struct *vma)
 	 * accessible to the user through its mapping, use S_PRIVATE flag to
 	 * bypass file security, in the same way as shmem_kernel_file_setup().
 	 */
-	file = __shmem_file_setup("dev/zero", size, vma->vm_flags, S_PRIVATE);
+	file = shmem_kernel_file_setup("dev/zero", size, vma->vm_flags);
 	if (IS_ERR(file))
 		return PTR_ERR(file);
 
Signature · 7 lines
2.13.5

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Reviewed-by on v1 1/22
#2 lore raw

Re: [PATCH 01/22] mm/shmem: support passing mnt to shmem_file_setup

Quoting Matthew Auld (2017-09-25 19:47:16)

Quoted 8 lines

We are planning to use our own tmpfs mnt in i915 in place of the shm_mnt such that we can control the mount options, in particular huge=, which we require to support huge-gtt-pages. So rather than roll our own version of __shmem_file_setup, it would be preferred if we could just give shmem our mnt, and let it do the rest.

Based on the patch: https://patchwork.freedesktop.org/patch/178433/

Quoted 15 lines
Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Arve Hjønnevåg" <[email protected]>
Cc Riley Andrews <[email protected]>

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author reviewer
#3 lore raw

PATCH 2/22 drm/i915: introduce simple gemfs

In reply to Matthew Auld

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.

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Arve Hjønnevåg" <[email protected]>
Cc Riley Andrews <[email protected]>
---
 drivers/gpu/drm/i915/Makefile                    |  1 +
 drivers/gpu/drm/i915/i915_drv.h                  |  5 +++
 drivers/gpu/drm/i915/i915_gem.c                  | 26 +++++++++++-
 drivers/gpu/drm/i915/i915_gemfs.c                | 52 ++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gemfs.h                | 34 ++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_gem_device.c |  4 ++
 6 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/i915_gemfs.c
 create mode 100644 drivers/gpu/drm/i915/i915_gemfs.h
drivers/gpu/drm/i915/Makefile +1 -0
index 5182e3d5557d..980c41568f46 100644
@@ -47,6 +47,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 \
drivers/gpu/drm/i915/i915_drv.h +5 -0
index 61a4be9c2d37..d2079c863a9f 100644
@@ -1501,6 +1501,11 @@ struct i915_gem_mm {
 	/** Usable portion of the GTT for GEM */
 	dma_addr_t stolen_base; /* limited to low memory (32-bit) */
 
+	/**
+	 * tmpfs instance used for shmem backed objects
+	 */
+	struct vfsmount *gemfs;
+
 	/** PPGTT used for aliasing the PPGTT with the GTT */
 	struct i915_hw_ppgtt *aliasing_ppgtt;
 
drivers/gpu/drm/i915/i915_gem.c +25 -1
index 73eeb6b1f1cd..26a3ad2668d7 100644
@@ -35,6 +35,7 @@
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
 #include "intel_mocs.h"
+#include "i915_gemfs.h"
 #include <linux/dma-fence-array.h>
 #include <linux/kthread.h>
 #include <linux/reservation.h>
@@ -4251,6 +4252,24 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
 	.pwrite = i915_gem_object_pwrite_gtt,
 };
 
+static int i915_gem_object_create_shmem(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 = shmem_file_setup(i915->mm.gemfs, "i915", size, VM_NORESERVE);
+	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)
 {
@@ -4275,7 +4294,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_gem_object_create_shmem(&dev_priv->drm, &obj->base, size);
 	if (ret)
 		goto fail;
 
@@ -4914,6 +4933,9 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
 
 	spin_lock_init(&dev_priv->fb_tracking.lock);
 
+	if (i915_gemfs_init(dev_priv))
+		DRM_NOTE("Unable to create a private tmpfs mountpoint, hugepage support will be disabled.\n");
+
 	return 0;
 
 err_priorities:
@@ -4952,6 +4974,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_fini(dev_priv);
 }
 
 int i915_gem_freeze(struct drm_i915_private *dev_priv)
drivers/gpu/drm/i915/i915_gemfs.c new file +52 -0

52 lines not on this page · raw message

drivers/gpu/drm/i915/i915_gemfs.h new file +34 -0
new file mode 100644
index 000000000000..cca8bdc5b93e
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __I915_GEMFS_H__
+#define __I915_GEMFS_H__
+
+struct drm_i915_private;
+
+int i915_gemfs_init(struct drm_i915_private *i915);
+
+void i915_gemfs_fini(struct drm_i915_private *i915);
+
+#endif
drivers/gpu/drm/i915/selftests/mock_gem_device.c +4 -0
index 2388424a14da..ed3407b078e7 100644
@@ -83,6 +83,8 @@ static void mock_device_release(struct drm_device *dev)
 	kmem_cache_destroy(i915->vmas);
 	kmem_cache_destroy(i915->objects);
 
+	i915_gemfs_fini(i915);
+
 	drm_dev_fini(&i915->drm);
 	put_device(&i915->drm.pdev->dev);
 }
@@ -239,6 +241,8 @@ struct drm_i915_private *mock_gem_device(void)
 	if (!i915->kernel_context)
 		goto err_engine;
 
+	WARN_ON(i915_gemfs_init(i915));
+
 	return i915;
 
 err_engine:
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v1 2/22
#4 lore raw

Re: [PATCH 02/22] drm/i915: introduce simple gemfs

Quoting Matthew Auld (2017-09-25 19:47:17)

Quoted 15 lines

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.

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Quoted 14 lines
Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc "Arve Hjønnevåg" <[email protected]>
Cc Riley Andrews <[email protected]>

-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#5 lore raw

Re: [PATCH 02/22] drm/i915: introduce simple gemfs

In reply to Matthew Auld
Quoted 6 lines · Matthew Auld

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.

Quoted 8 lines

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Why do this only for one specific driver? Shouldn't the drm core handle this for you, for all other drivers as well? Otherwise trying to figure out how to "contain" this type of thing is going to be a pain (mount options, selinux options, etc.)

thanks,

greg k-h

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#6 lore raw

Re: [PATCH 02/22] drm/i915: introduce simple gemfs

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Matthew Auld

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.

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

Quoted 8 lines
Quoted 3 lines

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Why do this only for one specific driver? Shouldn't the drm core handle this for you, for all other drivers as well? Otherwise trying to figure out how to "contain" this type of thing is going to be a pain (mount options, selinux options, etc.)

We actually started quite grande by making stripped down version of shmemfs for drm core, but kept running into nacks about how we were implementing it (after getting a recommendation to try implementing it some way). After a few iterations and massive engineering time, we have been progressively reducing the amount of changes outside i915 in the hopes to get this merged.

And all the while clock is ticking, so we thought the best way to get something to support our future work is to implement this first locally with minimal external changes outside i915 and then once we have something working, it'll be easier to generalize it for the drm core. Otherwise we'll never get to work with the huge page support, for which gemfs is the stepping stone here.

So we're not planning on sitting on top of it, we'll just incubate it under i915/ so that it'll then be less pain for others to adopt when the biggest hurdles with core MM interactions are sorted out.

Regards, Joonas

Signature · 7 lines
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#7 lore raw

Re: [PATCH 02/22] drm/i915: introduce simple gemfs

Quoted 36 lines · Joonas Lahtinen
Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Matthew Auld

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.

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

Quoted 8 lines
Quoted 3 lines

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Why do this only for one specific driver? Shouldn't the drm core handle this for you, for all other drivers as well? Otherwise trying to figure out how to "contain" this type of thing is going to be a pain (mount options, selinux options, etc.)

We actually started quite grande by making stripped down version of shmemfs for drm core, but kept running into nacks about how we were implementing it (after getting a recommendation to try implementing it some way). After a few iterations and massive engineering time, we have been progressively reducing the amount of changes outside i915 in the hopes to get this merged.

And all the while clock is ticking, so we thought the best way to get something to support our future work is to implement this first locally with minimal external changes outside i915 and then once we have something working, it'll be easier to generalize it for the drm core. Otherwise we'll never get to work with the huge page support, for which gemfs is the stepping stone here.

Quoted 3 lines

So we're not planning on sitting on top of it, we'll just incubate it under i915/ so that it'll then be less pain for others to adopt when the biggest hurdles with core MM interactions are sorted out.

But by doing this, you are now creating a new user/kernel api that you have to support for forever, right? Will it not change if you make it "generic" to the drm core eventually?

Worse case, name it a generic name that everyone will end up using in the future, and then you can just claim that all other drivers need to implement it :)

thanks,

greg k-h

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#8 lore raw

Re: [PATCH 02/22] drm/i915: introduce simple gemfs

Quoted 37 lines · Greg Kroah-Hartman
Quoted 36 lines · Joonas Lahtinen
Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Matthew Auld

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.

v2: various improvements suggested by Joonas

v3: move gemfs instance to i915.mm and simplify now that we have file_setup_with_mnt

Quoted 8 lines
Quoted 3 lines

v4: fallback to tmpfs shm_mnt upon failure to setup gemfs

v5: make tmpfs fallback kinder

Why do this only for one specific driver? Shouldn't the drm core handle this for you, for all other drivers as well? Otherwise trying to figure out how to "contain" this type of thing is going to be a pain (mount options, selinux options, etc.)

We actually started quite grande by making stripped down version of shmemfs for drm core, but kept running into nacks about how we were implementing it (after getting a recommendation to try implementing it some way). After a few iterations and massive engineering time, we have been progressively reducing the amount of changes outside i915 in the hopes to get this merged.

And all the while clock is ticking, so we thought the best way to get something to support our future work is to implement this first locally with minimal external changes outside i915 and then once we have something working, it'll be easier to generalize it for the drm core. Otherwise we'll never get to work with the huge page support, for which gemfs is the stepping stone here.

Quoted 7 lines
Quoted 3 lines

So we're not planning on sitting on top of it, we'll just incubate it under i915/ so that it'll then be less pain for others to adopt when the biggest hurdles with core MM interactions are sorted out.

But by doing this, you are now creating a new user/kernel api that you have to support for forever, right? Will it not change if you make it "generic" to the drm core eventually?

Nope, this series is actually just for the driver to get some THPs, regardless of whether user asked for them or not. It's an opportunistic feature in this form, no new API introduced. We will also take advantage if we happen to get 4-order pages (64KB).

What comes to the API anyway, the differences between each GPU driver are big enough that we each have our own GEM buffer create IOCTLs for example (I915_GEM_CREATE for i915). And then those are internally calling DRM core functions which do bulk of the work with the backing storage. So if we provide an interface for the user to enforce getting huge pages, we'll simply have our own bit in the IOCTL which will then be translated to some DRM core flag or function call.

Quoted 3 lines

Worse case, name it a generic name that everyone will end up using in the future, and then you can just claim that all other drivers need to implement it :)

"gem" is the DRM core memory manager (well, the other of them), so "gemfs" is not an accidental name :) We're definitely driving it there.

Regards, Joonas

Signature · 7 lines
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#9 lore raw

PATCH 3/22 mm/shmem: parse mount options for MS_KERNMOUNT

In reply to Matthew Auld

In i915 we now have our own tmpfs mount, so ensure that shmem_fill_super also calls shmem_parse_options when dealing with a kernel mount. Otherwise we have to clumsily call remount_fs when we want to supply our mount options.

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
---
 mm/shmem.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
mm/shmem.c +6 -4
index ae2e46291ffa..6074e527b9b9 100644
@@ -3781,13 +3781,15 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
 	if (!(sb->s_flags & MS_KERNMOUNT)) {
 		sbinfo->max_blocks = shmem_default_max_blocks();
 		sbinfo->max_inodes = shmem_default_max_inodes();
-		if (shmem_parse_options(data, sbinfo, false)) {
-			err = -EINVAL;
-			goto failed;
-		}
 	} else {
 		sb->s_flags |= MS_NOUSER;
 	}
+
+	if (shmem_parse_options(data, sbinfo, false)) {
+		err = -EINVAL;
+		goto failed;
+	}
+
 	sb->s_export_op = &shmem_export_ops;
 	sb->s_flags |= MS_NOSEC;
 #else
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#10 lore raw

Re: [PATCH 03/22] mm/shmem: parse mount options for MS_KERNMOUNT

Quoting Matthew Auld (2017-09-25 19:47:18)

Quoted 5 lines

In i915 we now have our own tmpfs mount, so ensure that shmem_fill_super also calls shmem_parse_options when dealing with a kernel mount. Otherwise we have to clumsily call remount_fs when we want to supply our mount options.

Quoted 8 lines
Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>

I could not find a counter argument why all kernel users had to skip shmem_parse_options(), is there a danger that data may be anything other than a string or NULL?
-Chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author reviewer
#11 lore raw

PATCH 4/22 drm/i915/gemfs: enable THP

In reply to Matthew Auld

Enable transparent-huge-pages through gemfs by mounting with huge=within_size.

v2: prefer kern_mount_data

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
---
 drivers/gpu/drm/i915/i915_gemfs.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_gemfs.c +7 -1
index 168d0bd98f60..dc35719814f0 100644
@@ -24,6 +24,7 @@
 
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/pagemap.h>
 
 #include "i915_drv.h"
 #include "i915_gemfs.h"
@@ -32,12 +33,17 @@ int i915_gemfs_init(struct drm_i915_private *i915)
 {
 	struct file_system_type *type;
 	struct vfsmount *gemfs;
+	char within_size[] = "huge=within_size";
+	char *options = NULL;
 
 	type = get_fs_type("tmpfs");
 	if (!type)
 		return -ENODEV;
 
-	gemfs = kern_mount(type);
+	if (has_transparent_hugepage())
+		options = within_size;
+
+	gemfs = kern_mount_data(type, options);
 	if (IS_ERR(gemfs))
 		return PTR_ERR(gemfs);
 
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on v1 4/22
#12 lore raw

Re: [PATCH 04/22] drm/i915/gemfs: enable THP

Quoting Matthew Auld (2017-09-25 19:47:19)

Quoted 30 lines

Enable transparent-huge-pages through gemfs by mounting with huge=within_size.

v2: prefer kern_mount_data

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Kirill A. Shutemov <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Hugh Dickins <[email protected]>
---
 drivers/gpu/drm/i915/i915_gemfs.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_gemfs.c +1 -0
index 168d0bd98f60..dc35719814f0 100644
@@ -24,6 +24,7 @@
 
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/pagemap.h>
 
 #include "i915_drv.h"
 #include "i915_gemfs.h"

drivers/gpu/drm/i915/i915_gemfs.c int i915_gemfs_init(struct drm_i915_private *i915) · line 42

Quoted 10 lines
drivers/gpu/drm/i915/i915_gemfs.c +2 -0
@@ -32,12 +33,17 @@ int i915_gemfs_init(struct drm_i915_private *i915)
 {
        struct file_system_type *type;
        struct vfsmount *gemfs;
+       char within_size[] = "huge=within_size";
+       char *options = NULL;
 
        type = get_fs_type("tmpfs");
        if (!type)
                return -ENODEV;
 

/*
* Enable hugepages that fit into the object's size so that
* we do not overallocate, as the excess will not be reused and
* our objects may be extremely long lived.
*/

drivers/gpu/drm/i915/i915_gemfs.c int i915_gemfs_init(struct drm_i915_private *i915) · line 46

Quoted 5 lines
drivers/gpu/drm/i915/i915_gemfs.c +4 -1
-       gemfs = kern_mount(type);
+       if (has_transparent_hugepage())
+               options = within_size;
+
+       gemfs = kern_mount_data(type, options);

The alternative to the previous two patches would be to export a function to set the hugepage policy on the shmem_sb_info.

drivers/gpu/drm/i915/i915_gemfs.c int i915_gemfs_init(struct drm_i915_private *i915) · line 48

Quoted 2 lines
drivers/gpu/drm/i915/i915_gemfs.c +0 -0
        if (IS_ERR(gemfs))
                return PTR_ERR(gemfs);

-Chris

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author reviewer
#13 lore raw

PATCH 5/22 drm/i915: introduce page_sizes field to dev_info

In reply to Matthew Auld

In preparation for huge gtt pages expose page_sizes as part of the device info, to indicate the page sizes supported by the HW. Currently only 4K is supported.

v2: s/page_size_mask/page_sizes/

---
 drivers/gpu/drm/i915/i915_drv.h                  |  1 +
 drivers/gpu/drm/i915/i915_gem_gtt.h              |  7 ++++++-
 drivers/gpu/drm/i915/i915_pci.c                  | 20 ++++++++++++++++++++
 drivers/gpu/drm/i915/selftests/mock_gem_device.c |  3 +++
 4 files changed, 30 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index d2079c863a9f..b7ecf43080a8 100644
@@ -862,6 +862,7 @@ struct intel_device_info {
 	u8 gt; /* GT number, 0 if undefined */
 	u8 ring_mask; /* Rings supported by the HW */
 	u8 num_rings;
+	unsigned int page_sizes; /* page sizes supported by the HW */
 #define DEFINE_FLAG(name) u8 name:1
 	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
 #undef DEFINE_FLAG
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -1
index f62fb903dc24..88e9724d5fc7 100644
@@ -42,7 +42,12 @@
 #include "i915_gem_request.h"
 #include "i915_selftest.h"
 
-#define I915_GTT_PAGE_SIZE 4096UL
+#define I915_GTT_PAGE_SIZE_4K BIT(12)
+#define I915_GTT_PAGE_SIZE_64K BIT(16)
+#define I915_GTT_PAGE_SIZE_2M BIT(21)
+
+#define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K
+
 #define I915_GTT_MIN_ALIGNMENT I915_GTT_PAGE_SIZE
 
 #define I915_FENCE_REG_NONE -1
drivers/gpu/drm/i915/i915_pci.c +20 -0
index da60866b6628..84cdab3c5f09 100644
@@ -56,6 +56,10 @@
 	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
 
 /* Keep in gen based order, and chronological order within a gen */
+
+#define GEN_DEFAULT_PAGE_SIZES \
+	.page_sizes = I915_GTT_PAGE_SIZE_4K
+
 #define GEN2_FEATURES \
 	.gen = 2, .num_pipes = 1, \
 	.has_overlay = 1, .overlay_needs_physical = 1, \
@@ -65,6 +69,7 @@
 	.ring_mask = RENDER_RING, \
 	.has_snoop = true, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i830_info __initconst = {
@@ -98,6 +103,7 @@ static const struct intel_device_info intel_i865g_info __initconst = {
 	.ring_mask = RENDER_RING, \
 	.has_snoop = true, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i915g_info __initconst = {
@@ -161,6 +167,7 @@ static const struct intel_device_info intel_pineview_info __initconst = {
 	.ring_mask = RENDER_RING, \
 	.has_snoop = true, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i965g_info __initconst = {
@@ -203,6 +210,7 @@ static const struct intel_device_info intel_gm45_info __initconst = {
 	.ring_mask = RENDER_RING | BSD_RING, \
 	.has_snoop = true, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_ironlake_d_info __initconst = {
@@ -226,6 +234,7 @@ static const struct intel_device_info intel_ironlake_m_info __initconst = {
 	.has_rc6p = 1, \
 	.has_aliasing_ppgtt = 1, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	CURSOR_OFFSETS
 
 #define SNB_D_PLATFORM \
@@ -269,6 +278,7 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst =
 	.has_aliasing_ppgtt = 1, \
 	.has_full_ppgtt = 1, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	IVB_CURSOR_OFFSETS
 
 #define IVB_D_PLATFORM \
@@ -325,6 +335,7 @@ static const struct intel_device_info intel_valleyview_info __initconst = {
 	.has_snoop = true,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
+	GEN_DEFAULT_PAGE_SIZES,
 	GEN_DEFAULT_PIPEOFFSETS,
 	CURSOR_OFFSETS
 };
@@ -363,6 +374,7 @@ static const struct intel_device_info intel_haswell_gt3_info __initconst = {
 #define BDW_FEATURES \
 	HSW_FEATURES, \
 	BDW_COLORS, \
+	GEN_DEFAULT_PAGE_SIZES, \
 	.has_logical_ring_contexts = 1, \
 	.has_full_48bit_ppgtt = 1, \
 	.has_64bit_reloc = 1, \
@@ -415,13 +427,18 @@ static const struct intel_device_info intel_cherryview_info __initconst = {
 	.has_reset_engine = 1,
 	.has_snoop = true,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
+	GEN_DEFAULT_PAGE_SIZES,
 	GEN_CHV_PIPEOFFSETS,
 	CURSOR_OFFSETS,
 	CHV_COLORS,
 };
 
+#define GEN9_DEFAULT_PAGE_SIZES \
+	.page_sizes = I915_GTT_PAGE_SIZE_4K
+
 #define SKL_PLATFORM \
 	BDW_FEATURES, \
+	GEN9_DEFAULT_PAGE_SIZES, \
 	.gen = 9, \
 	.platform = INTEL_SKYLAKE, \
 	.has_csr = 1, \
@@ -477,6 +494,7 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = {
 	.has_reset_engine = 1, \
 	.has_snoop = true, \
 	.has_ipc = 1, \
+	GEN9_DEFAULT_PAGE_SIZES, \
 	GEN_DEFAULT_PIPEOFFSETS, \
 	IVB_CURSOR_OFFSETS, \
 	BDW_COLORS
@@ -496,6 +514,7 @@ static const struct intel_device_info intel_geminilake_info __initconst = {
 
 #define KBL_PLATFORM \
 	BDW_FEATURES, \
+	GEN9_DEFAULT_PAGE_SIZES, \
 	.gen = 9, \
 	.platform = INTEL_KABYLAKE, \
 	.has_csr = 1, \
@@ -546,6 +565,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info __initconst = {
 
 static const struct intel_device_info intel_cannonlake_gt2_info __initconst = {
 	BDW_FEATURES,
+	GEN9_DEFAULT_PAGE_SIZES, \
 	.is_alpha_support = 1,
 	.platform = INTEL_CANNONLAKE,
 	.gen = 10,
drivers/gpu/drm/i915/selftests/mock_gem_device.c +3 -0
index ed3407b078e7..1785c63ad797 100644
@@ -174,6 +174,9 @@ struct drm_i915_private *mock_gem_device(void)
 
 	mkwrite_device_info(i915)->gen = -1;
 
+	mkwrite_device_info(i915)->page_sizes =
+		I915_GTT_PAGE_SIZE_4K;
+
 	spin_lock_init(&i915->mm.object_stat_lock);
 	mock_uncore_init(i915);
 
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#14 lore raw

PATCH 6/22 drm/i915: push set_pages down to the callers

In reply to Matthew Auld

Each backend is now responsible for calling __i915_gem_object_set_pages upon successfully gathering its backing storage. This eliminates the inconsistency between the async and sync paths, which stands out even more when we start throwing around an sg_mask in a later patch.

---
 drivers/gpu/drm/i915/i915_gem.c                  | 45 +++++++++++++-----------
 drivers/gpu/drm/i915/i915_gem_dmabuf.c           | 15 +++++---
 drivers/gpu/drm/i915/i915_gem_internal.c         | 15 ++++----
 drivers/gpu/drm/i915/i915_gem_object.h           |  2 +-
 drivers/gpu/drm/i915/i915_gem_stolen.c           | 16 ++++++---
 drivers/gpu/drm/i915/i915_gem_userptr.c          | 12 +++----
 drivers/gpu/drm/i915/selftests/huge_gem_object.c | 14 ++++----
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c    | 12 ++++---
 8 files changed, 77 insertions(+), 54 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +24 -21
index 26a3ad2668d7..f26385732635 100644
@@ -162,8 +162,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
-static struct sg_table *
-i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
 	struct address_space *mapping = obj->base.filp->f_mapping;
 	drm_dma_handle_t *phys;
@@ -171,9 +170,10 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	struct scatterlist *sg;
 	char *vaddr;
 	int i;
+	int err;
 
 	if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	/* Always aligning to the object size, allows a single allocation
 	 * to handle all possible callers, and given typical object sizes,
@@ -183,7 +183,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 			     roundup_pow_of_two(obj->base.size),
 			     roundup_pow_of_two(obj->base.size));
 	if (!phys)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	vaddr = phys->vaddr;
 	for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
@@ -192,7 +192,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 
 		page = shmem_read_mapping_page(mapping, i);
 		if (IS_ERR(page)) {
-			st = ERR_CAST(page);
+			err = PTR_ERR(page);
 			goto err_phys;
 		}
 
@@ -209,13 +209,13 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st) {
-		st = ERR_PTR(-ENOMEM);
+		err = -ENOMEM;
 		goto err_phys;
 	}
 
 	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
 		kfree(st);
-		st = ERR_PTR(-ENOMEM);
+		err = -ENOMEM;
 		goto err_phys;
 	}
 
@@ -227,11 +227,15 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 	sg_dma_len(sg) = obj->base.size;
 
 	obj->phys_handle = phys;
-	return st;
+
+	__i915_gem_object_set_pages(obj, st);
+
+	return 0;
 
 err_phys:
 	drm_pci_free(obj->base.dev, phys);
-	return st;
+
+	return err;
 }
 
 static void __start_cpu_write(struct drm_i915_gem_object *obj)
@@ -2292,8 +2296,7 @@ static bool i915_sg_trim(struct sg_table *orig_st)
 	return true;
 }
 
-static struct sg_table *
-i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 	const unsigned long page_count = obj->base.size / PAGE_SIZE;
@@ -2317,12 +2320,12 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (st == NULL)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 rebuild_st:
 	if (sg_alloc_table(st, page_count, GFP_KERNEL)) {
 		kfree(st);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* Get the list of pages out of our struct file.  They'll be pinned
@@ -2430,7 +2433,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_do_bit_17_swizzle(obj, st);
 
-	return st;
+	__i915_gem_object_set_pages(obj, st);
+
+	return 0;
 
 err_sg:
 	sg_mark_end(sg);
@@ -2451,7 +2456,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 	if (ret == -ENOSPC)
 		ret = -ENOMEM;
 
-	return ERR_PTR(ret);
+	return ret;
 }
 
 void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
@@ -2474,19 +2479,17 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 
 static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 {
-	struct sg_table *pages;
+	int err;
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
 		return -EFAULT;
 	}
 
-	pages = obj->ops->get_pages(obj);
-	if (unlikely(IS_ERR(pages)))
-		return PTR_ERR(pages);
+	err = obj->ops->get_pages(obj);
+	GEM_BUG_ON(!err && IS_ERR_OR_NULL(obj->mm.pages));
 
-	__i915_gem_object_set_pages(obj, pages);
-	return 0;
+	return err;
 }
 
 /* Ensure that the associated pages are gathered from the backing storage
drivers/gpu/drm/i915/i915_gem_dmabuf.c +11 -4
index 6176e589cf09..4c4dc85159fb 100644
@@ -256,11 +256,18 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
 	return drm_gem_dmabuf_export(dev, &exp_info);
 }
 
-static struct sg_table *
-i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
 {
-	return dma_buf_map_attachment(obj->base.import_attach,
-				      DMA_BIDIRECTIONAL);
+	struct sg_table *pages;
+
+	pages = dma_buf_map_attachment(obj->base.import_attach,
+				       DMA_BIDIRECTIONAL);
+	if (IS_ERR(pages))
+		return PTR_ERR(pages);
+
+	__i915_gem_object_set_pages(obj, pages);
+
+	return 0;
 }
 
 static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
drivers/gpu/drm/i915/i915_gem_internal.c +9 -6
index c1f64ddaf8aa..f59764da4254 100644
@@ -44,8 +44,7 @@ static void internal_free_pages(struct sg_table *st)
 	kfree(st);
 }
 
-static struct sg_table *
-i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct sg_table *st;
@@ -78,12 +77,12 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 create_st:
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	npages = obj->base.size / PAGE_SIZE;
 	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
 		kfree(st);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	sg = st->sgl;
@@ -132,13 +131,17 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	 * object are only valid whilst active and pinned.
 	 */
 	obj->mm.madv = I915_MADV_DONTNEED;
-	return st;
+
+	__i915_gem_object_set_pages(obj, st);
+
+	return 0;
 
 err:
 	sg_set_page(sg, NULL, 0, 0);
 	sg_mark_end(sg);
 	internal_free_pages(st);
-	return ERR_PTR(-ENOMEM);
+
+	return -ENOMEM;
 }
 
 static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
drivers/gpu/drm/i915/i915_gem_object.h +1 -1
index c30d8f808185..036e847b27f0 100644
@@ -69,7 +69,7 @@ struct drm_i915_gem_object_ops {
 	 * being released or under memory pressure (where we attempt to
 	 * reap pages for the shrinker).
 	 */
-	struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
+	int (*get_pages)(struct drm_i915_gem_object *);
 	void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
 
 	int (*pwrite)(struct drm_i915_gem_object *,
drivers/gpu/drm/i915/i915_gem_stolen.c +11 -5
index 507c9f0d8df1..537ecb224db0 100644
@@ -539,12 +539,18 @@ i915_pages_create_for_stolen(struct drm_device *dev,
 	return st;
 }
 
-static struct sg_table *
-i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
+static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
 {
-	return i915_pages_create_for_stolen(obj->base.dev,
-					    obj->stolen->start,
-					    obj->stolen->size);
+	struct sg_table *pages =
+		i915_pages_create_for_stolen(obj->base.dev,
+					     obj->stolen->start,
+					     obj->stolen->size);
+	if (IS_ERR(pages))
+		return PTR_ERR(pages);
+
+	__i915_gem_object_set_pages(obj, pages);
+
+	return 0;
 }
 
 static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
drivers/gpu/drm/i915/i915_gem_userptr.c +6 -6
index 2d4996de7331..70ad7489827d 100644
@@ -434,6 +434,8 @@ __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj,
 		return ERR_PTR(ret);
 	}
 
+	__i915_gem_object_set_pages(obj, st);
+
 	return st;
 }
 
@@ -521,7 +523,6 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
 			pages = __i915_gem_userptr_alloc_pages(obj, pvec,
 							       npages);
 			if (!IS_ERR(pages)) {
-				__i915_gem_object_set_pages(obj, pages);
 				pinned = 0;
 				pages = NULL;
 			}
@@ -582,8 +583,7 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj)
 	return ERR_PTR(-EAGAIN);
 }
 
-static struct sg_table *
-i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
+static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
 	const int num_pages = obj->base.size >> PAGE_SHIFT;
 	struct mm_struct *mm = obj->userptr.mm->mm;
@@ -612,9 +612,9 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 	if (obj->userptr.work) {
 		/* active flag should still be held for the pending work */
 		if (IS_ERR(obj->userptr.work))
-			return ERR_CAST(obj->userptr.work);
+			return PTR_ERR(obj->userptr.work);
 		else
-			return ERR_PTR(-EAGAIN);
+			return -EAGAIN;
 	}
 
 	pvec = NULL;
@@ -650,7 +650,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 		release_pages(pvec, pinned, 0);
 	kvfree(pvec);
 
-	return pages;
+	return PTR_ERR_OR_ZERO(pages);
 }
 
 static void
drivers/gpu/drm/i915/selftests/huge_gem_object.c +8 -6
index c5c7e8efbdd3..41c15f3aa467 100644
@@ -37,8 +37,7 @@ static void huge_free_pages(struct drm_i915_gem_object *obj,
 	kfree(pages);
 }
 
-static struct sg_table *
-huge_get_pages(struct drm_i915_gem_object *obj)
+static int huge_get_pages(struct drm_i915_gem_object *obj)
 {
 #define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY)
 	const unsigned long nreal = obj->scratch / PAGE_SIZE;
@@ -49,11 +48,11 @@ huge_get_pages(struct drm_i915_gem_object *obj)
 
 	pages = kmalloc(sizeof(*pages), GFP);
 	if (!pages)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	if (sg_alloc_table(pages, npages, GFP)) {
 		kfree(pages);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	sg = pages->sgl;
@@ -81,11 +80,14 @@ huge_get_pages(struct drm_i915_gem_object *obj)
 	if (i915_gem_gtt_prepare_pages(obj, pages))
 		goto err;
 
-	return pages;
+	__i915_gem_object_set_pages(obj, pages);
+
+	return 0;
 
 err:
 	huge_free_pages(obj, pages);
-	return ERR_PTR(-ENOMEM);
+
+	return -ENOMEM;
 #undef GFP
 }
 
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +7 -5
index 6b132caffa18..aa1db375d59a 100644
@@ -39,8 +39,7 @@ static void fake_free_pages(struct drm_i915_gem_object *obj,
 	kfree(pages);
 }
 
-static struct sg_table *
-fake_get_pages(struct drm_i915_gem_object *obj)
+static int fake_get_pages(struct drm_i915_gem_object *obj)
 {
 #define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY)
 #define PFN_BIAS 0x1000
@@ -50,12 +49,12 @@ fake_get_pages(struct drm_i915_gem_object *obj)
 
 	pages = kmalloc(sizeof(*pages), GFP);
 	if (!pages)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	rem = round_up(obj->base.size, BIT(31)) >> 31;
 	if (sg_alloc_table(pages, rem, GFP)) {
 		kfree(pages);
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	rem = obj->base.size;
@@ -72,7 +71,10 @@ fake_get_pages(struct drm_i915_gem_object *obj)
 	GEM_BUG_ON(rem);
 
 	obj->mm.madv = I915_MADV_DONTNEED;
-	return pages;
+
+	__i915_gem_object_set_pages(obj, pages);
+
+	return 0;
 #undef GFP
 }
 
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#15 lore raw

PATCH 7/22 drm/i915: introduce page_size members

In reply to Matthew Auld

In preparation for supporting huge gtt pages for the ppgtt, we introduce page size members for gem objects. We fill in the page sizes by scanning the sg table.

v2: pass the sg_mask to set_pages

v3: calculate the sg_mask inline with populating the sg_table where possible, and pass to set_pages along with the pages.

v4: bunch of improvements from Joonas

---
 drivers/gpu/drm/i915/i915_drv.h                  |  5 ++-
 drivers/gpu/drm/i915/i915_gem.c                  | 42 +++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_gem_dmabuf.c           |  9 ++++-
 drivers/gpu/drm/i915/i915_gem_internal.c         |  5 ++-
 drivers/gpu/drm/i915/i915_gem_object.h           | 17 ++++++++++
 drivers/gpu/drm/i915/i915_gem_stolen.c           |  2 +-
 drivers/gpu/drm/i915/i915_gem_userptr.c          |  9 ++++-
 drivers/gpu/drm/i915/selftests/huge_gem_object.c |  2 +-
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c    |  5 ++-
 9 files changed, 84 insertions(+), 12 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +4 -1
index b7ecf43080a8..bbdfb15c6183 100644
@@ -3085,6 +3085,8 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define USES_PPGTT(dev_priv)		(i915_modparams.enable_ppgtt)
 #define USES_FULL_PPGTT(dev_priv)	(i915_modparams.enable_ppgtt >= 2)
 #define USES_FULL_48BIT_PPGTT(dev_priv)	(i915_modparams.enable_ppgtt == 3)
+#define HAS_PAGE_SIZES(dev_priv, sizes) \
+	((sizes) && (((sizes) & ~(dev_priv)->info.page_sizes)) == 0)
 
 #define HAS_OVERLAY(dev_priv)		 ((dev_priv)->info.has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
@@ -3501,7 +3503,8 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
 				unsigned long n);
 
 void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
-				 struct sg_table *pages);
+				 struct sg_table *pages,
+				 unsigned int sg_mask);
 int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 
 static inline int __must_check
drivers/gpu/drm/i915/i915_gem.c +37 -5

99 lines not on this page · raw message

drivers/gpu/drm/i915/i915_gem_dmabuf.c +8 -1
index 4c4dc85159fb..2f80b07d7f61 100644
@@ -259,13 +259,20 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
 {
 	struct sg_table *pages;
+	struct scatterlist *sg;
+	unsigned int sg_mask;
+	int n;
 
 	pages = dma_buf_map_attachment(obj->base.import_attach,
 				       DMA_BIDIRECTIONAL);
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
-	__i915_gem_object_set_pages(obj, pages);
+	sg_mask = 0;
+	for_each_sg(pages->sgl, sg, pages->nents, n)
+		sg_mask |= sg->length;
+
+	__i915_gem_object_set_pages(obj, pages, sg_mask);
 
 	return 0;
 }
drivers/gpu/drm/i915/i915_gem_internal.c +4 -1
index f59764da4254..bdc23c4c8783 100644
@@ -49,6 +49,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct sg_table *st;
 	struct scatterlist *sg;
+	unsigned int sg_mask;
 	unsigned int npages;
 	int max_order;
 	gfp_t gfp;
@@ -87,6 +88,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 
 	sg = st->sgl;
 	st->nents = 0;
+	sg_mask = 0;
 
 	do {
 		int order = min(fls(npages) - 1, max_order);
@@ -104,6 +106,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 		} while (1);
 
 		sg_set_page(sg, page, PAGE_SIZE << order, 0);
+		sg_mask |= PAGE_SIZE << order;
 		st->nents++;
 
 		npages -= 1 << order;
@@ -132,7 +135,7 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 	 */
 	obj->mm.madv = I915_MADV_DONTNEED;
 
-	__i915_gem_object_set_pages(obj, st);
+	__i915_gem_object_set_pages(obj, st, sg_mask);
 
 	return 0;
 
drivers/gpu/drm/i915/i915_gem_object.h +17 -0
index 036e847b27f0..110672952a1c 100644
@@ -169,6 +169,23 @@ struct drm_i915_gem_object {
 		struct sg_table *pages;
 		void *mapping;
 
+		struct i915_page_sizes {
+			/**
+			 * The sg mask of the pages sg_table. i.e the mask of
+			 * of the lengths for each sg entry.
+			 */
+			unsigned int phys;
+
+			/**
+			 * The gtt page sizes we are allowed to use given the
+			 * sg mask and the supported page sizes. This will
+			 * express the smallest unit we can use for the whole
+			 * object, as well as the larger sizes we may be able
+			 * to use opportunistically.
+			 */
+			unsigned int sg;
+		} page_sizes;
+
 		struct i915_gem_object_page_iter {
 			struct scatterlist *sg_pos;
 			unsigned int sg_idx; /* in pages, but 32bit eek! */
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 537ecb224db0..54fd4cfa9d07 100644
@@ -548,7 +548,7 @@ static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
-	__i915_gem_object_set_pages(obj, pages);
+	__i915_gem_object_set_pages(obj, pages, obj->stolen->size);
 
 	return 0;
 }
drivers/gpu/drm/i915/i915_gem_userptr.c +8 -1
index 70ad7489827d..ad5abca1f794 100644
@@ -405,6 +405,9 @@ __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj,
 {
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
+	struct scatterlist *sg;
+	unsigned int sg_mask;
+	int n;
 	int ret;
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
@@ -434,7 +437,11 @@ __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj,
 		return ERR_PTR(ret);
 	}
 
-	__i915_gem_object_set_pages(obj, st);
+	sg_mask = 0;
+	for_each_sg(st->sgl, sg, num_pages, n)
+		sg_mask |= sg->length;
+
+	__i915_gem_object_set_pages(obj, st, sg_mask);
 
 	return st;
 }
drivers/gpu/drm/i915/selftests/huge_gem_object.c +1 -1
index 41c15f3aa467..a2632df39173 100644
@@ -80,7 +80,7 @@ static int huge_get_pages(struct drm_i915_gem_object *obj)
 	if (i915_gem_gtt_prepare_pages(obj, pages))
 		goto err;
 
-	__i915_gem_object_set_pages(obj, pages);
+	__i915_gem_object_set_pages(obj, pages, PAGE_SIZE);
 
 	return 0;
 
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +4 -1
index aa1db375d59a..883bc19e3aaf 100644
@@ -45,6 +45,7 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
 #define PFN_BIAS 0x1000
 	struct sg_table *pages;
 	struct scatterlist *sg;
+	unsigned int sg_mask;
 	typeof(obj->base.size) rem;
 
 	pages = kmalloc(sizeof(*pages), GFP);
@@ -57,6 +58,7 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
 		return -ENOMEM;
 	}
 
+	sg_mask = 0;
 	rem = obj->base.size;
 	for (sg = pages->sgl; sg; sg = sg_next(sg)) {
 		unsigned long len = min_t(typeof(rem), rem, BIT(31));
@@ -65,6 +67,7 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
 		sg_set_page(sg, pfn_to_page(PFN_BIAS), len, 0);
 		sg_dma_address(sg) = page_to_phys(sg_page(sg));
 		sg_dma_len(sg) = len;
+		sg_mask |= len;
 
 		rem -= len;
 	}
@@ -72,7 +75,7 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
 
 	obj->mm.madv = I915_MADV_DONTNEED;
 
-	__i915_gem_object_set_pages(obj, pages);
+	__i915_gem_object_set_pages(obj, pages, sg_mask);
 
 	return 0;
 #undef GFP
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#16 lore raw

PATCH 8/22 drm/i915: introduce vm set_pages/clear_pages

In reply to Matthew Auld

Move the setting/clearing of the vma->pages to a vm operation. Doing so neatens things up a little, but more importantly gives us a sane place to also set/clear the vma->pages_sizes, which we introduce later in preparation for supporting huge-pages.

v2: remove redundant vma->pages check

v3: GEM_BUG_ON(vma->pages) following i915_vma_remove

---
 drivers/gpu/drm/i915/i915_gem_gtt.c       | 70 +++++++++++++++++++------------
 drivers/gpu/drm/i915/i915_gem_gtt.h       |  2 +
 drivers/gpu/drm/i915/i915_vma.c           | 27 +++++++-----
 drivers/gpu/drm/i915/selftests/mock_gtt.c | 11 ++---
 4 files changed, 66 insertions(+), 44 deletions(-)
drivers/gpu/drm/i915/i915_gem_gtt.c +44 -26
index 64d785262d14..5e0ac4c5a81c 100644
@@ -205,8 +205,6 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
 			return ret;
 	}
 
-	vma->pages = vma->obj->mm.pages;
-
 	/* Currently applicable only to VLV */
 	pte_flags = 0;
 	if (vma->obj->gt_ro)
@@ -222,6 +220,26 @@ static void ppgtt_unbind_vma(struct i915_vma *vma)
 	vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
 }
 
+static int ppgtt_set_pages(struct i915_vma *vma)
+{
+	GEM_BUG_ON(vma->pages);
+
+	vma->pages = vma->obj->mm.pages;
+
+	return 0;
+}
+
+static void clear_pages(struct i915_vma *vma)
+{
+	GEM_BUG_ON(!vma->pages);
+
+	if (vma->pages != vma->obj->mm.pages) {
+		sg_free_table(vma->pages);
+		kfree(vma->pages);
+	}
+	vma->pages = NULL;
+}
+
 static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
 				  enum i915_cache_level level)
 {
@@ -1454,6 +1472,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 	ppgtt->base.cleanup = gen8_ppgtt_cleanup;
 	ppgtt->base.unbind_vma = ppgtt_unbind_vma;
 	ppgtt->base.bind_vma = ppgtt_bind_vma;
+	ppgtt->base.set_pages = ppgtt_set_pages;
+	ppgtt->base.clear_pages = clear_pages;
 	ppgtt->debug_dump = gen8_dump_ppgtt;
 
 	return 0;
@@ -1896,6 +1916,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 	ppgtt->base.insert_entries = gen6_ppgtt_insert_entries;
 	ppgtt->base.unbind_vma = ppgtt_unbind_vma;
 	ppgtt->base.bind_vma = ppgtt_bind_vma;
+	ppgtt->base.set_pages = ppgtt_set_pages;
+	ppgtt->base.clear_pages = clear_pages;
 	ppgtt->base.cleanup = gen6_ppgtt_cleanup;
 	ppgtt->debug_dump = gen6_dump_ppgtt;
 
@@ -2407,12 +2429,6 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 	struct drm_i915_gem_object *obj = vma->obj;
 	u32 pte_flags;
 
-	if (unlikely(!vma->pages)) {
-		int ret = i915_get_ggtt_vma_pages(vma);
-		if (ret)
-			return ret;
-	}
-
 	/* Currently applicable only to VLV */
 	pte_flags = 0;
 	if (obj->gt_ro)
@@ -2449,12 +2465,6 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 	u32 pte_flags;
 	int ret;
 
-	if (unlikely(!vma->pages)) {
-		ret = i915_get_ggtt_vma_pages(vma);
-		if (ret)
-			return ret;
-	}
-
 	/* Currently applicable only to VLV */
 	pte_flags = 0;
 	if (vma->obj->gt_ro)
@@ -2469,7 +2479,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 							     vma->node.start,
 							     vma->size);
 			if (ret)
-				goto err_pages;
+				return ret;
 		}
 
 		appgtt->base.insert_entries(&appgtt->base, vma, cache_level,
@@ -2483,17 +2493,6 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 	}
 
 	return 0;
-
-err_pages:
-	if (!(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND))) {
-		if (vma->pages != vma->obj->mm.pages) {
-			GEM_BUG_ON(!vma->pages);
-			sg_free_table(vma->pages);
-			kfree(vma->pages);
-		}
-		vma->pages = NULL;
-	}
-	return ret;
 }
 
 static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
@@ -2531,6 +2530,19 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
 	dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL);
 }
 
+static int ggtt_set_pages(struct i915_vma *vma)
+{
+	int ret;
+
+	GEM_BUG_ON(vma->pages);
+
+	ret = i915_get_ggtt_vma_pages(vma);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static void i915_gtt_color_adjust(const struct drm_mm_node *node,
 				  unsigned long color,
 				  u64 *start,
@@ -3153,6 +3165,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 	ggtt->base.cleanup = gen6_gmch_remove;
 	ggtt->base.bind_vma = ggtt_bind_vma;
 	ggtt->base.unbind_vma = ggtt_unbind_vma;
+	ggtt->base.set_pages = ggtt_set_pages;
+	ggtt->base.clear_pages = clear_pages;
 	ggtt->base.insert_page = gen8_ggtt_insert_page;
 	ggtt->base.clear_range = nop_clear_range;
 	if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv))
@@ -3211,6 +3225,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
 	ggtt->base.insert_entries = gen6_ggtt_insert_entries;
 	ggtt->base.bind_vma = ggtt_bind_vma;
 	ggtt->base.unbind_vma = ggtt_unbind_vma;
+	ggtt->base.set_pages = ggtt_set_pages;
+	ggtt->base.clear_pages = clear_pages;
 	ggtt->base.cleanup = gen6_gmch_remove;
 
 	ggtt->invalidate = gen6_ggtt_invalidate;
@@ -3256,6 +3272,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
 	ggtt->base.clear_range = i915_ggtt_clear_range;
 	ggtt->base.bind_vma = ggtt_bind_vma;
 	ggtt->base.unbind_vma = ggtt_unbind_vma;
+	ggtt->base.set_pages = ggtt_set_pages;
+	ggtt->base.clear_pages = clear_pages;
 	ggtt->base.cleanup = i915_gmch_remove;
 
 	ggtt->invalidate = gmch_ggtt_invalidate;
drivers/gpu/drm/i915/i915_gem_gtt.h +2 -0
index 88e9724d5fc7..87f3ceaca5a8 100644
@@ -334,6 +334,8 @@ struct i915_address_space {
 	int (*bind_vma)(struct i915_vma *vma,
 			enum i915_cache_level cache_level,
 			u32 flags);
+	int (*set_pages)(struct i915_vma *vma);
+	void (*clear_pages)(struct i915_vma *vma);
 
 	I915_SELFTEST_DECLARE(struct fault_attr fault_attr);
 };
drivers/gpu/drm/i915/i915_vma.c +16 -11
index 02d1a5eacb00..49bf49571e47 100644
@@ -266,6 +266,8 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
 	if (bind_flags == 0)
 		return 0;
 
+	GEM_BUG_ON(!vma->pages);
+
 	trace_i915_vma_bind(vma, bind_flags);
 	ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
 	if (ret)
@@ -471,25 +473,31 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	if (ret)
 		return ret;
 
+	GEM_BUG_ON(vma->pages);
+
+	ret = vma->vm->set_pages(vma);
+	if (ret)
+		goto err_unpin;
+
 	if (flags & PIN_OFFSET_FIXED) {
 		u64 offset = flags & PIN_OFFSET_MASK;
 		if (!IS_ALIGNED(offset, alignment) ||
 		    range_overflows(offset, size, end)) {
 			ret = -EINVAL;
-			goto err_unpin;
+			goto err_clear;
 		}
 
 		ret = i915_gem_gtt_reserve(vma->vm, &vma->node,
 					   size, offset, obj->cache_level,
 					   flags);
 		if (ret)
-			goto err_unpin;
+			goto err_clear;
 	} else {
 		ret = i915_gem_gtt_insert(vma->vm, &vma->node,
 					  size, alignment, obj->cache_level,
 					  start, end, flags);
 		if (ret)
-			goto err_unpin;
+			goto err_clear;
 
 		GEM_BUG_ON(vma->node.start < start);
 		GEM_BUG_ON(vma->node.start + vma->node.size > end);
@@ -504,6 +512,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
 	return 0;
 
+err_clear:
+	vma->vm->clear_pages(vma);
 err_unpin:
 	i915_gem_object_unpin_pages(obj);
 	return ret;
@@ -517,6 +527,8 @@ i915_vma_remove(struct i915_vma *vma)
 	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
 	GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
 
+	vma->vm->clear_pages(vma);
+
 	drm_mm_remove_node(&vma->node);
 	list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
 
@@ -569,8 +581,8 @@ int __i915_vma_do_pin(struct i915_vma *vma,
 
 err_remove:
 	if ((bound & I915_VMA_BIND_MASK) == 0) {
-		GEM_BUG_ON(vma->pages);
 		i915_vma_remove(vma);
+		GEM_BUG_ON(vma->pages);
 	}
 err_unpin:
 	__i915_vma_unpin(vma);
@@ -695,13 +707,6 @@ int i915_vma_unbind(struct i915_vma *vma)
 	}
 	vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
 
-	if (vma->pages != obj->mm.pages) {
-		GEM_BUG_ON(!vma->pages);
-		sg_free_table(vma->pages);
-		kfree(vma->pages);
-	}
-	vma->pages = NULL;
-
 	i915_vma_remove(vma);
 
 destroy:
drivers/gpu/drm/i915/selftests/mock_gtt.c +4 -7
index f2118cf535a0..336e1afb250f 100644
@@ -43,7 +43,6 @@ static int mock_bind_ppgtt(struct i915_vma *vma,
 			   u32 flags)
 {
 	GEM_BUG_ON(flags & I915_VMA_GLOBAL_BIND);
-	vma->pages = vma->obj->mm.pages;
 	vma->flags |= I915_VMA_LOCAL_BIND;
 	return 0;
 }
@@ -84,6 +83,8 @@ mock_ppgtt(struct drm_i915_private *i915,
 	ppgtt->base.insert_entries = mock_insert_entries;
 	ppgtt->base.bind_vma = mock_bind_ppgtt;
 	ppgtt->base.unbind_vma = mock_unbind_ppgtt;
+	ppgtt->base.set_pages = ppgtt_set_pages;
+	ppgtt->base.clear_pages = clear_pages;
 	ppgtt->base.cleanup = mock_cleanup;
 
 	return ppgtt;
@@ -93,12 +94,6 @@ static int mock_bind_ggtt(struct i915_vma *vma,
 			  enum i915_cache_level cache_level,
 			  u32 flags)
 {
-	int err;
-
-	err = i915_get_ggtt_vma_pages(vma);
-	if (err)
-		return err;
-
 	vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND;
 	return 0;
 }
@@ -124,6 +119,8 @@ void mock_init_ggtt(struct drm_i915_private *i915)
 	ggtt->base.insert_entries = mock_insert_entries;
 	ggtt->base.bind_vma = mock_bind_ggtt;
 	ggtt->base.unbind_vma = mock_unbind_ggtt;
+	ggtt->base.set_pages = ggtt_set_pages;
+	ggtt->base.clear_pages = clear_pages;
 	ggtt->base.cleanup = mock_cleanup;
 
 	i915_address_space_init(&ggtt->base, i915, "global");
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#17 lore raw

PATCH 9/22 drm/i915: align the vma start to the largest gtt page size

In reply to Matthew Auld

For the 48b PPGTT try to align the vma start address to the required page size boundary to guarantee we use said page size in the gtt. If we are dealing with multiple page sizes, we can't guarantee anything and just align to the largest. For soft pinning and objects which need to be tightly packed into the lower 32bits we don't force any alignment.

v2: various improvements suggested by Chris

v3: use set_pages and better placement of page_sizes

v4: prefer upper_32_bits()

---
 drivers/gpu/drm/i915/i915_gem_gtt.c |  8 ++++++++
 drivers/gpu/drm/i915/i915_vma.c     | 13 +++++++++++++
 drivers/gpu/drm/i915/i915_vma.h     |  1 +
 3 files changed, 22 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +8 -0
index 5e0ac4c5a81c..a3897676e0bc 100644
@@ -226,6 +226,9 @@ static int ppgtt_set_pages(struct i915_vma *vma)
 
 	vma->pages = vma->obj->mm.pages;
 
+	vma->page_sizes.phys = vma->obj->mm.page_sizes.phys;
+	vma->page_sizes.sg = vma->obj->mm.page_sizes.sg;
+
 	return 0;
 }
 
@@ -238,6 +241,8 @@ static void clear_pages(struct i915_vma *vma)
 		kfree(vma->pages);
 	}
 	vma->pages = NULL;
+
+	memset(&vma->page_sizes, 0, sizeof(struct i915_page_sizes));
 }
 
 static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
@@ -2540,6 +2545,9 @@ static int ggtt_set_pages(struct i915_vma *vma)
 	if (ret)
 		return ret;
 
+	vma->page_sizes.phys = vma->obj->mm.page_sizes.phys;
+	vma->page_sizes.sg = vma->obj->mm.page_sizes.sg;
+
 	return 0;
 }
 
drivers/gpu/drm/i915/i915_vma.c +13 -0
index 49bf49571e47..5067eab27829 100644
@@ -493,6 +493,19 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 		if (ret)
 			goto err_clear;
 	} else {
+		/*
+		 * We only support huge gtt pages through the 48b PPGTT,
+		 * however we also don't want to force any alignment for
+		 * objects which need to be tightly packed into the low 32bits.
+		 */
+		if (upper_32_bits(end) &&
+		    vma->page_sizes.sg > I915_GTT_PAGE_SIZE) {
+			u64 page_alignment =
+				rounddown_pow_of_two(vma->page_sizes.sg);
+
+			alignment = max(alignment, page_alignment);
+		}
+
 		ret = i915_gem_gtt_insert(vma->vm, &vma->node,
 					  size, alignment, obj->cache_level,
 					  start, end, flags);
drivers/gpu/drm/i915/i915_vma.h +1 -0
index e811067c7724..c59ba76613a3 100644
@@ -55,6 +55,7 @@ struct i915_vma {
 	void __iomem *iomap;
 	u64 size;
 	u64 display_alignment;
+	struct i915_page_sizes page_sizes;
 
 	u32 fence_size;
 	u32 fence_alignment;
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#18 lore raw

PATCH 10/22 drm/i915: align 64K objects to 2M

In reply to Matthew Auld

We can't mix 64K and 4K pte's in the same page-table, so for now we align 64K objects to 2M to avoid any potential mixing. This is potentially wasteful but in reality shouldn't be too bad since this only applies to the virtual address space of a 48b PPGTT.

v2: don't separate logically connected ops

---
 drivers/gpu/drm/i915/i915_vma.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_vma.c +10 -1
index 5067eab27829..cc06a7100c81 100644
@@ -501,9 +501,18 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 		if (upper_32_bits(end) &&
 		    vma->page_sizes.sg > I915_GTT_PAGE_SIZE) {
 			u64 page_alignment =
-				rounddown_pow_of_two(vma->page_sizes.sg);
+				rounddown_pow_of_two(vma->page_sizes.sg |
+						     I915_GTT_PAGE_SIZE_2M);
 
 			alignment = max(alignment, page_alignment);
+
+			/*
+			 * We can't mix 64K and 4K PTEs in the same page-table (2M
+			 * block), and so to avoid the ugliness and complexity of
+			 * coloring we opt for just aligning 64K objects to 2M.
+			 */
+			if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K)
+				size = round_up(size, I915_GTT_PAGE_SIZE_2M);
 		}
 
 		ret = i915_gem_gtt_insert(vma->vm, &vma->node,
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#19 lore raw

PATCH 11/22 drm/i915: enable IPS bit for 64K pages

In reply to Matthew Auld

Before we can enable 64K pages through the IPS bit, we must first enable it through MMIO, otherwise the page-walker will simply ignore it.

v2: add comment mentioning that 64K is BDW+

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h |  3 +++
 2 files changed, 20 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +17 -0
index c9460433372a..11b287d53315 100644
@@ -4751,6 +4751,23 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv)
 		}
 	}
 
+	/*
+	 * To support 64K PTEs we need to first enable the use of the
+	 * Intermediate-Page-Size(IPS) bit of the PDE field via some magical
+	 * mmio, otherwise the page-walker will simply ignore the IPS bit. This
+	 * shouldn't be needed after GEN10.
+	 *
+	 * 64K pages were first introduced from BDW+, although technically they
+	 * only *work* from gen9+. For pre-BDW we instead have the option for
+	 * 32K pages, but we don't currently have any support for it in our
+	 * driver.
+	 */
+	if (HAS_PAGE_SIZES(dev_priv, I915_GTT_PAGE_SIZE_64K) &&
+	    INTEL_GEN(dev_priv) <= 10)
+		I915_WRITE(GEN8_GAMW_ECO_DEV_RW_IA,
+			   I915_READ(GEN8_GAMW_ECO_DEV_RW_IA) |
+			   GAMW_ECO_ENABLE_64K_IPS_FIELD);
+
 	i915_gem_init_swizzling(dev_priv);
 
 	/*
drivers/gpu/drm/i915/i915_reg.h +3 -0
index 82f36dd0cd94..6fdcaec0e2ee 100644
@@ -2371,6 +2371,9 @@ enum i915_power_well_id {
 #define GEN9_GAMT_ECO_REG_RW_IA _MMIO(0x4ab0)
 #define   GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS	(1<<18)
 
+#define GEN8_GAMW_ECO_DEV_RW_IA _MMIO(0x4080)
+#define   GAMW_ECO_ENABLE_64K_IPS_FIELD 0xF
+
 #define GAMT_CHKN_BIT_REG	_MMIO(0x4ab8)
 #define   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING	(1<<28)
 #define   GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT	(1<<24)
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#20 lore raw

PATCH 12/22 drm/i915: disable GTT cache for 2M pages

In reply to Matthew Auld

When SW enables the use of 2M/1G pages, it must disable the GTT cache.

v2: don't disable for Cherryview which doesn't even support 48b PPGTT!

v3: explicitly check that the system does support 2M/1G pages

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/intel_pm.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +5 -3
index c66af09e27a7..719a1c5f1ffa 100644
@@ -8483,10 +8483,12 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
 
 	/*
 	 * WaGttCachingOffByDefault:bdw
-	 * GTT cache may not work with big pages, so if those
-	 * are ever enabled GTT cache may need to be disabled.
+	 * The GTT cache must be disabled if the system is planning to use
+	 * 2M/1G pages.
 	 */
-	I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
+	I915_WRITE(HSW_GTT_CACHE_EN,
+		   HAS_PAGE_SIZES(dev_priv, I915_GTT_PAGE_SIZE_2M) ? 0 :
+		   GTT_CACHE_EN_ALL);
 
 	/* WaKVMNotificationOnConfigChange:bdw */
 	I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1)
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#21 lore raw

PATCH 13/22 drm/i915: support 2M pages for the 48b PPGTT

In reply to Matthew Auld

Support inserting 2M gtt pages into the 48b PPGTT.

v2: sanity check sg->length against page_size

v3: don't recalculate rem on each loop
whitespace breakup

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 76 +++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_gem_gtt.h |  2 +
 2 files changed, 74 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_gem_gtt.c +72 -4
index a3897676e0bc..51a1cdcfc693 100644
@@ -1016,6 +1016,69 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
 				      cache_level);
 }
 
+static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
+					   struct i915_page_directory_pointer **pdps,
+					   struct sgt_dma *iter,
+					   enum i915_cache_level cache_level)
+{
+	const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level);
+	u64 start = vma->node.start;
+	dma_addr_t rem = iter->sg->length;
+
+	do {
+		struct gen8_insert_pte idx = gen8_insert_pte(start);
+		struct i915_page_directory_pointer *pdp = pdps[idx.pml4e];
+		struct i915_page_directory *pd = pdp->page_directory[idx.pdpe];
+		unsigned int page_size;
+		gen8_pte_t encode = pte_encode;
+		gen8_pte_t *vaddr;
+		u16 index, max;
+
+		if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
+		    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) &&
+		    rem >= I915_GTT_PAGE_SIZE_2M && !idx.pte) {
+			index = idx.pde;
+			max = I915_PDES;
+			page_size = I915_GTT_PAGE_SIZE_2M;
+
+			encode |= GEN8_PDE_PS_2M;
+
+			vaddr = kmap_atomic_px(pd);
+		} else {
+			struct i915_page_table *pt = pd->page_table[idx.pde];
+
+			index = idx.pte;
+			max = GEN8_PTES;
+			page_size = I915_GTT_PAGE_SIZE;
+
+			vaddr = kmap_atomic_px(pt);
+		}
+
+		do {
+			GEM_BUG_ON(iter->sg->length < page_size);
+			vaddr[index++] = encode | iter->dma;
+
+			start += page_size;
+			iter->dma += page_size;
+			rem -= page_size;
+			if (iter->dma >= iter->max) {
+				iter->sg = __sg_next(iter->sg);
+				if (!iter->sg)
+					break;
+
+				rem = iter->sg->length;
+				iter->dma = sg_dma_address(iter->sg);
+				iter->max = iter->dma + rem;
+
+				if (unlikely(!IS_ALIGNED(iter->dma, page_size)))
+					break;
+			}
+		} while (rem >= page_size && index < max);
+
+		kunmap_atomic(vaddr);
+	} while (iter->sg);
+}
+
 static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 				   struct i915_vma *vma,
 				   enum i915_cache_level cache_level,
@@ -1028,11 +1091,16 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 		.max = iter.dma + iter.sg->length,
 	};
 	struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;
-	struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start);
 
-	while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter,
-					     &idx, cache_level))
-		GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
+	if (vma->page_sizes.sg > I915_GTT_PAGE_SIZE) {
+		gen8_ppgtt_insert_huge_entries(vma, pdps, &iter, cache_level);
+	} else {
+		struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start);
+
+		while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++],
+						     &iter, &idx, cache_level))
+			GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
+	}
 }
 
 static void gen8_free_page_tables(struct i915_address_space *vm,
drivers/gpu/drm/i915/i915_gem_gtt.h +2 -0
index 87f3ceaca5a8..e9e66abbe532 100644
@@ -153,6 +153,8 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT_GET_AGE(x) ((x) & (3 << 4))
 #define CHV_PPAT_GET_SNOOP(x) ((x) & (1 << 6))
 
+#define GEN8_PDE_PS_2M   BIT(7)
+
 struct sg_table;
 
 struct intel_rotation_info {
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#22 lore raw

PATCH 14/22 drm/i915: add support for 64K scratch page

In reply to Matthew Auld

Before we can fully enable 64K pages, we need to first support a 64K scratch page if we intend to support the case where we have object sizes < 2M, since any scratch PTE must also point to a 64K region. Without this our 64K usage is limited to objects which completely fill the page-table, and therefore don't need any scratch.

v2: add reminder about why 48b PPGTT

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 64 ++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/i915_gem_gtt.h |  1 +
 2 files changed, 54 insertions(+), 11 deletions(-)
drivers/gpu/drm/i915/i915_gem_gtt.c +53 -11
index 51a1cdcfc693..86e9b6c3a987 100644
@@ -522,22 +522,63 @@ static void fill_page_dma_32(struct i915_address_space *vm,
 static int
 setup_scratch_page(struct i915_address_space *vm, gfp_t gfp)
 {
-	struct page *page;
+	struct page *page = NULL;
 	dma_addr_t addr;
+	int order;
 
-	page = alloc_page(gfp | __GFP_ZERO);
-	if (unlikely(!page))
-		return -ENOMEM;
+	/*
+	 * In order to utilize 64K pages for an object with a size < 2M, we will
+	 * need to support a 64K scratch page, given that every 16th entry for a
+	 * page-table operating in 64K mode must point to a properly aligned 64K
+	 * region, including any PTEs which happen to point to scratch.
+	 *
+	 * This is only relevant for the 48b PPGTT where we support
+	 * huge-gtt-pages, see also i915_vma_insert().
+	 *
+	 * TODO: we should really consider write-protecting the scratch-page and
+	 * sharing between ppgtt
+	 */
+	if (i915_vm_is_48bit(vm) &&
+	    HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) {
+		order = get_order(I915_GTT_PAGE_SIZE_64K);
+		page = alloc_pages(gfp | __GFP_ZERO, order);
+		if (page) {
+			addr = dma_map_page(vm->dma, page, 0,
+					    I915_GTT_PAGE_SIZE_64K,
+					    PCI_DMA_BIDIRECTIONAL);
+			if (unlikely(dma_mapping_error(vm->dma, addr))) {
+				__free_pages(page, order);
+				page = NULL;
+			}
 
-	addr = dma_map_page(vm->dma, page, 0, PAGE_SIZE,
-			    PCI_DMA_BIDIRECTIONAL);
-	if (unlikely(dma_mapping_error(vm->dma, addr))) {
-		__free_page(page);
-		return -ENOMEM;
+			if (!IS_ALIGNED(addr, I915_GTT_PAGE_SIZE_64K)) {
+				dma_unmap_page(vm->dma, addr,
+					       I915_GTT_PAGE_SIZE_64K,
+					       PCI_DMA_BIDIRECTIONAL);
+				__free_pages(page, order);
+				page = NULL;
+			}
+		}
+	}
+
+	if (!page) {
+		order = 0;
+		page = alloc_page(gfp | __GFP_ZERO);
+		if (unlikely(!page))
+			return -ENOMEM;
+
+		addr = dma_map_page(vm->dma, page, 0, PAGE_SIZE,
+				    PCI_DMA_BIDIRECTIONAL);
+		if (unlikely(dma_mapping_error(vm->dma, addr))) {
+			__free_page(page);
+			return -ENOMEM;
+		}
 	}
 
 	vm->scratch_page.page = page;
 	vm->scratch_page.daddr = addr;
+	vm->scratch_page.order = order;
+
 	return 0;
 }
 
@@ -545,8 +586,9 @@ static void cleanup_scratch_page(struct i915_address_space *vm)
 {
 	struct i915_page_dma *p = &vm->scratch_page;
 
-	dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-	__free_page(p->page);
+	dma_unmap_page(vm->dma, p->daddr, BIT(p->order) << PAGE_SHIFT,
+		       PCI_DMA_BIDIRECTIONAL);
+	__free_pages(p->page, p->order);
 }
 
 static struct i915_page_table *alloc_pt(struct i915_address_space *vm)
drivers/gpu/drm/i915/i915_gem_gtt.h +1 -0
index e9e66abbe532..0a31dc369c28 100644
@@ -214,6 +214,7 @@ struct i915_vma;
 
 struct i915_page_dma {
 	struct page *page;
+	int order;
 	union {
 		dma_addr_t daddr;
 
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#23 lore raw

PATCH 15/22 drm/i915: support 64K pages for the 48b PPGTT

In reply to Matthew Auld

Support inserting 64K pages into the 48b PPGTT.

v2: check for 64K scratch

v3: we should only have to re-adjust maybe_64K at every sg interval

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 31 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  7 +++++++
 2 files changed, 38 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +31 -0
index 86e9b6c3a987..5b6829990657 100644
@@ -1072,6 +1072,7 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
 		struct i915_page_directory_pointer *pdp = pdps[idx.pml4e];
 		struct i915_page_directory *pd = pdp->page_directory[idx.pdpe];
 		unsigned int page_size;
+		bool maybe_64K = false;
 		gen8_pte_t encode = pte_encode;
 		gen8_pte_t *vaddr;
 		u16 index, max;
@@ -1093,6 +1094,13 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
 			max = GEN8_PTES;
 			page_size = I915_GTT_PAGE_SIZE;
 
+			if (!index &&
+			    vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K &&
+			    IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
+			    (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) ||
+			     rem >= (max - index) << PAGE_SHIFT))
+				maybe_64K = true;
+
 			vaddr = kmap_atomic_px(pt);
 		}
 
@@ -1112,12 +1120,35 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
 				iter->dma = sg_dma_address(iter->sg);
 				iter->max = iter->dma + rem;
 
+				if (maybe_64K && index < max &&
+				    !(IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
+				      (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) ||
+				       rem >= (max - index) << PAGE_SHIFT)))
+					maybe_64K = false;
+
 				if (unlikely(!IS_ALIGNED(iter->dma, page_size)))
 					break;
 			}
 		} while (rem >= page_size && index < max);
 
 		kunmap_atomic(vaddr);
+
+		/*
+		 * Is it safe to mark the 2M block as 64K? -- Either we have
+		 * filled whole page-table with 64K entries, or filled part of
+		 * it and have reached the end of the sg table and we have
+		 * enough padding.
+		 */
+		if (maybe_64K &&
+		    (index == max ||
+		     (i915_vm_has_scratch_64K(vma->vm) &&
+		      !iter->sg && IS_ALIGNED(vma->node.start +
+					      vma->node.size,
+					      I915_GTT_PAGE_SIZE_2M)))) {
+			vaddr = kmap_atomic_px(pd);
+			vaddr[idx.pde] |= GEN8_PDE_IPS_64K;
+			kunmap_atomic(vaddr);
+		}
 	} while (iter->sg);
 }
 
drivers/gpu/drm/i915/i915_gem_gtt.h +7 -0
index 0a31dc369c28..475e4cf042be 100644
@@ -153,6 +153,7 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT_GET_AGE(x) ((x) & (3 << 4))
 #define CHV_PPAT_GET_SNOOP(x) ((x) & (1 << 6))
 
+#define GEN8_PDE_IPS_64K BIT(11)
 #define GEN8_PDE_PS_2M   BIT(7)
 
 struct sg_table;
@@ -351,6 +352,12 @@ i915_vm_is_48bit(const struct i915_address_space *vm)
 	return (vm->total - 1) >> 32;
 }
 
+static inline bool
+i915_vm_has_scratch_64K(struct i915_address_space *vm)
+{
+	return vm->scratch_page.order == get_order(I915_GTT_PAGE_SIZE_64K);
+}
+
 /* The Graphics Translation Table is the way in which GEN hardware translates a
  * Graphics Virtual Address into a Physical Address. In addition to the normal
  * collateral associated with any va->pa translations GEN hardware also has a
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#24 lore raw

PATCH 16/22 drm/i915: accurate page size tracking for the ppgtt

In reply to Matthew Auld

Now that we support multiple page sizes for the ppgtt, it would be useful to track the real usage for debugging purposes.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c    | 11 +++++++++++
 drivers/gpu/drm/i915/i915_gem_object.h | 10 ++++++++++
 2 files changed, 21 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +11 -0
index 5b6829990657..c625f665388c 100644
@@ -1056,6 +1056,8 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
 
 	gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx,
 				      cache_level);
+
+	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 }
 
 static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
@@ -1148,7 +1150,10 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma,
 			vaddr = kmap_atomic_px(pd);
 			vaddr[idx.pde] |= GEN8_PDE_IPS_64K;
 			kunmap_atomic(vaddr);
+			page_size = I915_GTT_PAGE_SIZE_64K;
 		}
+
+		vma->page_sizes.gtt |= page_size;
 	} while (iter->sg);
 }
 
@@ -1173,6 +1178,8 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 		while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++],
 						     &iter, &idx, cache_level))
 			GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
+
+		vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 	}
 }
 
@@ -1894,6 +1901,8 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 		}
 	} while (1);
 	kunmap_atomic(vaddr);
+
+	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 }
 
 static int gen6_alloc_va_range(struct i915_address_space *vm,
@@ -2584,6 +2593,8 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
 	intel_runtime_pm_put(i915);
 
+	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
+
 	/*
 	 * Without aliasing PPGTT there's no difference between
 	 * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
drivers/gpu/drm/i915/i915_gem_object.h +10 -0
index 110672952a1c..e4e6dd93889d 100644
@@ -169,6 +169,7 @@ struct drm_i915_gem_object {
 		struct sg_table *pages;
 		void *mapping;
 
+		/* TODO: whack some of this into the error state */
 		struct i915_page_sizes {
 			/**
 			 * The sg mask of the pages sg_table. i.e the mask of
@@ -184,6 +185,15 @@ struct drm_i915_gem_object {
 			 * to use opportunistically.
 			 */
 			unsigned int sg;
+
+			/**
+			 * The actual gtt page size usage. Since we can have
+			 * multiple vma associated with this object we need to
+			 * prevent any trampling of state, hence a copy of this
+			 * struct also lives in each vma, therefore the gtt
+			 * value here should only be read/write through the vma.
+			 */
+			unsigned int gtt;
 		} page_sizes;
 
 		struct i915_gem_object_page_iter {
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#25 lore raw

PATCH 17/22 drm/i915/debugfs: include some gtt page size metrics

In reply to Matthew Auld

Good to know, mostly for debugging purposes.

v2: some improvements from Chris

---
 drivers/gpu/drm/i915/i915_debugfs.c | 61 ++++++++++++++++++++++++++++++++++---
 1 file changed, 57 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_debugfs.c +57 -4
index 847f8e8d6b58..27a0403d3a23 100644
@@ -118,6 +118,36 @@ static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj)
 	return size;
 }
 
+static const char *
+stringify_page_sizes(unsigned int page_sizes, char *buf, size_t len)
+{
+	size_t x = 0;
+
+	switch (page_sizes) {
+	case 0:
+		return "";
+	case I915_GTT_PAGE_SIZE_4K:
+		return "4K";
+	case I915_GTT_PAGE_SIZE_64K:
+		return "64K";
+	case I915_GTT_PAGE_SIZE_2M:
+		return "2M";
+	default:
+		if (!buf)
+			return "M";
+
+		if (page_sizes & I915_GTT_PAGE_SIZE_2M)
+			x += snprintf(buf + x, len - x, "2M, ");
+		if (page_sizes & I915_GTT_PAGE_SIZE_64K)
+			x += snprintf(buf + x, len - x, "64K, ");
+		if (page_sizes & I915_GTT_PAGE_SIZE_4K)
+			x += snprintf(buf + x, len - x, "4K, ");
+		buf[x-2] = '\0';
+
+		return buf;
+	}
+}
+
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
@@ -155,9 +185,10 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 		if (!drm_mm_node_allocated(&vma->node))
 			continue;
 
-		seq_printf(m, " (%sgtt offset: %08llx, size: %08llx",
+		seq_printf(m, " (%sgtt offset: %08llx, size: %08llx, pages: %s",
 			   i915_vma_is_ggtt(vma) ? "g" : "pp",
-			   vma->node.start, vma->node.size);
+			   vma->node.start, vma->node.size,
+			   stringify_page_sizes(vma->page_sizes.gtt, NULL, 0));
 		if (i915_vma_is_ggtt(vma)) {
 			switch (vma->ggtt_view.type) {
 			case I915_GGTT_VIEW_NORMAL:
@@ -402,10 +433,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct drm_device *dev = &dev_priv->drm;
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	u32 count, mapped_count, purgeable_count, dpy_count;
-	u64 size, mapped_size, purgeable_size, dpy_size;
+	u32 count, mapped_count, purgeable_count, dpy_count, huge_count;
+	u64 size, mapped_size, purgeable_size, dpy_size, huge_size;
 	struct drm_i915_gem_object *obj;
+	unsigned int page_sizes = 0;
 	struct drm_file *file;
+	char buf[80];
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -419,6 +452,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 	size = count = 0;
 	mapped_size = mapped_count = 0;
 	purgeable_size = purgeable_count = 0;
+	huge_size = huge_count = 0;
 	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
 		size += obj->base.size;
 		++count;
@@ -432,6 +466,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
+
+		if (obj->mm.page_sizes.sg > I915_GTT_PAGE_SIZE) {
+			huge_count++;
+			huge_size += obj->base.size;
+			page_sizes |= obj->mm.page_sizes.sg;
+		}
 	}
 	seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
 
@@ -454,6 +494,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
+
+		if (obj->mm.page_sizes.sg > I915_GTT_PAGE_SIZE) {
+			huge_count++;
+			huge_size += obj->base.size;
+			page_sizes |= obj->mm.page_sizes.sg;
+		}
 	}
 	seq_printf(m, "%u bound objects, %llu bytes\n",
 		   count, size);
@@ -461,11 +507,18 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 		   purgeable_count, purgeable_size);
 	seq_printf(m, "%u mapped objects, %llu bytes\n",
 		   mapped_count, mapped_size);
+	seq_printf(m, "%u huge-paged objects (%s) %llu bytes\n",
+		   huge_count,
+		   stringify_page_sizes(page_sizes, buf, sizeof(buf)),
+		   huge_size);
 	seq_printf(m, "%u display objects (pinned), %llu bytes\n",
 		   dpy_count, dpy_size);
 
 	seq_printf(m, "%llu [%llu] gtt total\n",
 		   ggtt->base.total, ggtt->mappable_end);
+	seq_printf(m, "Supported page sizes: %s\n",
+		   stringify_page_sizes(INTEL_INFO(dev_priv)->page_sizes,
+					buf, sizeof(buf)));
 
 	seq_putc(m, '\n');
 	print_batch_pool_stats(m, dev_priv);
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#26 lore raw

PATCH 18/22 drm/i915/selftests: huge page tests

In reply to Matthew Auld

v2: mock test page support configurations and add MI_STORE_DWORD test

v3: run all mockable huge page tests on all platforms via the mock_device

v4: add pin_update regression test
various improvements suggested by Chris

v5: fix issues reported by kbuild
test single sg spanning multiple page sizes
don't explode when running the live-tests through the appgtt

v6: lots of improvements from Chris

v7: run on each engine for igt_write_huge
add simple tmpfs fallback test

Cc Joonas Lahtinen <[email protected]>
Cc Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_gem.c                    |    1 +
 drivers/gpu/drm/i915/i915_gem_object.h             |    2 +
 drivers/gpu/drm/i915/selftests/huge_pages.c        | 1687 ++++++++++++++++++++
 .../gpu/drm/i915/selftests/i915_live_selftests.h   |    1 +
 .../gpu/drm/i915/selftests/i915_mock_selftests.h   |    1 +
 5 files changed, 1692 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/selftests/huge_pages.c
drivers/gpu/drm/i915/i915_gem.c +1 -0
index 11b287d53315..e0087f180f26 100644
@@ -5417,6 +5417,7 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
 #include "selftests/scatterlist.c"
 #include "selftests/mock_gem_device.c"
 #include "selftests/huge_gem_object.c"
+#include "selftests/huge_pages.c"
 #include "selftests/i915_gem_object.c"
 #include "selftests/i915_gem_coherency.c"
 #endif
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
index e4e6dd93889d..956c911c2cbf 100644
@@ -196,6 +196,8 @@ struct drm_i915_gem_object {
 			unsigned int gtt;
 		} page_sizes;
 
+		I915_SELFTEST_DECLARE(unsigned int page_mask);
+
 		struct i915_gem_object_page_iter {
 			struct scatterlist *sg_pos;
 			unsigned int sg_idx; /* in pages, but 32bit eek! */
drivers/gpu/drm/i915/selftests/huge_pages.c new file +1687 -0

1,687 lines not on this page · raw message

drivers/gpu/drm/i915/selftests/i915_live_selftests.h +1 -0
index 18b174d855ca..64acd7eccc5c 100644
@@ -15,5 +15,6 @@ selftest(objects, i915_gem_object_live_selftests)
 selftest(dmabuf, i915_gem_dmabuf_live_selftests)
 selftest(coherency, i915_gem_coherency_live_selftests)
 selftest(gtt, i915_gem_gtt_live_selftests)
+selftest(hugepages, i915_gem_huge_page_live_selftests)
 selftest(contexts, i915_gem_context_live_selftests)
 selftest(hangcheck, intel_hangcheck_live_selftests)
drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +1 -0
index fc74687501ba..9961b44f76ed 100644
@@ -21,3 +21,4 @@ selftest(dmabuf, i915_gem_dmabuf_mock_selftests)
 selftest(vma, i915_vma_mock_selftests)
 selftest(evict, i915_gem_evict_mock_selftests)
 selftest(gtt, i915_gem_gtt_mock_selftests)
+selftest(hugepages, i915_gem_huge_page_mock_selftests)
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#27 lore raw

Re: [PATCH 18/22] drm/i915/selftests: huge page tests

Quoting Matthew Auld (2017-09-25 19:47:33)

Quoted 23 lines
drivers/gpu/drm/i915/selftests/huge_pages.c new file +23 -0
+static int igt_tmpfs_fallback(void *arg)
+{
+       struct drm_i915_private *i915 = arg;
+       struct vfsmount *gemfs = i915->mm.gemfs;
+       struct drm_i915_gem_object *obj;
+       int err = 0;
+
+       /*
+        * Make sure that we don't burst into a ball of flames upon falling back
+        * to tmpfs, which we rely on if on the off-chance we encouter a failure
+        * when setting up gemfs.
+        */
+
+       i915->mm.gemfs = NULL;
+
+       obj = i915_gem_object_create(i915, PAGE_SIZE);
+       if (IS_ERR(obj)) {
+               err = PTR_ERR(obj);
+               goto out_restore;
+       }
+
+       err = i915_gem_object_pin_pages(obj);
+       if (err)

drivers/gpu/drm/i915/selftests/huge_pages.c line 1521

Quoted 10 lines
drivers/gpu/drm/i915/selftests/huge_pages.c new file +10 -0
+               goto out_put;
+
+       i915_gem_object_unpin_pages(obj);
+out_put:
+       i915_gem_object_put(obj);
+out_restore:
+       i915->mm.gemfs = gemfs;
+
+       return err;
+}

Very sensible! Do a vaddr = pin_map(); *vaddr; unpin_map() in the middle (instead of just pin_pages). Could do with a vma_bind as well to check that dma_map_sg() is also happy.
-Chris
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

author reviewer
#28 lore raw

PATCH 19/22 drm/i915/selftests: mix huge pages

In reply to Matthew Auld

Try to mix sg page sizes for 4K, 64K and 2M pages.

v2: s/BIT(x) >> 12/BIT(x) >> PAGE_SHIFT/

---
 drivers/gpu/drm/i915/selftests/scatterlist.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/gpu/drm/i915/selftests/scatterlist.c +15 -0
index 1cc5d2931753..cd6d2a16071f 100644
@@ -189,6 +189,20 @@ static unsigned int random(unsigned long n,
 	return 1 + (prandom_u32_state(rnd) % 1024);
 }
 
+static unsigned int random_page_size_pages(unsigned long n,
+					   unsigned long count,
+					   struct rnd_state *rnd)
+{
+	/* 4K, 64K, 2M */
+	static unsigned int page_count[] = {
+		BIT(12) >> PAGE_SHIFT,
+		BIT(16) >> PAGE_SHIFT,
+		BIT(21) >> PAGE_SHIFT,
+	};
+
+	return page_count[(prandom_u32_state(rnd) % 3)];
+}
+
 static inline bool page_contiguous(struct page *first,
 				   struct page *last,
 				   unsigned long npages)
@@ -252,6 +266,7 @@ static const npages_fn_t npages_funcs[] = {
 	grow,
 	shrink,
 	random,
+	random_page_size_pages,
 	NULL,
 };
 
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#29 lore raw

PATCH 20/22 drm/i915: disable platform support for vGPU huge gtt pages

In reply to Matthew Auld

Currently gvt gtt handling doesn't support huge page entries, so disable for now.

v2: remove useless 48b PPGTT check

---
 drivers/gpu/drm/i915/i915_gem.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +9 -0
index e0087f180f26..518c8703f4a9 100644
@@ -4828,6 +4828,15 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
 
 	mutex_lock(&dev_priv->drm.struct_mutex);
 
+	/*
+	 * We need to fallback to 4K pages since gvt gtt handling doesn't
+	 * support huge page entries - we will need to check either hypervisor
+	 * mm can support huge guest page or just do emulation in gvt.
+	 */
+	if (intel_vgpu_active(dev_priv))
+		mkwrite_device_info(dev_priv)->page_sizes =
+			I915_GTT_PAGE_SIZE_4K;
+
 	dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1);
 
 	if (!i915_modparams.enable_execlists) {
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#30 lore raw

PATCH 21/22 drm/i915: enable platform support for 64K pages

In reply to Matthew Auld

For gen9+ enable platform level support for 64K pages. Also enable for mock testing.

---
 drivers/gpu/drm/i915/i915_pci.c                  | 3 ++-
 drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_pci.c +2 -1
index 84cdab3c5f09..9da69cb55302 100644
@@ -434,7 +434,8 @@ static const struct intel_device_info intel_cherryview_info __initconst = {
 };
 
 #define GEN9_DEFAULT_PAGE_SIZES \
-	.page_sizes = I915_GTT_PAGE_SIZE_4K
+	.page_sizes = I915_GTT_PAGE_SIZE_4K | \
+		      I915_GTT_PAGE_SIZE_64K
 
 #define SKL_PLATFORM \
 	BDW_FEATURES, \
drivers/gpu/drm/i915/selftests/mock_gem_device.c +2 -1
index 1785c63ad797..8a5a42ea1c98 100644
@@ -175,7 +175,8 @@ struct drm_i915_private *mock_gem_device(void)
 	mkwrite_device_info(i915)->gen = -1;
 
 	mkwrite_device_info(i915)->page_sizes =
-		I915_GTT_PAGE_SIZE_4K;
+		I915_GTT_PAGE_SIZE_4K |
+		I915_GTT_PAGE_SIZE_64K;
 
 	spin_lock_init(&i915->mm.object_stat_lock);
 	mock_uncore_init(i915);
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
author reviewer
#31 lore raw

PATCH 22/22 drm/i915: enable platform support for 2M pages

In reply to Matthew Auld

For gen8+ platforms which support the 48b PPGTT, enable platform level support for 2M pages. Also enable for mock testing.

---
 drivers/gpu/drm/i915/i915_pci.c                  | 6 ++++--
 drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_pci.c +4 -2
index 9da69cb55302..ad07f7075f29 100644
@@ -374,7 +374,8 @@ static const struct intel_device_info intel_haswell_gt3_info __initconst = {
 #define BDW_FEATURES \
 	HSW_FEATURES, \
 	BDW_COLORS, \
-	GEN_DEFAULT_PAGE_SIZES, \
+	.page_sizes = I915_GTT_PAGE_SIZE_4K | \
+		      I915_GTT_PAGE_SIZE_2M, \
 	.has_logical_ring_contexts = 1, \
 	.has_full_48bit_ppgtt = 1, \
 	.has_64bit_reloc = 1, \
@@ -435,7 +436,8 @@ static const struct intel_device_info intel_cherryview_info __initconst = {
 
 #define GEN9_DEFAULT_PAGE_SIZES \
 	.page_sizes = I915_GTT_PAGE_SIZE_4K | \
-		      I915_GTT_PAGE_SIZE_64K
+		      I915_GTT_PAGE_SIZE_64K | \
+		      I915_GTT_PAGE_SIZE_2M
 
 #define SKL_PLATFORM \
 	BDW_FEATURES, \
drivers/gpu/drm/i915/selftests/mock_gem_device.c +2 -1
index 8a5a42ea1c98..39556a5979d4 100644
@@ -176,7 +176,8 @@ struct drm_i915_private *mock_gem_device(void)
 
 	mkwrite_device_info(i915)->page_sizes =
 		I915_GTT_PAGE_SIZE_4K |
-		I915_GTT_PAGE_SIZE_64K;
+		I915_GTT_PAGE_SIZE_64K |
+		I915_GTT_PAGE_SIZE_2M;
 
 	spin_lock_init(&i915->mm.object_stat_lock);
 	mock_uncore_init(i915);
Signature · 6 lines
2.13.5

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#32 lore raw

✓ Fi.CI.BAT: success for huge gtt pages (rev9)

In reply to Matthew Auld
== Series Details ==

== Series Details ==

Series: huge gtt pages (rev9)
URL : https://patchwork.freedesktop.org/series/25118/
State : success

== Summary ==

Series 25118v9 huge gtt pages
https://patchwork.freedesktop.org/api/1.0/series/25118/revisions/9/mbox/

Test chamelium:

        Subgroup dp-crc-fast:
                pass       -> DMESG-FAIL (fi-kbl-7500u) fdo#102514
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-b:
                dmesg-warn -> PASS       (fi-skl-6770hq)

fdo#102514 https://bugs.freedesktop.org/show_bug.cgi?id=102514

fi-bdw-5557u     total:289  pass:268  dwarn:0   dfail:0   fail:0   skip:21  time:439s
fi-bdw-gvtdvm    total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:466s
fi-blb-e6850     total:289  pass:224  dwarn:1   dfail:0   fail:0   skip:64  time:418s
fi-bsw-n3050     total:289  pass:243  dwarn:0   dfail:0   fail:0   skip:46  time:508s
fi-bwr-2160      total:289  pass:184  dwarn:0   dfail:0   fail:0   skip:105 time:274s
fi-bxt-j4205     total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:501s
fi-byt-j1900     total:289  pass:254  dwarn:1   dfail:0   fail:0   skip:34  time:483s
fi-byt-n2820     total:289  pass:250  dwarn:1   dfail:0   fail:0   skip:38  time:489s
fi-cfl-s         total:289  pass:222  dwarn:35  dfail:0   fail:0   skip:32  time:533s
fi-cnl-y         total:289  pass:256  dwarn:0   dfail:0   fail:6   skip:27  time:630s
fi-elk-e7500     total:289  pass:230  dwarn:0   dfail:0   fail:0   skip:59  time:418s
fi-glk-1         total:289  pass:260  dwarn:0   dfail:0   fail:0   skip:29  time:559s
fi-hsw-4770      total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:419s
fi-hsw-4770r     total:289  pass:263  dwarn:0   dfail:0   fail:0   skip:26  time:403s
fi-ilk-650       total:289  pass:229  dwarn:0   dfail:0   fail:0   skip:60  time:426s
fi-ivb-3520m     total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:491s
fi-ivb-3770      total:289  pass:261  dwarn:0   dfail:0   fail:0   skip:28  time:467s
fi-kbl-7500u     total:289  pass:263  dwarn:1   dfail:1   fail:0   skip:24  time:467s
fi-kbl-7560u     total:289  pass:270  dwarn:0   dfail:0   fail:0   skip:19  time:571s
fi-kbl-r         total:289  pass:262  dwarn:0   dfail:0   fail:0   skip:27  time:587s
fi-pnv-d510      total:289  pass:223  dwarn:1   dfail:0   fail:0   skip:65  time:539s
fi-skl-6260u     total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:453s
fi-skl-6700k     total:289  pass:265  dwarn:0   dfail:0   fail:0   skip:24  time:747s
fi-skl-6770hq    total:289  pass:269  dwarn:0   dfail:0   fail:0   skip:20  time:485s
fi-skl-gvtdvm    total:289  pass:266  dwarn:0   dfail:0   fail:0   skip:23  time:472s
fi-snb-2520m     total:289  pass:251  dwarn:0   dfail:0   fail:0   skip:38  time:570s
fi-snb-2600      total:289  pass:250  dwarn:0   dfail:0   fail:0   skip:39  time:420s

0b65077382608db179cb5afafecf4a0edd35c2fe drm-tip: 2017y-09m-25d-13h-55m-18s UTC integration manifest 578b8f99b758 drm/i915: enable platform support for 2M pages
df4bb0d6aab9 drm/i915: enable platform support for 64K pages
11f6d9c46589 drm/i915: disable platform support for vGPU huge gtt pages
cc3977e202f5 drm/i915/selftests: mix huge pages
bcd61b9f77f9 drm/i915/selftests: huge page tests
8c8a41908fcd drm/i915/debugfs: include some gtt page size metrics
d31d8a7687d2 drm/i915: accurate page size tracking for the ppgtt
83b6fed82319 drm/i915: support 64K pages for the 48b PPGTT
304b39536f18 drm/i915: add support for 64K scratch page
4def0c15e165 drm/i915: support 2M pages for the 48b PPGTT
fe7848ded3cd drm/i915: disable GTT cache for 2M pages
86a240c4790f drm/i915: enable IPS bit for 64K pages
b06a1702687f drm/i915: align 64K objects to 2M
202ad27f224a drm/i915: align the vma start to the largest gtt page size
56c17dcaf53b drm/i915: introduce vm set_pages/clear_pages
91f3f6ac7e9f drm/i915: introduce page_size members
4f07ce353b33 drm/i915: push set_pages down to the callers
f28cc29a97eb drm/i915: introduce page_sizes field to dev_info
1dbe5bd39a37 drm/i915/gemfs: enable THP
b052a23724c7 mm/shmem: parse mount options for MS_KERNMOUNT
e6702be68524 drm/i915: introduce simple gemfs
5b9af30c698d mm/shmem: support passing mnt to shmem_file_setup

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5808/
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#33 lore raw

✓ Fi.CI.IGT: success for huge gtt pages (rev9)

In reply to Matthew Auld
== Series Details ==

== Series Details ==

Series: huge gtt pages (rev9)
URL : https://patchwork.freedesktop.org/series/25118/
State : success

== Summary ==

Test kms_setmode:

        Subgroup basic:
                fail       -> PASS       (shard-hsw) fdo#99912
Test perf:
        Subgroup polling:
                pass       -> FAIL       (shard-hsw) fdo#102252

fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
fdo#102252 https://bugs.freedesktop.org/show_bug.cgi?id=102252

shard-hsw total:2429 pass:1325 dwarn:5 dfail:0 fail:16 skip:1083 time:9858s

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_5808/shards.html
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx