Skip to contentSkip to conversation

drm/i915: initial support for huge gtt pages V2

RFC PATCH In review Matthew Auld 6 participants 42 messages Apr 4, 2017 – Apr 10, 2017

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover drm/i915: initial support for huge gtt pages V2

Same as before, folding in review comments. Notably we now hook in transparent huge pages through by shmem, and *attempt* to deal with all the fun which that brings. Again should be considered very much RFC.

So far I have only gone as far as testing 2M pages on my BDW machine.

Thanks,
Matt

Matthew Auld (18):
drm/i915: add page_size_mask to dev_info
drm/i915: introduce drm_i915_gem_object page_size members drm/i915: pass page_size to insert_entries
drm/i915: s/i915_gtt_color_adjust/i915_ggtt_color_adjust drm/i915: clean up cache coloring
drm/i915: export color_differs
drm/i915: introduce ppgtt page coloring
drm/i915: handle evict-for-node with page coloring drm/i915: support inserting 64K pages in the ppgtt drm/i915: support inserting 2M pages in the ppgtt drm/i915: support inserting 1G pages in the ppgtt drm/i915: disable GTT cache for huge-pages drm/i915/selftests: exercise 4K and 64K mm insertion drm/i915/selftests: modify the gtt tests to also exercise huge pages drm/i915/selftests: exercise evict-for-node page coloring drm/i915/debugfs: include some huge-page metrics mm/shmem: tweak the huge-page interface
drm/i915: support transparent-huge-pages through shmemfs

 drivers/gpu/drm/i915/i915_debugfs.c             |  38 +++-
 drivers/gpu/drm/i915/i915_drv.h                 |   8 +-
 drivers/gpu/drm/i915/i915_gem.c                 | 195 ++++++++++++++++----
 drivers/gpu/drm/i915/i915_gem_evict.c           |  36 +++-
 drivers/gpu/drm/i915/i915_gem_gtt.c             | 236 ++++++++++++++++++++++--
 drivers/gpu/drm/i915/i915_gem_gtt.h             |  35 +++-
 drivers/gpu/drm/i915/i915_gem_object.h          |   3 +
 drivers/gpu/drm/i915/i915_pci.c                 |  23 ++-
 drivers/gpu/drm/i915/i915_vma.c                 |  32 +++-
 drivers/gpu/drm/i915/i915_vma.h                 |   6 +
 drivers/gpu/drm/i915/intel_pm.c                 |  12 +-
 drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 125 ++++++++++++-
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c   | 194 +++++++++++++++----
 drivers/gpu/drm/i915/selftests/mock_gtt.c       |   4 +
 include/linux/shmem_fs.h                        |   1 +
 mm/shmem.c                                      |  10 +-
 16 files changed, 836 insertions(+), 122 deletions(-)
Signature · 6 lines
2.9.3

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

PATCH 1/18 drm/i915: add page_size_mask to dev_info

v2:
- move out pde/pdpe bit definitions until later
- tidyup the page size definitions, use BIT
- introduce helper for detecting invalid page sizes

Cc Mika Kuoppala <[email protected]>
Cc Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_drv.h     |  3 +++
 drivers/gpu/drm/i915/i915_gem_gtt.h | 17 ++++++++++++++++-
 drivers/gpu/drm/i915/i915_pci.c     | 23 ++++++++++++++++++++++-
 3 files changed, 41 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +3 -0
index c9b0949f6c1a..ab7a1072e7b5 100644
@@ -901,6 +901,7 @@ struct intel_device_info {
 	enum intel_platform platform;
 	u8 ring_mask; /* Rings supported by the HW */
 	u8 num_rings;
+	unsigned int page_size_mask; /* page sizes supported by the HW */
 #define DEFINE_FLAG(name) u8 name:1
 	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
 #undef DEFINE_FLAG
@@ -2876,6 +2877,8 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define USES_PPGTT(dev_priv)		(i915.enable_ppgtt)
 #define USES_FULL_PPGTT(dev_priv)	(i915.enable_ppgtt >= 2)
 #define USES_FULL_48BIT_PPGTT(dev_priv)	(i915.enable_ppgtt == 3)
+#define SUPPORTS_PAGE_SIZE(dev_priv, page_size) \
+	((dev_priv)->info.page_size_mask & (page_size))
 
 #define HAS_OVERLAY(dev_priv)		 ((dev_priv)->info.has_overlay)
 #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
drivers/gpu/drm/i915/i915_gem_gtt.h +16 -1
index fb15684c1d83..27b2b9e681db 100644
@@ -42,7 +42,22 @@
 #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_1G BIT(30)
+
+#define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K
+
+#define I915_GTT_PAGE_SIZE_MASK (I915_GTT_PAGE_SIZE_4K | \
+				 I915_GTT_PAGE_SIZE_64K | \
+				 I915_GTT_PAGE_SIZE_2M | \
+				 I915_GTT_PAGE_SIZE_1G)
+
+#define is_valid_gtt_page_size(page_size) \
+	(is_power_of_2(page_size) && \
+	 (page_size) & I915_GTT_PAGE_SIZE_MASK)
+
 #define I915_GTT_MIN_ALIGNMENT I915_GTT_PAGE_SIZE
 
 #define I915_FENCE_REG_NONE -1
drivers/gpu/drm/i915/i915_pci.c +22 -1
index f87b0c4e564d..25de64dfe732 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_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K
+
 #define GEN2_FEATURES \
 	.gen = 2, .num_pipes = 1, \
 	.has_overlay = 1, .overlay_needs_physical = 1, \
@@ -64,6 +68,7 @@
 	.unfenced_needs_alignment = 1, \
 	.ring_mask = RENDER_RING, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i830_info = {
@@ -96,6 +101,7 @@ static const struct intel_device_info intel_i865g_info = {
 	.has_gmch_display = 1, \
 	.ring_mask = RENDER_RING, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i915g_info = {
@@ -158,6 +164,7 @@ static const struct intel_device_info intel_pineview_info = {
 	.has_gmch_display = 1, \
 	.ring_mask = RENDER_RING, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_i965g_info = {
@@ -198,6 +205,7 @@ static const struct intel_device_info intel_gm45_info = {
 	.has_gmbus_irq = 1, \
 	.ring_mask = RENDER_RING | BSD_RING, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_ironlake_d_info = {
@@ -223,6 +231,7 @@ static const struct intel_device_info intel_ironlake_m_info = {
 	.has_hw_contexts = 1, \
 	.has_aliasing_ppgtt = 1, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	CURSOR_OFFSETS
 
 static const struct intel_device_info intel_sandybridge_d_info = {
@@ -249,6 +258,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 	.has_aliasing_ppgtt = 1, \
 	.has_full_ppgtt = 1, \
 	GEN_DEFAULT_PIPEOFFSETS, \
+	GEN_DEFAULT_PAGE_SZ, \
 	IVB_CURSOR_OFFSETS
 
 static const struct intel_device_info intel_ivybridge_d_info = {
@@ -287,6 +297,7 @@ static const struct intel_device_info intel_valleyview_info = {
 	.has_full_ppgtt = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
+	GEN_DEFAULT_PAGE_SZ,
 	GEN_DEFAULT_PIPEOFFSETS,
 	CURSOR_OFFSETS
 };
@@ -313,7 +324,8 @@ static const struct intel_device_info intel_haswell_info = {
 	BDW_COLORS, \
 	.has_logical_ring_contexts = 1, \
 	.has_full_48bit_ppgtt = 1, \
-	.has_64bit_reloc = 1
+	.has_64bit_reloc = 1, \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G
 
 static const struct intel_device_info intel_broadwell_info = {
 	BDW_FEATURES,
@@ -346,13 +358,18 @@ static const struct intel_device_info intel_cherryview_info = {
 	.has_aliasing_ppgtt = 1,
 	.has_full_ppgtt = 1,
 	.display_mmio_offset = VLV_DISPLAY_BASE,
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G,
 	GEN_CHV_PIPEOFFSETS,
 	CURSOR_OFFSETS,
 	CHV_COLORS,
 };
 
+#define GEN9_DEFAULT_PAGE_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G
+
 static const struct intel_device_info intel_skylake_info = {
 	BDW_FEATURES,
+	GEN9_DEFAULT_PAGE_SZ,
 	.platform = INTEL_SKYLAKE,
 	.gen = 9,
 	.has_csr = 1,
@@ -362,6 +379,7 @@ static const struct intel_device_info intel_skylake_info = {
 
 static const struct intel_device_info intel_skylake_gt3_info = {
 	BDW_FEATURES,
+	GEN9_DEFAULT_PAGE_SZ,
 	.platform = INTEL_SKYLAKE,
 	.gen = 9,
 	.has_csr = 1,
@@ -394,6 +412,7 @@ static const struct intel_device_info intel_skylake_gt3_info = {
 	.has_aliasing_ppgtt = 1, \
 	.has_full_ppgtt = 1, \
 	.has_full_48bit_ppgtt = 1, \
+	GEN9_DEFAULT_PAGE_SZ, \
 	GEN_DEFAULT_PIPEOFFSETS, \
 	IVB_CURSOR_OFFSETS, \
 	BDW_COLORS
@@ -414,6 +433,7 @@ static const struct intel_device_info intel_geminilake_info = {
 
 static const struct intel_device_info intel_kabylake_info = {
 	BDW_FEATURES,
+	GEN9_DEFAULT_PAGE_SZ,
 	.platform = INTEL_KABYLAKE,
 	.gen = 9,
 	.has_csr = 1,
@@ -423,6 +443,7 @@ static const struct intel_device_info intel_kabylake_info = {
 
 static const struct intel_device_info intel_kabylake_gt3_info = {
 	BDW_FEATURES,
+	GEN9_DEFAULT_PAGE_SZ,
 	.platform = INTEL_KABYLAKE,
 	.gen = 9,
 	.has_csr = 1,
Signature · 6 lines
2.9.3

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

Re: [PATCH 01/18] drm/i915: add page_size_mask to dev_info

Add commit message.

Quoted 8 lines · Matthew Auld

v2:
  - move out pde/pdpe bit definitions until later
  - tidyup the page size definitions, use BIT
  - introduce helper for detecting invalid page sizes

Cc Mika Kuoppala <[email protected]>
Cc Chris Wilson <[email protected]>

<SNIP>

drivers/gpu/drm/i915/i915_drv.h intel_info(const struct drm_i915_private *dev_priv) · line 2881

Quoted 6 lines
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -2876,6 +2877,8 @@ intel_info(const struct drm_i915_private *dev_priv)
  #define USES_PPGTT(dev_priv)		(i915.enable_ppgtt)
  #define USES_FULL_PPGTT(dev_priv)	(i915.enable_ppgtt >= 2)
  #define USES_FULL_48BIT_PPGTT(dev_priv)	(i915.enable_ppgtt == 3)
+#define SUPPORTS_PAGE_SIZE(dev_priv, page_size) \
+	((dev_priv)->info.page_size_mask & (page_size))

Why not HAS_PAGE_SIZE()?

drivers/gpu/drm/i915/i915_gem_gtt.h line 59

Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_gtt.h +3 -0
+#define is_valid_gtt_page_size(page_size) \
+	(is_power_of_2(page_size) && \
+	 (page_size) & I915_GTT_PAGE_SIZE_MASK)

When would this matter? I'd assume we always gotta rely on device info.

drivers/gpu/drm/i915/i915_pci.c line 61

Quoted 8 lines
drivers/gpu/drm/i915/i915_pci.c +1 -0
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -56,6 +56,10 @@
  	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }


 /* Keep in gen based order, and chronological order within a gen */

drivers/gpu/drm/i915/i915_pci.c +3 -0
+
+#define GEN_DEFAULT_PAGE_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K

GEN_DEFAULT_PAGE_SIZES

drivers/gpu/drm/i915/i915_pci.c static const struct intel_device_info intel_cherryview_info = { · line 361

Quoted 5 lines
drivers/gpu/drm/i915/i915_pci.c +1 -0
@@ -346,13 +358,18 @@ static const struct intel_device_info intel_cherryview_info = {
  	.has_aliasing_ppgtt = 1,
  	.has_full_ppgtt = 1,
  	.display_mmio_offset = VLV_DISPLAY_BASE,
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G,

Split long line.

drivers/gpu/drm/i915/i915_pci.c static const struct intel_device_info intel_cherryview_info = { · line 368

Quoted 7 lines
drivers/gpu/drm/i915/i915_pci.c +0 -0
  	GEN_CHV_PIPEOFFSETS,
  	CURSOR_OFFSETS,
 >  	CHV_COLORS,
  };

drivers/gpu/drm/i915/i915_pci.c +2 -0
+#define GEN9_DEFAULT_PAGE_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G

GEN9_DEFAULT_PAGE_SIZES, also split long line.

With above,

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
#3 lore raw

Re: [PATCH 01/18] drm/i915: add page_size_mask to dev_info

Quoted 22 lines · Joonas Lahtinen

drivers/gpu/drm/i915/i915_pci.c line 61

Quoted 8 lines · Matthew Auld

+++ b/drivers/gpu/drm/i915/i915_pci.c

drivers/gpu/drm/i915/i915_pci.c +0 -0
@@ -56,6 +56,10 @@
  	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }


 /* Keep in gen based order, and chronological order within a gen */

drivers/gpu/drm/i915/i915_pci.c +3 -0
+
+#define GEN_DEFAULT_PAGE_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K

GEN_DEFAULT_PAGE_SIZES

drivers/gpu/drm/i915/i915_pci.c static const struct intel_device_info intel_cherryview_info = { · line 361

Quoted 5 lines
drivers/gpu/drm/i915/i915_pci.c +1 -0
@@ -346,13 +358,18 @@ static const struct intel_device_info intel_cherryview_info = {
  	.has_aliasing_ppgtt = 1,
  	.has_full_ppgtt = 1,
  	.display_mmio_offset = VLV_DISPLAY_BASE,
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G,

Split long line.

Quoted 2 lines
drivers/gpu/drm/i915/i915_pci.c +0 -0
  	GEN_CHV_PIPEOFFSETS,
  	CURSOR_OFFSETS,
Quoted 7 lines

drivers/gpu/drm/i915/i915_pci.c static const struct intel_device_info intel_cherryview_info = { · line 368

Quoted 5 lines
(quoted diff) +0 -0
 >  	CHV_COLORS,
  };

drivers/gpu/drm/i915/i915_pci.c +2 -0
+#define GEN9_DEFAULT_PAGE_SZ \
+	.page_size_mask = I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_2M | I915_GTT_PAGE_SIZE_1G

GEN9_DEFAULT_PAGE_SIZES, also split long line.

Also not in this patch. First patch is to set everything to the status quo. Last patch will be to enable the (completed) feature on the platforms using. In testing, that enabling patch comes early on to check bisection of the series.
-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
maintainer
#4 lore raw

Re: [PATCH 01/18] drm/i915: add page_size_mask to dev_info

Quoted 5 lines · Chris Wilson

Also not in this patch. First patch is to set everything to the status quo. Last patch will be to enable the (completed) feature on the platforms using. In testing, that enabling patch comes early on to check bisection of the series.

Except if the feature is implemented in increments, but I already mentioned in another patch that the ordering could be shuffled to allow for easier review (which will lead to easier bisecting, too).

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
#5 lore raw

Re: [PATCH 01/18] drm/i915: add page_size_mask to dev_info

In reply to Matthew Auld
Quoted 14 lines · Matthew Auld
drivers/gpu/drm/i915/i915_gem_gtt.h +5 -1
index fb15684c1d83..27b2b9e681db 100644
@@ -42,7 +42,22 @@
 #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_1G BIT(30)
+

drivers/gpu/drm/i915/i915_gem_gtt.h line 59

Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_gtt.h +10 -0
+#define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K
+
+#define I915_GTT_PAGE_SIZE_MASK (I915_GTT_PAGE_SIZE_4K | \
+				 I915_GTT_PAGE_SIZE_64K | \
+				 I915_GTT_PAGE_SIZE_2M | \
+				 I915_GTT_PAGE_SIZE_1G)
+
+#define is_valid_gtt_page_size(page_size) \
+	(is_power_of_2(page_size) && \
+	 (page_size) & I915_GTT_PAGE_SIZE_MASK)

({ unsigned int __size = (page_size); (__size & SIZE_MASK) == __size; })

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#6 lore raw

PATCH 2/18 drm/i915: introduce drm_i915_gem_object page_size members

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem.c        | 5 +++++
 drivers/gpu/drm/i915/i915_gem_object.h | 3 +++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
index 4ca88f2539c0..cbf97f4bbb72 100644
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	struct sg_table *pages;
 
 	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
@@ -4159,6 +4161,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 
 	obj->ops = ops;
 
+	obj->page_size = PAGE_SIZE;
+	obj->gtt_page_size = I915_GTT_PAGE_SIZE;
+
 	reservation_object_init(&obj->__builtin_resv);
 	obj->resv = &obj->__builtin_resv;
 
drivers/gpu/drm/i915/i915_gem_object.h +3 -0
index 174cf923c236..b1dacbfe5173 100644
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */
+
 	atomic_t frontbuffer_bits;
 	unsigned int frontbuffer_ggtt_origin; /* write once */
 	struct i915_gem_active frontbuffer_write;
Signature · 6 lines
2.9.3

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

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

Commit message to explain why.

Quoted 1 line · Matthew Auld

<SNIP>

drivers/gpu/drm/i915/i915_gem.c static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) · line 2445

Quoted 7 lines
drivers/gpu/drm/i915/i915_gem.c +0 -0
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
  	struct sg_table *pages;

GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));

drivers/gpu/drm/i915/i915_gem.c +2 -0
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));

GEM_BUG_ON(!HAS_PAGE_SIZE(obj->i915, obj->page_size)); GEM_BUG_ON(!HAS_PAGE_SIZE(obj->i915, obj->gtt_page_size));

Patches should be split functionally, not for the sake of splitting. Tt's rather hard to complete review when the appearing code is pretty much no-op, so for next you could squash them a bit. For now, as a leap of faith;

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
#8 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

In reply to Matthew Auld
Quoted 34 lines · Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem.c        | 5 +++++
 drivers/gpu/drm/i915/i915_gem_object.h | 3 +++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
index 4ca88f2539c0..cbf97f4bbb72 100644
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	struct sg_table *pages;
 
 	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
@@ -4159,6 +4161,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 
 	obj->ops = ops;
 
+	obj->page_size = PAGE_SIZE;
+	obj->gtt_page_size = I915_GTT_PAGE_SIZE;
+
 	reservation_object_init(&obj->__builtin_resv);
 	obj->resv = &obj->__builtin_resv;
 
drivers/gpu/drm/i915/i915_gem_object.h +0 -0
index 174cf923c236..b1dacbfe5173 100644

drivers/gpu/drm/i915/i915_gem_object.h struct drm_i915_gem_object { · line 111

Quoted 5 lines
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */

Just kinda archecture review, with a long-term view: Is the plan to eventually become more flexible here, i.e. allow mixed mode? We can of course ask shmem to try really hard to give us huge pages, but at the end it might not be able to give us a huge page (if the obj size isn't rounded to 2M), and there's no hw reason to not map everything else as hugepage. Through sg table coalescing we can cope with that, and we can check fairly cheaply whether an entry is big enough to be eligible for huge page mapping.

That also means in the pte functions we'd not make a top-level decision whether to use huge entries or not, but do that at each level by looking at the sg table. This should also make it easier for stolen, which is always contiguous but rather often not size-rounded.

It's a bit more tricky for 64kb pages, but I think those only can be used for an object which already has huge pages/is contiguous, but where the size is only rounded to 64kb and not 2m (because 2m would wast too much space). Then we can map the partial 2m using 64kb entries.

Just some long-term thoughts on this here, wher I expect things will head towards eventually.
-Daniel

Signature · 7 lines
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#9 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

Quoted 38 lines · Daniel Vetter
Quoted 37 lines · Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem.c        | 5 +++++
 drivers/gpu/drm/i915/i915_gem_object.h | 3 +++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
index 4ca88f2539c0..cbf97f4bbb72 100644
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	struct sg_table *pages;
 
 	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
@@ -4159,6 +4161,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 
 	obj->ops = ops;
 
+	obj->page_size = PAGE_SIZE;
+	obj->gtt_page_size = I915_GTT_PAGE_SIZE;
+
 	reservation_object_init(&obj->__builtin_resv);
 	obj->resv = &obj->__builtin_resv;
 
drivers/gpu/drm/i915/i915_gem_object.h +0 -0
index 174cf923c236..b1dacbfe5173 100644
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
Quoted 5 lines

drivers/gpu/drm/i915/i915_gem_object.h struct drm_i915_gem_object { · line 111

Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */

Just kinda archecture review, with a long-term view: Is the plan to eventually become more flexible here, i.e. allow mixed mode?

Simply put we can not support obj->page_size. Every object will be composed of a mixture of page sizes, often outside of our control and those page sizes may vary over the lifetime of the object.

Trying to design around an a priori static page_size is a bad idea, imo. -Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#10 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

Quoted 45 lines · Chris Wilson
Quoted 38 lines · Daniel Vetter
Quoted 37 lines · Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem.c        | 5 +++++
 drivers/gpu/drm/i915/i915_gem_object.h | 3 +++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
index 4ca88f2539c0..cbf97f4bbb72 100644
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	struct sg_table *pages;
 
 	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
@@ -4159,6 +4161,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 
 	obj->ops = ops;
 
+	obj->page_size = PAGE_SIZE;
+	obj->gtt_page_size = I915_GTT_PAGE_SIZE;
+
 	reservation_object_init(&obj->__builtin_resv);
 	obj->resv = &obj->__builtin_resv;
 
drivers/gpu/drm/i915/i915_gem_object.h +0 -0
index 174cf923c236..b1dacbfe5173 100644
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
Quoted 5 lines

drivers/gpu/drm/i915/i915_gem_object.h struct drm_i915_gem_object { · line 111

Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */

Just kinda archecture review, with a long-term view: Is the plan to eventually become more flexible here, i.e. allow mixed mode?

Quoted 5 lines

Simply put we can not support obj->page_size. Every object will be composed of a mixture of page sizes, often outside of our control and those page sizes may vary over the lifetime of the object.

Trying to design around an a priori static page_size is a bad idea, imo.

I think I've misrepresented the intention of obj->page_size, it merely serves as a hint to get pages, thereafter it represents the minimum page size in the mapping and is just bookkeeping, so mixed pages are totally fine and expected. I mostly wanted it to make it clear to the reader that we have a gtt and cpu page size. I also wanted to know if an object is entirely composed of huge-pages for debugfs purposes. I'll try to rework this to make it less terrible.

Quoted 8 lines

-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

#11 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

Quoted 52 lines · Matthew Auld
Quoted 45 lines · Chris Wilson
Quoted 38 lines · Daniel Vetter
Quoted 37 lines · Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem.c        | 5 +++++
 drivers/gpu/drm/i915/i915_gem_object.h | 3 +++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
index 4ca88f2539c0..cbf97f4bbb72 100644
@@ -2441,6 +2441,8 @@ static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
 	struct sg_table *pages;
 
 	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->page_size));
+	GEM_BUG_ON(!is_valid_gtt_page_size(obj->gtt_page_size));
 
 	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
@@ -4159,6 +4161,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 
 	obj->ops = ops;
 
+	obj->page_size = PAGE_SIZE;
+	obj->gtt_page_size = I915_GTT_PAGE_SIZE;
+
 	reservation_object_init(&obj->__builtin_resv);
 	obj->resv = &obj->__builtin_resv;
 
drivers/gpu/drm/i915/i915_gem_object.h +0 -0
index 174cf923c236..b1dacbfe5173 100644
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
Quoted 5 lines

drivers/gpu/drm/i915/i915_gem_object.h struct drm_i915_gem_object { · line 111

Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */

Just kinda archecture review, with a long-term view: Is the plan to eventually become more flexible here, i.e. allow mixed mode?

Quoted 5 lines

Simply put we can not support obj->page_size. Every object will be composed of a mixture of page sizes, often outside of our control and those page sizes may vary over the lifetime of the object.

Trying to design around an a priori static page_size is a bad idea, imo.

Quoted 7 lines

I think I've misrepresented the intention of obj->page_size, it merely serves as a hint to get pages, thereafter it represents the minimum page size in the mapping and is just bookkeeping, so mixed pages are totally fine and expected. I mostly wanted it to make it clear to the reader that we have a gtt and cpu page size. I also wanted to know if an object is entirely composed of huge-pages for debugfs purposes. I'll try to rework this to make it less terrible.

But if you already handle mixed pages, why do we need this still? Viz. this thread, it does seem to cause quite a bit of confusion.

And I have no idea why we need the cpu_page_size, we kmap at the page level anyway, and shmem handles the cpu mmap stuff for us. -Daniel

Signature · 7 lines
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#12 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

In reply to Matthew Auld
Quoted 23 lines · Matthew Auld
Quoted 16 lines · Chris Wilson
Quoted 9 lines · Daniel Vetter
Quoted 8 lines · Matthew Auld
drivers/gpu/drm/i915/i915_gem_object.h +0 -0
index 174cf923c236..b1dacbfe5173 100644
@@ -107,6 +107,9 @@ struct drm_i915_gem_object {
 	unsigned int cache_level:3;
 	unsigned int cache_dirty:1;
 
Quoted 5 lines

drivers/gpu/drm/i915/i915_gem_object.h struct drm_i915_gem_object { · line 111

Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_object.h +2 -0
+	unsigned int page_size; /* CPU pov - 4K(default), 2M, 1G */
+	unsigned int gtt_page_size; /* GPU pov - 4K(default), 64K, 2M, 1G */

Just kinda archecture review, with a long-term view: Is the plan to eventually become more flexible here, i.e. allow mixed mode?

Quoted 5 lines

Simply put we can not support obj->page_size. Every object will be composed of a mixture of page sizes, often outside of our control and those page sizes may vary over the lifetime of the object.

Trying to design around an a priori static page_size is a bad idea, imo.

Quoted 7 lines

I think I've misrepresented the intention of obj->page_size, it merely serves as a hint to get pages, thereafter it represents the minimum page size in the mapping and is just bookkeeping, so mixed pages are totally fine and expected. I mostly wanted it to make it clear to the reader that we have a gtt and cpu page size. I also wanted to know if an object is entirely composed of huge-pages for debugfs purposes. I'll try to rework this to make it less terrible.

An approach that might be interesting. On pinning the pages (i.e. ops->get_pages) if we fill in the bitmask of page sizes, something like

for_each_sg() {
	obj->mm.page_sizes |= fls(sg->length);

obj->mm.pages_sizes &= ~i915->info.page_sizes;

Then in insert_pages or probably better as vma_insert:

	gtt_page_alignment = fls(obj->mm.page_sizes);

I think that will be useful info even prior to trying to put it to good use, i.e. that will be enough to start dumping debugfs stats over how frequently we get large allocations.
-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#13 lore raw

Re: [PATCH 02/18] drm/i915: introduce drm_i915_gem_object page_size members

Quoted 8 lines · Chris Wilson

An approach that might be interesting. On pinning the pages (i.e. ops->get_pages) if we fill in the bitmask of page sizes, something like

for_each_sg() {
	obj->mm.page_sizes |= fls(sg->length);

obj->mm.pages_sizes &= ~i915->info.page_sizes;

Well, that was written in haste. You'll need a precomputed translation table to map the order to the nearest supported page size. -Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#14 lore raw

PATCH 3/18 drm/i915: pass page_size to insert_entries

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_gtt.c           | 33 ++++++++++++++++++++++-----
 drivers/gpu/drm/i915/i915_gem_gtt.h           |  1 +
 drivers/gpu/drm/i915/i915_vma.c               |  1 +
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  3 ++-
 drivers/gpu/drm/i915/selftests/mock_gtt.c     |  1 +
 5 files changed, 32 insertions(+), 7 deletions(-)
drivers/gpu/drm/i915/i915_gem_gtt.c +27 -6
index 8bab4aea63e6..0c8350f709da 100644
@@ -205,7 +205,7 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
 		pte_flags |= PTE_READ_ONLY;
 
 	vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
-				cache_level, pte_flags);
+				vma->obj->gtt_page_size, cache_level, pte_flags);
 
 	return 0;
 }
@@ -906,6 +906,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
 static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
 				   struct sg_table *pages,
 				   u64 start,
+				   unsigned int page_size,
 				   enum i915_cache_level cache_level,
 				   u32 unused)
 {
@@ -924,6 +925,7 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm,
 static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 				   struct sg_table *pages,
 				   u64 start,
+				   unsigned int page_size,
 				   enum i915_cache_level cache_level,
 				   u32 unused)
 {
@@ -935,9 +937,24 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 	};
 	struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;
 	struct gen8_insert_pte idx = gen8_insert_pte(start);
+	bool (*insert_entries)(struct i915_hw_ppgtt *ppgtt,
+			       struct i915_page_directory_pointer *pdp,
+			       struct sgt_dma *iter,
+			       struct gen8_insert_pte *idx,
+			       enum i915_cache_level cache_level);
+
+	/* TODO: turn this into vfunc */
+	switch (page_size) {
+	case I915_GTT_PAGE_SIZE_4K:
+		insert_entries = gen8_ppgtt_insert_pte_entries;
+		break;
+	default:
+		MISSING_CASE(page_size);
+		return;
+	}
 
-	while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter,
-					     &idx, cache_level))
+	while (insert_entries(ppgtt, pdps[idx.pml4e++], &iter, &idx,
+			      cache_level))
 		GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4);
 }
 
@@ -1620,6 +1637,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
 				      struct sg_table *pages,
 				      u64 start,
+				      unsigned int page_size,
 				      enum i915_cache_level cache_level,
 				      u32 flags)
 {
@@ -2093,6 +2111,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
 static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     u64 start,
+				     unsigned int page_size,
 				     enum i915_cache_level level,
 				     u32 unused)
 {
@@ -2140,6 +2159,7 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
 static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *st,
 				     u64 start,
+				     unsigned int page_size,
 				     enum i915_cache_level level,
 				     u32 flags)
 {
@@ -2224,6 +2244,7 @@ static void i915_ggtt_insert_page(struct i915_address_space *vm,
 static void i915_ggtt_insert_entries(struct i915_address_space *vm,
 				     struct sg_table *pages,
 				     u64 start,
+				     unsigned int page_size,
 				     enum i915_cache_level cache_level,
 				     u32 unused)
 {
@@ -2260,7 +2281,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 
 	intel_runtime_pm_get(i915);
 	vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
-				cache_level, pte_flags);
+				I915_GTT_PAGE_SIZE, cache_level, pte_flags);
 	intel_runtime_pm_put(i915);
 
 	/*
@@ -2314,14 +2335,14 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 
 		appgtt->base.insert_entries(&appgtt->base,
 					    vma->pages, vma->node.start,
-					    cache_level, pte_flags);
+					    I915_GTT_PAGE_SIZE, cache_level, pte_flags);
 	}
 
 	if (flags & I915_VMA_GLOBAL_BIND) {
 		intel_runtime_pm_get(i915);
 		vma->vm->insert_entries(vma->vm,
 					vma->pages, vma->node.start,
-					cache_level, pte_flags);
+					I915_GTT_PAGE_SIZE, cache_level, pte_flags);
 		intel_runtime_pm_put(i915);
 	}
 
drivers/gpu/drm/i915/i915_gem_gtt.h +1 -0
index 27b2b9e681db..232f7ef4c21b 100644
@@ -329,6 +329,7 @@ struct i915_address_space {
 	void (*insert_entries)(struct i915_address_space *vm,
 			       struct sg_table *st,
 			       u64 start,
+			       unsigned int page_size,
 			       enum i915_cache_level cache_level,
 			       u32 flags);
 	void (*cleanup)(struct i915_address_space *vm);
drivers/gpu/drm/i915/i915_vma.c +1 -0
index 1aba47024656..0cf9c0a98c19 100644
@@ -544,6 +544,7 @@ int __i915_vma_do_pin(struct i915_vma *vma,
 	lockdep_assert_held(&vma->vm->i915->drm.struct_mutex);
 	GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
 	GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma));
+	GEM_BUG_ON(!is_valid_gtt_page_size(vma->obj->gtt_page_size));
 
 	if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
 		ret = -EBUSY;
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +2 -1
index 50710e3f1caa..259b5e139df1 100644
@@ -256,7 +256,8 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 				break;
 
 			vm->insert_entries(vm, obj->mm.pages, addr,
-					   I915_CACHE_NONE, 0);
+					   I915_GTT_PAGE_SIZE, I915_CACHE_NONE,
+					   0);
 		}
 		count = n;
 
drivers/gpu/drm/i915/selftests/mock_gtt.c +1 -0
index a61309c7cb3e..38532a008387 100644
@@ -35,6 +35,7 @@ static void mock_insert_page(struct i915_address_space *vm,
 static void mock_insert_entries(struct i915_address_space *vm,
 				struct sg_table *st,
 				u64 start,
+				unsigned int page_size,
 				enum i915_cache_level level, u32 flags)
 {
 }
Signature · 6 lines
2.9.3

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

PATCH 4/18 drm/i915: s/i915_gtt_color_adjust/i915_ggtt_color_adjust

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/i915_gem_gtt.c +5 -5
index 0c8350f709da..0989af4a17e4 100644
@@ -2395,10 +2395,10 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
 	dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL);
 }
 
-static void i915_gtt_color_adjust(const struct drm_mm_node *node,
-				  unsigned long color,
-				  u64 *start,
-				  u64 *end)
+static void i915_ggtt_color_adjust(const struct drm_mm_node *node,
+				   unsigned long color,
+				   u64 *start,
+				   u64 *end)
 {
 	if (node->allocated && node->color != color)
 		*start += I915_GTT_PAGE_SIZE;
@@ -2970,7 +2970,7 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
 	mutex_lock(&dev_priv->drm.struct_mutex);
 	i915_address_space_init(&ggtt->base, dev_priv, "[global]");
 	if (!HAS_LLC(dev_priv) && !USES_PPGTT(dev_priv))
-		ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
+		ggtt->base.mm.color_adjust = i915_ggtt_color_adjust;
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	if (!io_mapping_init_wc(&dev_priv->ggtt.mappable,
Signature · 6 lines
2.9.3

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

Re: [PATCH 04/18] drm/i915: s/i915_gtt_color_adjust/i915_ggtt_color_adjust

Commit message for why we do this.

Quoted 1 line · Matthew Auld

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
#17 lore raw

PATCH 5/18 drm/i915: clean up cache coloring

In reply to Matthew Auld

Rid the code of any mm.color_adjust assumptions to allow adding another flavour of coloring.

v2: better naming

---
 drivers/gpu/drm/i915/i915_drv.h                 |  2 +-
 drivers/gpu/drm/i915/i915_gem.c                 |  3 ++-
 drivers/gpu/drm/i915/i915_gem_evict.c           | 12 +++++-------
 drivers/gpu/drm/i915/i915_gem_gtt.h             |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c                 | 10 +++++++---
 drivers/gpu/drm/i915/selftests/i915_gem_evict.c |  8 +++++---
 6 files changed, 26 insertions(+), 15 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -1
index ab7a1072e7b5..838ce22a0a40 100644
@@ -3543,7 +3543,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct i915_address_space *vm,
 					  u64 min_size, u64 alignment,
-					  unsigned cache_level,
+					  unsigned long color,
 					  u64 start, u64 end,
 					  unsigned flags);
 int __must_check i915_gem_evict_for_node(struct i915_address_space *vm,
drivers/gpu/drm/i915/i915_gem.c +2 -1
index cbf97f4bbb72..5362f4d18689 100644
@@ -3578,7 +3578,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		obj->cache_dirty = true;
 
 	list_for_each_entry(vma, &obj->vma_list, obj_link)
-		vma->node.color = cache_level;
+		if (i915_vm_has_cache_coloring(vma->vm))
+			vma->node.color = cache_level;
 	obj->cache_level = cache_level;
 
 	return 0;
drivers/gpu/drm/i915/i915_gem_evict.c +5 -7
index 51e365f70464..0c9c51be0f6a 100644
@@ -74,7 +74,7 @@ mark_free(struct drm_mm_scan *scan,
  * @vm: address space to evict from
  * @min_size: size of the desired free space
  * @alignment: alignment constraint of the desired free space
- * @cache_level: cache_level for the desired space
+ * @color: color for the desired space
  * @start: start (inclusive) of the range from which to evict objects
  * @end: end (exclusive) of the range from which to evict objects
  * @flags: additional flags to control the eviction algorithm
@@ -95,7 +95,7 @@ mark_free(struct drm_mm_scan *scan,
 int
 i915_gem_evict_something(struct i915_address_space *vm,
 			 u64 min_size, u64 alignment,
-			 unsigned cache_level,
+			 unsigned long color,
 			 u64 start, u64 end,
 			 unsigned flags)
 {
@@ -134,7 +134,7 @@ i915_gem_evict_something(struct i915_address_space *vm,
 	if (flags & PIN_MAPPABLE)
 		mode = DRM_MM_INSERT_LOW;
 	drm_mm_scan_init_with_range(&scan, &vm->mm,
-				    min_size, alignment, cache_level,
+				    min_size, alignment, color,
 				    start, end, mode);
 
 	/* Retire before we search the active list. Although we have
@@ -253,7 +253,6 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
 	u64 start = target->start;
 	u64 end = start + target->size;
 	struct i915_vma *vma, *next;
-	bool check_color;
 	int ret = 0;
 
 	lockdep_assert_held(&vm->i915->drm.struct_mutex);
@@ -270,8 +269,7 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
 	if (!(flags & PIN_NONBLOCK))
 		i915_gem_retire_requests(vm->i915);
 
-	check_color = vm->mm.color_adjust;
-	if (check_color) {
+	if (i915_vm_has_cache_coloring(vm)) {
 		/* Expand search to cover neighbouring guard pages (or lack!) */
 		if (start)
 			start -= I915_GTT_PAGE_SIZE;
@@ -297,7 +295,7 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
 		 * abutt and conflict. If they are in conflict, then we evict
 		 * those as well to make room for our guard pages.
 		 */
-		if (check_color) {
+		if (i915_vm_has_cache_coloring(vm)) {
 			if (node->start + node->size == target->start) {
 				if (node->color == target->color)
 					continue;
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 232f7ef4c21b..9c592e2de516 100644
@@ -347,6 +347,12 @@ struct i915_address_space {
 #define i915_is_ggtt(V) (!(V)->file)
 
 static inline bool
+i915_vm_has_cache_coloring(const struct i915_address_space *vm)
+{
+	return vm->mm.color_adjust && i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
 	return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +7 -3
index 0cf9c0a98c19..4ead7d075fd3 100644
@@ -390,7 +390,7 @@ bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level)
 	 * these constraints apply and set the drm_mm.color_adjust
 	 * appropriately.
 	 */
-	if (vma->vm->mm.color_adjust == NULL)
+	if (!i915_vm_has_cache_coloring(vma->vm))
 		return true;
 
 	/* Only valid to be called on an already inserted vma */
@@ -429,6 +429,7 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	struct drm_i915_gem_object *obj = vma->obj;
 	u64 start, end;
 	int ret;
+	unsigned long color = 0;
 
 	GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
 	GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
@@ -471,6 +472,9 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	if (ret)
 		return ret;
 
+	if (i915_vm_has_cache_coloring(vma->vm))
+		color = obj->cache_level;
+
 	if (flags & PIN_OFFSET_FIXED) {
 		u64 offset = flags & PIN_OFFSET_MASK;
 		if (!IS_ALIGNED(offset, alignment) ||
@@ -480,13 +484,13 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 		}
 
 		ret = i915_gem_gtt_reserve(vma->vm, &vma->node,
-					   size, offset, obj->cache_level,
+					   size, offset, color,
 					   flags);
 		if (ret)
 			goto err_unpin;
 	} else {
 		ret = i915_gem_gtt_insert(vma->vm, &vma->node,
-					  size, alignment, obj->cache_level,
+					  size, alignment, color,
 					  start, end, flags);
 		if (ret)
 			goto err_unpin;
drivers/gpu/drm/i915/selftests/i915_gem_evict.c +5 -3
index 14e9c2fbc4e6..8c0b4dc9de3d 100644
@@ -224,11 +224,13 @@ static int igt_evict_for_cache_color(void *arg)
 	int err;
 
 	/* Currently the use of color_adjust is limited to cache domains within
-	 * the ggtt, and so the presence of mm.color_adjust is assumed to be
-	 * i915_gtt_color_adjust throughout our driver, so using a mock color
-	 * adjust will work just fine for our purposes.
+	 * the ggtt, and page sizes within the ppgtt, so the presence of
+	 * mm.color_adjust is assumed to be i915_gtt_color_adjust when if vm is
+	 * ggtt, so using a mock color adjust will work just fine for our
+	 * purposes.
 	 */
 	ggtt->base.mm.color_adjust = mock_color_adjust;
+	GEM_BUG_ON(!i915_vm_has_cache_coloring(&ggtt->base));
 
 	obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE);
 	if (IS_ERR(obj)) {
Signature · 6 lines
2.9.3

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

Re: [PATCH 05/18] drm/i915: clean up cache coloring

Quoted 7 lines · Matthew Auld

Rid the code of any mm.color_adjust assumptions to allow adding another flavour of coloring.

v2: better naming

<SNIP>

drivers/gpu/drm/i915/i915_gem_gtt.h struct i915_address_space { · line 353

Quoted 9 lines

+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h

drivers/gpu/drm/i915/i915_gem_gtt.h +0 -0
@@ -347,6 +347,12 @@ struct i915_address_space {
  #define i915_is_ggtt(V) (!(V)->file)


 static inline bool

drivers/gpu/drm/i915/i915_gem_gtt.h +4 -0
+i915_vm_has_cache_coloring(const struct i915_address_space *vm)
+{
+	return vm->mm.color_adjust && i915_is_ggtt(vm);
+}

I'd first check the is_ggtt() because it's more important one, and drop a comment here as to why we can make the decision.

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
#19 lore raw

PATCH 6/18 drm/i915: export color_differs

In reply to Matthew Auld

Export color_differs so that we can use it elsewhere.

v2: better naming

---
 drivers/gpu/drm/i915/i915_vma.c | 11 ++++-------
 drivers/gpu/drm/i915/i915_vma.h |  6 ++++++
 2 files changed, 10 insertions(+), 7 deletions(-)
drivers/gpu/drm/i915/i915_vma.c +4 -7
index 4ead7d075fd3..8f0041ba328f 100644
@@ -373,11 +373,6 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
 		vma->flags &= ~I915_VMA_CAN_FENCE;
 }
 
-static bool color_differs(struct drm_mm_node *node, unsigned long color)
-{
-	return node->allocated && node->color != color;
-}
-
 bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level)
 {
 	struct drm_mm_node *node = &vma->node;
@@ -398,11 +393,13 @@ bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level)
 	GEM_BUG_ON(list_empty(&node->node_list));
 
 	other = list_prev_entry(node, node_list);
-	if (color_differs(other, cache_level) && !drm_mm_hole_follows(other))
+	if (i915_node_color_differs(other, cache_level) &&
+	    !drm_mm_hole_follows(other))
 		return false;
 
 	other = list_next_entry(node, node_list);
-	if (color_differs(other, cache_level) && !drm_mm_hole_follows(node))
+	if (i915_node_color_differs(other, cache_level) &&
+	    !drm_mm_hole_follows(node))
 		return false;
 
 	return true;
drivers/gpu/drm/i915/i915_vma.h +6 -0
index 2e03f81dddbe..6c95926f896f 100644
@@ -284,6 +284,12 @@ static inline void i915_vma_unpin(struct i915_vma *vma)
 	__i915_vma_unpin(vma);
 }
 
+static inline bool i915_node_color_differs(const struct drm_mm_node *node,
+					   unsigned long color)
+{
+	return node->allocated && node->color != color;
+}
+
 /**
  * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
  * @vma: VMA to iomap
Signature · 6 lines
2.9.3

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
maintainer Reviewed-by on v1 6/18
#20 lore raw

Re: [PATCH 06/18] drm/i915: export color_differs

Quoted 6 lines · Matthew Auld

Export color_differs so that we can use it elsewhere.

v2: better naming

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
#21 lore raw

PATCH 7/18 drm/i915: introduce ppgtt page coloring

In reply to Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
 	return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+				   unsigned long color,
+				   u64 *start,
+				   u64 *end)
+{
+	GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+	if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+		return;
+
+	GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+	if (i915_node_color_differs(node, color))
+		*start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+	node = list_next_entry(node, node_list);
+	if (i915_node_color_differs(node, color))
+		*end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+	GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 		ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
 		ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
 		ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+		if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+			ppgtt->base.mm.color_adjust = i915_page_color_adjust;
 	} else {
 		ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
 		if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+	return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
 	return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +2 -0
index 8f0041ba328f..4043145b4310 100644
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
 	if (i915_vm_has_cache_coloring(vma->vm))
 		color = obj->cache_level;
+	else if (i915_vm_has_page_coloring(vma->vm))
+		color = obj->gtt_page_size;
 
 	if (flags & PIN_OFFSET_FIXED) {
 		u64 offset = flags & PIN_OFFSET_MASK;
Signature · 6 lines
2.9.3

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

Re: [PATCH 07/18] drm/i915: introduce ppgtt page coloring

Quoted 77 lines · Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
 	return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+				   unsigned long color,
+				   u64 *start,
+				   u64 *end)
+{
+	GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+	if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+		return;
+
+	GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+	if (i915_node_color_differs(node, color))
+		*start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+	node = list_next_entry(node, node_list);
+	if (i915_node_color_differs(node, color))
+		*end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+	GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 		ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
 		ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
 		ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+		if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+			ppgtt->base.mm.color_adjust = i915_page_color_adjust;
 	} else {
 		ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
 		if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+	return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
 	return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +0 -0
index 8f0041ba328f..4043145b4310 100644

drivers/gpu/drm/i915/i915_vma.c i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) · line 475

Quoted 5 lines
drivers/gpu/drm/i915/i915_vma.c +2 -0
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
 	if (i915_vm_has_cache_coloring(vma->vm))
 		color = obj->cache_level;
+	else if (i915_vm_has_page_coloring(vma->vm))
+		color = obj->gtt_page_size;

This does not need color_adjust since you are just specifying an alignment and size. Why the extra complications? I remember asking the same last time.
-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#23 lore raw

Re: [PATCH 07/18] drm/i915: introduce ppgtt page coloring

Quoted 79 lines · Chris Wilson
Quoted 78 lines · Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
      return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+                                unsigned long color,
+                                u64 *start,
+                                u64 *end)
+{
+     GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+     if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+             return;
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+     if (i915_node_color_differs(node, color))
+             *start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+     node = list_next_entry(node, node_list);
+     if (i915_node_color_differs(node, color))
+             *end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
              ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
              ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
              ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+             if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+                     ppgtt->base.mm.color_adjust = i915_page_color_adjust;
      } else {
              ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
              if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+     return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
      return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +0 -0
index 8f0041ba328f..4043145b4310 100644
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
Quoted 8 lines

drivers/gpu/drm/i915/i915_vma.c i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) · line 475

Quoted 4 lines
drivers/gpu/drm/i915/i915_vma.c +2 -0
      if (i915_vm_has_cache_coloring(vma->vm))
              color = obj->cache_level;
+     else if (i915_vm_has_page_coloring(vma->vm))
+             color = obj->gtt_page_size;

This does not need color_adjust since you are just specifying an alignment and size. Why the extra complications? I remember asking the same last time.

Hmm, are you saying the whole idea of needing a color_adjust for 4K/64K vm placement is completely unnecessary?
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#24 lore raw

Re: [PATCH 07/18] drm/i915: introduce ppgtt page coloring

Quoted 88 lines · Matthew Auld
Quoted 79 lines · Chris Wilson
Quoted 78 lines · Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
      return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+                                unsigned long color,
+                                u64 *start,
+                                u64 *end)
+{
+     GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+     if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+             return;
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+     if (i915_node_color_differs(node, color))
+             *start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+     node = list_next_entry(node, node_list);
+     if (i915_node_color_differs(node, color))
+             *end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
              ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
              ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
              ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+             if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+                     ppgtt->base.mm.color_adjust = i915_page_color_adjust;
      } else {
              ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
              if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+     return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
      return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +0 -0
index 8f0041ba328f..4043145b4310 100644
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
Quoted 8 lines

drivers/gpu/drm/i915/i915_vma.c i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) · line 475

Quoted 4 lines
drivers/gpu/drm/i915/i915_vma.c +2 -0
      if (i915_vm_has_cache_coloring(vma->vm))
              color = obj->cache_level;
+     else if (i915_vm_has_page_coloring(vma->vm))
+             color = obj->gtt_page_size;

This does not need color_adjust since you are just specifying an alignment and size. Why the extra complications? I remember asking the same last time.

Quoted 2 lines

Hmm, are you saying the whole idea of needing a color_adjust for 4K/64K vm placement is completely unnecessary?

As constructed here, yes. Since you just want to request a obj->gtt_page_size aligned block:

	.size = round_up(size, obj->gtt_page_size),
	.align = max(align, obj->gtt_page_size).

(Hmm, now I think about it you shouldn't round size up unless the insert_pages() is careful not to assume that the last page is a full superpage. More I think about this, you only want to align the base and let insert_pages group up the superpages.)

Unless I have completely misunderstood, you do not need to insert gaps between blocks. Both the color_adjust approach and this approach still need lower level support to amalgamate pages.
-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#25 lore raw

Re: [PATCH 07/18] drm/i915: introduce ppgtt page coloring

Quoted 89 lines · Chris Wilson
Quoted 88 lines · Matthew Auld
Quoted 87 lines · Chris Wilson
Quoted 77 lines · Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
      return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+                                unsigned long color,
+                                u64 *start,
+                                u64 *end)
+{
+     GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+     if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+             return;
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+     if (i915_node_color_differs(node, color))
+             *start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+     node = list_next_entry(node, node_list);
+     if (i915_node_color_differs(node, color))
+             *end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
              ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
              ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
              ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+             if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+                     ppgtt->base.mm.color_adjust = i915_page_color_adjust;
      } else {
              ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
              if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+     return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
      return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +0 -0
index 8f0041ba328f..4043145b4310 100644

drivers/gpu/drm/i915/i915_vma.c i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) · line 475

Quoted 5 lines
drivers/gpu/drm/i915/i915_vma.c +2 -0
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
      if (i915_vm_has_cache_coloring(vma->vm))
              color = obj->cache_level;
+     else if (i915_vm_has_page_coloring(vma->vm))
+             color = obj->gtt_page_size;

This does not need color_adjust since you are just specifying an alignment and size. Why the extra complications? I remember asking the same last time.

Quoted 8 lines
Quoted 2 lines

Hmm, are you saying the whole idea of needing a color_adjust for 4K/64K vm placement is completely unnecessary?

As constructed here, yes. Since you just want to request a obj->gtt_page_size aligned block:

        .size = round_up(size, obj->gtt_page_size),
        .align = max(align, obj->gtt_page_size).

Unless I've gone completely mad, I really don't think it's that simple, we never ever want a 4K object or 64K object to overlap the same page-table. We derive the pde and hence the page-table from node.start, so if we just request an obj->gtt_page_size aligned block, we could have a page-table with a mixture of 64K and 4K pte's, at which point we're screwed.

Quoted 6 lines

(Hmm, now I think about it you shouldn't round size up unless the insert_pages() is careful not to assume that the last page is a full superpage. More I think about this, you only want to align the base and let insert_pages group up the superpages.)

Quoted 7 lines

Unless I have completely misunderstood, you do not need to insert gaps between blocks. Both the color_adjust approach and this approach still need lower level support to amalgamate pages.
-Chris

--
Chris Wilson, Intel Open Source Technology Centre

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

#26 lore raw

Re: [PATCH 07/18] drm/i915: introduce ppgtt page coloring

In reply to Chris Wilson
Quoted 95 lines · Chris Wilson
Quoted 88 lines · Matthew Auld
Quoted 79 lines · Chris Wilson
Quoted 78 lines · Matthew Auld

To enable 64K pages we need to set the intermediate-page-size(IPS) bit of the pde, therefore a page table is said to be either operating in 64K or 4K mode. To accommodate this vm placement restriction we introduce a color for pages and corresponding color_adjust callback.

---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  6 ++++++
 drivers/gpu/drm/i915/i915_vma.c     |  2 ++
 3 files changed, 33 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +25 -0
index 0989af4a17e4..ddc3db345b76 100644
@@ -1332,6 +1332,28 @@ static int gen8_preallocate_top_level_pdp(struct i915_hw_ppgtt *ppgtt)
      return -ENOMEM;
 }
 
+static void i915_page_color_adjust(const struct drm_mm_node *node,
+                                unsigned long color,
+                                u64 *start,
+                                u64 *end)
+{
+     GEM_BUG_ON(!is_valid_gtt_page_size(color));
+
+     if (!(color & (I915_GTT_PAGE_SIZE_4K | I915_GTT_PAGE_SIZE_64K)))
+             return;
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+
+     if (i915_node_color_differs(node, color))
+             *start = roundup(*start, 1 << GEN8_PDE_SHIFT);
+
+     node = list_next_entry(node, node_list);
+     if (i915_node_color_differs(node, color))
+             *end = rounddown(*end, 1 << GEN8_PDE_SHIFT);
+
+     GEM_BUG_ON(node->allocated && !is_valid_gtt_page_size(node->color));
+}
+
 /*
  * GEN8 legacy ppgtt programming is accomplished through a max 4 PDP registers
  * with a net effect resembling a 2-level page table in normal x86 terms. Each
@@ -1372,6 +1394,9 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
              ppgtt->base.allocate_va_range = gen8_ppgtt_alloc_4lvl;
              ppgtt->base.insert_entries = gen8_ppgtt_insert_4lvl;
              ppgtt->base.clear_range = gen8_ppgtt_clear_4lvl;
+
+             if (SUPPORTS_PAGE_SIZE(dev_priv, I915_GTT_PAGE_SIZE_64K))
+                     ppgtt->base.mm.color_adjust = i915_page_color_adjust;
      } else {
              ret = __pdp_init(&ppgtt->base, &ppgtt->pdp);
              if (ret)
drivers/gpu/drm/i915/i915_gem_gtt.h +6 -0
index 9c592e2de516..8d893ddd98f2 100644
@@ -353,6 +353,12 @@ i915_vm_has_cache_coloring(const struct i915_address_space *vm)
 }
 
 static inline bool
+i915_vm_has_page_coloring(const struct i915_address_space *vm)
+{
+     return vm->mm.color_adjust && !i915_is_ggtt(vm);
+}
+
+static inline bool
 i915_vm_is_48bit(const struct i915_address_space *vm)
 {
      return (vm->total - 1) >> 32;
drivers/gpu/drm/i915/i915_vma.c +0 -0
index 8f0041ba328f..4043145b4310 100644
@@ -471,6 +471,8 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 
Quoted 8 lines

drivers/gpu/drm/i915/i915_vma.c i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) · line 475

Quoted 4 lines
drivers/gpu/drm/i915/i915_vma.c +2 -0
      if (i915_vm_has_cache_coloring(vma->vm))
              color = obj->cache_level;
+     else if (i915_vm_has_page_coloring(vma->vm))
+             color = obj->gtt_page_size;

This does not need color_adjust since you are just specifying an alignment and size. Why the extra complications? I remember asking the same last time.

Quoted 2 lines

Hmm, are you saying the whole idea of needing a color_adjust for 4K/64K vm placement is completely unnecessary?

As constructed here, yes. Since you just want to request a obj->gtt_page_size aligned block:

Quoted 7 lines
        .size = round_up(size, obj->gtt_page_size),
        .align = max(align, obj->gtt_page_size).

(Hmm, now I think about it you shouldn't round size up unless the insert_pages() is careful not to assume that the last page is a full superpage. More I think about this, you only want to align the base and let insert_pages group up the superpages.)

I feel like I must be missing your point, could you expand on what you mean my grouping superpages?

Quoted 8 lines

Unless I have completely misunderstood, you do not need to insert gaps between blocks. Both the color_adjust approach and this approach still need lower level support to amalgamate pages.
-Chris

--
Chris Wilson, Intel Open Source Technology Centre

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

#27 lore raw

PATCH 8/18 drm/i915: handle evict-for-node with page coloring

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_evict.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
drivers/gpu/drm/i915/i915_gem_evict.c +24 -0
index 0c9c51be0f6a..817acff2fb6c 100644
@@ -276,6 +276,30 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
 
 		/* Always look at the page afterwards to avoid the end-of-GTT */
 		end += I915_GTT_PAGE_SIZE;
+	} else if (i915_vm_has_page_coloring(vm)) {
+		u64 pt_start, pt_end;
+
+		GEM_BUG_ON(!is_valid_gtt_page_size(target->color));
+		GEM_BUG_ON(!IS_ALIGNED(start, target->color));
+		GEM_BUG_ON(!IS_ALIGNED(end, target->color));
+
+		/* We need to consider the page table coloring on both sides of
+		 * the range, where a mismatch would require extending our
+		 * range to evict nodes up to the page table boundry for each
+		 * side to ensure the underlying page table(s) for the range
+		 * match the target color.
+		 */
+		pt_start = rounddown(start, 1 << GEN8_PDE_SHIFT);
+		node = __drm_mm_interval_first(&vm->mm, pt_start, start);
+		if (i915_node_color_differs(node, target->color)) {
+			start = pt_start;
+		}
+
+		pt_end = roundup(start, 1 << GEN8_PDE_SHIFT);
+		node = __drm_mm_interval_first(&vm->mm, end, pt_end);
+		if (i915_node_color_differs(node, target->color)) {
+			end = pt_end;
+		}
 	}
 	GEM_BUG_ON(start >= end);
 
Signature · 6 lines
2.9.3

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

PATCH 9/18 drm/i915: support inserting 64K pages in the ppgtt

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 70 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  2 ++
 2 files changed, 72 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +70 -0
index ddc3db345b76..fb822c0bd973 100644
@@ -848,6 +848,73 @@ static __always_inline struct gen8_insert_pte gen8_insert_pte(u64 start)
 }
 
 static __always_inline bool
+gen8_ppgtt_insert_64K_pte_entries(struct i915_hw_ppgtt *ppgtt,
+				  struct i915_page_directory_pointer *pdp,
+				  struct sgt_dma *iter,
+				  struct gen8_insert_pte *idx,
+				  enum i915_cache_level cache_level)
+{
+	struct i915_page_directory *pd;
+	const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level);
+	gen8_pte_t *vaddr;
+	bool ret;
+
+	GEM_BUG_ON(idx->pte % 16);
+	GEM_BUG_ON(idx->pdpe >= i915_pdpes_per_pdp(&ppgtt->base));
+	/* TODO: probably move this to the allocation phase.. */
+	pd = pdp->page_directory[idx->pdpe];
+	vaddr = kmap_atomic_px(pd);
+	vaddr[idx->pde] |= GEN8_PDE_IPS_64K;
+	kunmap_atomic(vaddr);
+
+	vaddr = kmap_atomic_px(pd->page_table[idx->pde]);
+	do {
+		vaddr[idx->pte] = pte_encode | iter->dma;
+		iter->dma += I915_GTT_PAGE_SIZE_64K;
+		if (iter->dma >= iter->max) {
+			iter->sg = __sg_next(iter->sg);
+			if (!iter->sg) {
+				ret = false;
+				break;
+			}
+
+			iter->dma = sg_dma_address(iter->sg);
+			iter->max = iter->dma + iter->sg->length;
+		}
+
+		idx->pte += 16;
+
+		if (idx->pte == GEN8_PTES) {
+			idx->pte = 0;
+
+			if (++idx->pde == I915_PDES) {
+				idx->pde = 0;
+
+				/* Limited by sg length for 3lvl */
+				if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
+					idx->pdpe = 0;
+					ret = true;
+					break;
+				}
+
+				GEM_BUG_ON(idx->pdpe >= i915_pdpes_per_pdp(&ppgtt->base));
+				pd = pdp->page_directory[idx->pdpe];
+			}
+
+			kunmap_atomic(vaddr);
+			vaddr = kmap_atomic_px(pd);
+			vaddr[idx->pde] |= GEN8_PDE_IPS_64K;
+			kunmap_atomic(vaddr);
+
+			vaddr = kmap_atomic_px(pd->page_table[idx->pde]);
+		}
+	} while (1);
+	kunmap_atomic(vaddr);
+
+	return ret;
+}
+
+static __always_inline bool
 gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt,
 			      struct i915_page_directory_pointer *pdp,
 			      struct sgt_dma *iter,
@@ -948,6 +1015,9 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 	case I915_GTT_PAGE_SIZE_4K:
 		insert_entries = gen8_ppgtt_insert_pte_entries;
 		break;
+	case I915_GTT_PAGE_SIZE_64K:
+		insert_entries = gen8_ppgtt_insert_64K_pte_entries;
+		break;
 	default:
 		MISSING_CASE(page_size);
 		return;
drivers/gpu/drm/i915/i915_gem_gtt.h +2 -0
index 8d893ddd98f2..d948808fcf6a 100644
@@ -158,6 +158,8 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT_ELLC_OVERRIDE		(0<<2)
 #define GEN8_PPAT(i, x)			((u64)(x) << ((i) * 8))
 
+#define GEN8_PDE_IPS_64K BIT(11)
+
 struct sg_table;
 
 struct intel_rotation_info {
Signature · 6 lines
2.9.3

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

Re: [PATCH 09/18] drm/i915: support inserting 64K pages in the ppgtt

reproduce:

Hi Matthew,

[auto build test WARNING on drm-intel/for-linux-next]
[also build test WARNING on next-20170405]
[cannot apply to v4.11-rc5]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Matthew-Auld/drm-i915-initial-support-for-huge-gtt-pages-V2/20170406-060958
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-s2-04061013 (attached as .config)
compiler: gcc-4.4 (Debian 4.4.7-8) 4.4.7
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'gen8_ppgtt_insert_4lvl':

>> drivers/gpu/drm/i915/i915_gem_gtt.c:1002: warning: 'iter' is used uninitialized in this function

drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'gen8_ppgtt_insert_3lvl':
drivers/gpu/drm/i915/i915_gem_gtt.c:983: warning: 'iter.sg' is used uninitialized in this function drivers/gpu/drm/i915/i915_gem_gtt.c:984: warning: 'iter.dma' is used uninitialized in this function

vim +/iter +1002 drivers/gpu/drm/i915/i915_gem_gtt.c

9e89f9ee3 Chris Wilson   2017-02-25   986  	struct gen8_insert_pte idx = gen8_insert_pte(start);
de5ba8eb9 Michel Thierry 2015-08-03   987  
9e89f9ee3 Chris Wilson   2017-02-25   988  	gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx,
9e89f9ee3 Chris Wilson   2017-02-25   989  				      cache_level);
de5ba8eb9 Michel Thierry 2015-08-03   990  }
894ccebee Chris Wilson   2017-02-15   991  
894ccebee Chris Wilson   2017-02-15   992  static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
894ccebee Chris Wilson   2017-02-15   993  				   struct sg_table *pages,
75c7b0b86 Chris Wilson   2017-02-15   994  				   u64 start,
c7a43c911 Matthew Auld   2017-04-04   995  				   unsigned int page_size,
894ccebee Chris Wilson   2017-02-15   996  				   enum i915_cache_level cache_level,
894ccebee Chris Wilson   2017-02-15   997  				   u32 unused)
894ccebee Chris Wilson   2017-02-15   998  {
894ccebee Chris Wilson   2017-02-15   999  	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
894ccebee Chris Wilson   2017-02-15  1000  	struct sgt_dma iter = {
894ccebee Chris Wilson   2017-02-15  1001  		.sg = pages->sgl,
894ccebee Chris Wilson   2017-02-15 @1002  		.dma = sg_dma_address(iter.sg),
894ccebee Chris Wilson   2017-02-15  1003  		.max = iter.dma + iter.sg->length,
894ccebee Chris Wilson   2017-02-15  1004  	};
894ccebee Chris Wilson   2017-02-15  1005  	struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;
9e89f9ee3 Chris Wilson   2017-02-25  1006  	struct gen8_insert_pte idx = gen8_insert_pte(start);
c7a43c911 Matthew Auld   2017-04-04  1007  	bool (*insert_entries)(struct i915_hw_ppgtt *ppgtt,
c7a43c911 Matthew Auld   2017-04-04  1008  			       struct i915_page_directory_pointer *pdp,
c7a43c911 Matthew Auld   2017-04-04  1009  			       struct sgt_dma *iter,
c7a43c911 Matthew Auld   2017-04-04  1010  			       struct gen8_insert_pte *idx,

:::::: The code at line 1002 was first introduced by commit
:::::: 894ccebee2b0e606ba9638d20dd87b33568482d7 drm/i915: Micro-optimise gen8_ppgtt_insert_entries()

:::::: TO: Chris Wilson <[email protected]> :::::: CC: Chris Wilson <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

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

#30 lore raw

Re: [PATCH 09/18] drm/i915: support inserting 64K pages in the ppgtt

In reply to Matthew Auld
reproduce:

Hi Matthew,

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on next-20170407]
[cannot apply to v4.11-rc5]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Matthew-Auld/drm-i915-initial-support-for-huge-gtt-pages-V2/20170406-060958
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-s0-04090705 (attached as .config)
compiler: gcc-4.4 (Debian 4.4.7-8) 4.4.7
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

cc1: warnings being treated as errors drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'gen8_ppgtt_insert_4lvl':

>> drivers/gpu/drm/i915/i915_gem_gtt.c:1002: error: 'iter' is used uninitialized in this function

drivers/gpu/drm/i915/i915_gem_gtt.c: In function 'gen8_ppgtt_insert_3lvl':
drivers/gpu/drm/i915/i915_gem_gtt.c:983: error: 'iter.sg' is used uninitialized in this function drivers/gpu/drm/i915/i915_gem_gtt.c:984: error: 'iter.dma' is used uninitialized in this function

vim +/iter +1002 drivers/gpu/drm/i915/i915_gem_gtt.c

894ccebee Chris Wilson 2017-02-15   996  				   enum i915_cache_level cache_level,
894ccebee Chris Wilson 2017-02-15   997  				   u32 unused)
894ccebee Chris Wilson 2017-02-15   998  {
894ccebee Chris Wilson 2017-02-15   999  	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
894ccebee Chris Wilson 2017-02-15  1000  	struct sgt_dma iter = {
894ccebee Chris Wilson 2017-02-15  1001  		.sg = pages->sgl,
894ccebee Chris Wilson 2017-02-15 @1002  		.dma = sg_dma_address(iter.sg),
894ccebee Chris Wilson 2017-02-15  1003  		.max = iter.dma + iter.sg->length,
894ccebee Chris Wilson 2017-02-15  1004  	};
894ccebee Chris Wilson 2017-02-15  1005  	struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps;

:::::: The code at line 1002 was first introduced by commit
:::::: 894ccebee2b0e606ba9638d20dd87b33568482d7 drm/i915: Micro-optimise gen8_ppgtt_insert_entries()

:::::: TO: Chris Wilson <[email protected]> :::::: CC: Chris Wilson <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

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

#31 lore raw

PATCH 10/18 drm/i915: support inserting 2M pages in the ppgtt

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 53 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  1 +
 2 files changed, 54 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +53 -0
index fb822c0bd973..9dc12955f557 100644
@@ -848,6 +848,56 @@ static __always_inline struct gen8_insert_pte gen8_insert_pte(u64 start)
 }
 
 static __always_inline bool
+gen8_ppgtt_insert_2M_pde_entries(struct i915_hw_ppgtt *ppgtt,
+				 struct i915_page_directory_pointer *pdp,
+				 struct sgt_dma *iter,
+				 struct gen8_insert_pte *idx,
+				 enum i915_cache_level cache_level)
+{
+	const gen8_pte_t pde_encode = gen8_pte_encode(GEN8_PDE_PS_2M,
+						      cache_level);
+	gen8_pte_t *vaddr;
+	bool ret;
+
+	GEM_BUG_ON(idx->pte);
+	GEM_BUG_ON(idx->pdpe >= i915_pdpes_per_pdp(&ppgtt->base));
+	vaddr = kmap_atomic_px(pdp->page_directory[idx->pdpe]);
+	do {
+		vaddr[idx->pde] = pde_encode | iter->dma;
+		iter->dma += I915_GTT_PAGE_SIZE_2M;
+		if (iter->dma >= iter->max) {
+			iter->sg = __sg_next(iter->sg);
+			if (!iter->sg) {
+				ret = false;
+				break;
+			}
+
+			iter->dma = sg_dma_address(iter->sg);
+			iter->max = iter->dma + iter->sg->length;
+		}
+
+		if (++idx->pde == I915_PDES) {
+			idx->pde = 0;
+
+			if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
+				idx->pdpe = 0;
+				ret = true;
+				break;
+			}
+
+			kunmap_atomic(vaddr);
+			vaddr = kmap_atomic_px(pdp->page_directory[idx->pdpe]);
+		}
+
+	} while (1);
+	kunmap_atomic(vaddr);
+
+	mark_tlbs_dirty(ppgtt);
+
+	return ret;
+}
+
+static __always_inline bool
 gen8_ppgtt_insert_64K_pte_entries(struct i915_hw_ppgtt *ppgtt,
 				  struct i915_page_directory_pointer *pdp,
 				  struct sgt_dma *iter,
@@ -1018,6 +1068,9 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 	case I915_GTT_PAGE_SIZE_64K:
 		insert_entries = gen8_ppgtt_insert_64K_pte_entries;
 		break;
+	case I915_GTT_PAGE_SIZE_2M:
+		insert_entries = gen8_ppgtt_insert_2M_pde_entries;
+		break;
 	default:
 		MISSING_CASE(page_size);
 		return;
drivers/gpu/drm/i915/i915_gem_gtt.h +1 -0
index d948808fcf6a..cfe31db6b400 100644
@@ -159,6 +159,7 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT(i, x)			((u64)(x) << ((i) * 8))
 
 #define GEN8_PDE_IPS_64K BIT(11)
+#define GEN8_PDE_PS_2M   BIT(7)
 
 struct sg_table;
 
Signature · 6 lines
2.9.3

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

PATCH 11/18 drm/i915: support inserting 1G pages in the ppgtt

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 45 +++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_gem_gtt.h |  2 ++
 2 files changed, 47 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +45 -0
index 9dc12955f557..5269092ba048 100644
@@ -848,6 +848,48 @@ static __always_inline struct gen8_insert_pte gen8_insert_pte(u64 start)
 }
 
 static __always_inline bool
+gen8_ppgtt_insert_1G_pdpe_entries(struct i915_hw_ppgtt *ppgtt,
+				  struct i915_page_directory_pointer *pdp,
+				  struct sgt_dma *iter,
+				  struct gen8_insert_pte *idx,
+				  enum i915_cache_level cache_level)
+{
+	const gen8_pte_t pdpe_encode = gen8_pte_encode(GEN8_PDPE_PS_1G,
+						       cache_level);
+	gen8_pte_t *vaddr;
+	bool ret;
+
+	GEM_BUG_ON(idx->pte);
+	GEM_BUG_ON(idx->pde);
+	GEM_BUG_ON(idx->pdpe >= i915_pdpes_per_pdp(&ppgtt->base));
+	vaddr = kmap_atomic_px(pdp);
+	do {
+		vaddr[idx->pdpe] = pdpe_encode | iter->dma;
+		iter->dma += I915_GTT_PAGE_SIZE_1G;
+		if (iter->dma >= iter->max) {
+			iter->sg = __sg_next(iter->sg);
+			if (!iter->sg) {
+				ret = false;
+				break;
+			}
+
+			iter->dma = sg_dma_address(iter->sg);
+			iter->max = iter->dma + iter->sg->length;
+		}
+
+		if (++idx->pdpe == GEN8_PML4ES_PER_PML4) {
+			idx->pdpe = 0;
+			ret = true;
+			break;
+		}
+
+	} while (1);
+	kunmap_atomic(vaddr);
+
+	return ret;
+}
+
+static __always_inline bool
 gen8_ppgtt_insert_2M_pde_entries(struct i915_hw_ppgtt *ppgtt,
 				 struct i915_page_directory_pointer *pdp,
 				 struct sgt_dma *iter,
@@ -1071,6 +1113,9 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm,
 	case I915_GTT_PAGE_SIZE_2M:
 		insert_entries = gen8_ppgtt_insert_2M_pde_entries;
 		break;
+	case I915_GTT_PAGE_SIZE_1G:
+		insert_entries = gen8_ppgtt_insert_1G_pdpe_entries;
+		break;
 	default:
 		MISSING_CASE(page_size);
 		return;
drivers/gpu/drm/i915/i915_gem_gtt.h +2 -0
index cfe31db6b400..8b970e9e764c 100644
@@ -161,6 +161,8 @@ typedef u64 gen8_ppgtt_pml4e_t;
 #define GEN8_PDE_IPS_64K BIT(11)
 #define GEN8_PDE_PS_2M   BIT(7)
 
+#define GEN8_PDPE_PS_1G  BIT(7)
+
 struct sg_table;
 
 struct intel_rotation_info {
Signature · 6 lines
2.9.3

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

PATCH 12/18 drm/i915: disable GTT cache for huge-pages

In reply to Matthew Auld

As hinted by the comment and from actually testing 2M pages on a BDW machine with the GTT cache enabled, we are definitely going to need keep it disabled.

---
 drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_pm.c +6 -6
index 570bd603f401..2bb49bada4ea 100644
@@ -7544,10 +7544,10 @@ static void broadwell_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, 0);
 
 	/* WaKVMNotificationOnConfigChange:bdw */
 	I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1)
@@ -7823,10 +7823,10 @@ static void cherryview_init_clock_gating(struct drm_i915_private *dev_priv)
 	gen8_set_l3sqc_credits(dev_priv, 38, 2);
 
 	/*
-	 * 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, 0);
 }
 
 static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
Signature · 6 lines
2.9.3

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

PATCH 13/18 drm/i915/selftests: exercise 4K and 64K mm insertion

In reply to Matthew Auld

Mock test filling an address space with 4K and 64K objects, in the hope of exercising the page color adjust fun.

v2: s/roundup/round_up

---
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 68 +++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +68 -0
index 259b5e139df1..0963dcb67996 100644
@@ -31,6 +31,7 @@
 #include "mock_context.h"
 #include "mock_drm.h"
 #include "mock_gem_device.h"
+#include "mock_gtt.h"
 
 static void fake_free_pages(struct drm_i915_gem_object *obj,
 			    struct sg_table *pages)
@@ -1307,6 +1308,72 @@ static int igt_gtt_reserve(void *arg)
 	return err;
 }
 
+static int igt_ppgtt_page_color(void *arg)
+{
+	struct drm_mm mm;
+	struct drm_mm_node *node, *prev, *next;
+	unsigned long page_colors[] = {
+		I915_GTT_PAGE_SIZE,
+		I915_GTT_PAGE_SIZE_64K,
+	};
+	int idx = 0;
+	u64 count = 0;
+	u64 size;
+
+	drm_mm_init(&mm, 0, U64_MAX);
+	mm.color_adjust = i915_page_color_adjust;
+
+	/* Running out of memory is okay. */
+
+	for_each_prime_number_from(size, 0, U64_MAX) {
+		node = kzalloc(sizeof(*node), GFP_KERNEL);
+		if (!node) {
+			pr_info("finished test early, unable to allocate node, count=%llu\n", count);
+			break;
+		}
+
+		size = round_up(size, page_colors[idx]);
+
+		if (drm_mm_insert_node_in_range(&mm, node, size,
+						page_colors[idx],
+						page_colors[idx],
+						0, U64_MAX,
+						DRM_MM_INSERT_BEST)) {
+			pr_info("test finished, unable to insert node: color=%lu, size=%llx, count=%llu\n",
+				page_colors[idx], size, count);
+			kfree(node);
+			break;
+		}
+
+		GEM_BUG_ON(!IS_ALIGNED(node->start, node->color));
+		GEM_BUG_ON(!IS_ALIGNED(node->size, node->color));
+
+		/* We can't mix 4K and 64K pte's in the same pt. */
+
+		prev = list_prev_entry(node, node_list);
+		if (i915_node_color_differs(prev, node->color))
+			GEM_BUG_ON(prev->start >> GEN8_PDE_SHIFT ==
+				   node->start >> GEN8_PDE_SHIFT);
+
+		next = list_next_entry(node, node_list);
+		if (i915_node_color_differs(next, node->color))
+			GEM_BUG_ON(((next->start + next->size) >> GEN8_PDE_SHIFT) ==
+				   ((node->start + node->size) >> GEN8_PDE_SHIFT));
+
+		idx ^= 1;
+		++count;
+	}
+
+	drm_mm_for_each_node_safe(node, next, &mm) {
+		drm_mm_remove_node(node);
+		kfree(node);
+	}
+
+	drm_mm_takedown(&mm);
+
+	return 0;
+}
+
 static int igt_gtt_insert(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
@@ -1523,6 +1590,7 @@ int i915_gem_gtt_mock_selftests(void)
 		SUBTEST(igt_mock_fill),
 		SUBTEST(igt_gtt_reserve),
 		SUBTEST(igt_gtt_insert),
+		SUBTEST(igt_ppgtt_page_color),
 	};
 	struct drm_i915_private *i915;
 	int err;
Signature · 6 lines
2.9.3

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

PATCH 14/18 drm/i915/selftests: modify the gtt tests to also exercise huge pages

In reply to Matthew Auld

v2: s/roundup/round_up
s/rounddown/round_down

---
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 123 ++++++++++++++++++--------
 drivers/gpu/drm/i915/selftests/mock_gtt.c     |   3 +
 2 files changed, 89 insertions(+), 37 deletions(-)
drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +86 -37
index 0963dcb67996..e735de3d9975 100644
@@ -92,12 +92,14 @@ static const struct drm_i915_gem_object_ops fake_ops = {
 };
 
 static struct drm_i915_gem_object *
-fake_dma_object(struct drm_i915_private *i915, u64 size)
+fake_dma_object(struct drm_i915_private *i915, u64 size, unsigned int page_size)
 {
 	struct drm_i915_gem_object *obj;
 
 	GEM_BUG_ON(!size);
-	GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE));
+	GEM_BUG_ON(!is_valid_gtt_page_size(page_size));
+
+	size = round_up(size, page_size);
 
 	if (overflows_type(size, obj->base.size))
 		return ERR_PTR(-E2BIG);
@@ -107,8 +109,13 @@ fake_dma_object(struct drm_i915_private *i915, u64 size)
 		goto err;
 
 	drm_gem_private_object_init(&i915->drm, &obj->base, size);
+
 	i915_gem_object_init(obj, &fake_ops);
 
+	obj->gtt_page_size = obj->page_size = page_size;
+
+	GEM_BUG_ON(!IS_ALIGNED(obj->base.size, obj->page_size));
+
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 	obj->cache_level = I915_CACHE_NONE;
@@ -194,13 +201,14 @@ static int igt_ppgtt_alloc(void *arg)
 static int lowlevel_hole(struct drm_i915_private *i915,
 			 struct i915_address_space *vm,
 			 u64 hole_start, u64 hole_end,
+			 unsigned int page_size,
 			 unsigned long end_time)
 {
 	I915_RND_STATE(seed_prng);
 	unsigned int size;
 
 	/* Keep creating larger objects until one cannot fit into the hole */
-	for (size = 12; (hole_end - hole_start) >> size; size++) {
+	for (size = ilog2(page_size); (hole_end - hole_start) >> size; size++) {
 		I915_RND_SUBSTATE(prng, seed_prng);
 		struct drm_i915_gem_object *obj;
 		unsigned int *order, count, n;
@@ -226,7 +234,7 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 		 * memory. We expect to hit -ENOMEM.
 		 */
 
-		obj = fake_dma_object(i915, BIT_ULL(size));
+		obj = fake_dma_object(i915, BIT_ULL(size), page_size);
 		if (IS_ERR(obj)) {
 			kfree(order);
 			break;
@@ -303,18 +311,25 @@ static void close_object_list(struct list_head *objects,
 static int fill_hole(struct drm_i915_private *i915,
 		     struct i915_address_space *vm,
 		     u64 hole_start, u64 hole_end,
+		     unsigned int page_size,
 		     unsigned long end_time)
 {
 	const u64 hole_size = hole_end - hole_start;
 	struct drm_i915_gem_object *obj;
-	const unsigned long max_pages =
-		min_t(u64, ULONG_MAX - 1, hole_size/2 >> PAGE_SHIFT);
-	const unsigned long max_step = max(int_sqrt(max_pages), 2UL);
-	unsigned long npages, prime, flags;
+	const unsigned page_shift = ilog2(page_size);
+	unsigned long max_pages, max_step, npages, prime, flags;
 	struct i915_vma *vma;
 	LIST_HEAD(objects);
 	int err;
 
+	hole_start = round_up(hole_start, page_size);
+	hole_end = round_down(hole_end, page_size);
+
+	GEM_BUG_ON(hole_start >= hole_end);
+
+	max_pages = min_t(u64, ULONG_MAX - 1, hole_size/2 >> page_shift);
+	max_step = max(int_sqrt(max_pages), 2UL);
+
 	/* Try binding many VMA working inwards from either edge */
 
 	flags = PIN_OFFSET_FIXED | PIN_USER;
@@ -323,7 +338,7 @@ static int fill_hole(struct drm_i915_private *i915,
 
 	for_each_prime_number_from(prime, 2, max_step) {
 		for (npages = 1; npages <= max_pages; npages *= prime) {
-			const u64 full_size = npages << PAGE_SHIFT;
+			const u64 full_size = npages << page_shift;
 			const struct {
 				const char *name;
 				u64 offset;
@@ -334,7 +349,7 @@ static int fill_hole(struct drm_i915_private *i915,
 				{ }
 			}, *p;
 
-			obj = fake_dma_object(i915, full_size);
+			obj = fake_dma_object(i915, full_size, page_size);
 			if (IS_ERR(obj))
 				break;
 
@@ -359,7 +374,7 @@ static int fill_hole(struct drm_i915_private *i915,
 						offset -= obj->base.size;
 					}
 
-					err = i915_vma_pin(vma, 0, 0, offset | flags);
+					err = i915_vma_pin(vma, 0, page_size, offset | flags);
 					if (err) {
 						pr_err("%s(%s) pin (forward) failed with err=%d on size=%lu pages (prime=%lu), offset=%llx\n",
 						       __func__, p->name, err, npages, prime, offset);
@@ -367,7 +382,7 @@ static int fill_hole(struct drm_i915_private *i915,
 					}
 
 					if (!drm_mm_node_allocated(&vma->node) ||
-					    i915_vma_misplaced(vma, 0, 0, offset | flags)) {
+					    i915_vma_misplaced(vma, 0, page_size, offset | flags)) {
 						pr_err("%s(%s) (forward) insert failed: vma.node=%llx + %llx [allocated? %d], expected offset %llx\n",
 						       __func__, p->name, vma->node.start, vma->node.size, drm_mm_node_allocated(&vma->node),
 						       offset);
@@ -397,7 +412,7 @@ static int fill_hole(struct drm_i915_private *i915,
 					}
 
 					if (!drm_mm_node_allocated(&vma->node) ||
-					    i915_vma_misplaced(vma, 0, 0, offset | flags)) {
+					    i915_vma_misplaced(vma, 0, page_size, offset | flags)) {
 						pr_err("%s(%s) (forward) moved vma.node=%llx + %llx, expected offset %llx\n",
 						       __func__, p->name, vma->node.start, vma->node.size,
 						       offset);
@@ -432,7 +447,7 @@ static int fill_hole(struct drm_i915_private *i915,
 						offset -= obj->base.size;
 					}
 
-					err = i915_vma_pin(vma, 0, 0, offset | flags);
+					err = i915_vma_pin(vma, 0, page_size, offset | flags);
 					if (err) {
 						pr_err("%s(%s) pin (backward) failed with err=%d on size=%lu pages (prime=%lu), offset=%llx\n",
 						       __func__, p->name, err, npages, prime, offset);
@@ -440,7 +455,7 @@ static int fill_hole(struct drm_i915_private *i915,
 					}
 
 					if (!drm_mm_node_allocated(&vma->node) ||
-					    i915_vma_misplaced(vma, 0, 0, offset | flags)) {
+					    i915_vma_misplaced(vma, 0, page_size, offset | flags)) {
 						pr_err("%s(%s) (backward) insert failed: vma.node=%llx + %llx [allocated? %d], expected offset %llx\n",
 						       __func__, p->name, vma->node.start, vma->node.size, drm_mm_node_allocated(&vma->node),
 						       offset);
@@ -470,7 +485,7 @@ static int fill_hole(struct drm_i915_private *i915,
 					}
 
 					if (!drm_mm_node_allocated(&vma->node) ||
-					    i915_vma_misplaced(vma, 0, 0, offset | flags)) {
+					    i915_vma_misplaced(vma, 0, page_size, offset | flags)) {
 						pr_err("%s(%s) (backward) moved vma.node=%llx + %llx [allocated? %d], expected offset %llx\n",
 						       __func__, p->name, vma->node.start, vma->node.size, drm_mm_node_allocated(&vma->node),
 						       offset);
@@ -514,11 +529,13 @@ static int fill_hole(struct drm_i915_private *i915,
 static int walk_hole(struct drm_i915_private *i915,
 		     struct i915_address_space *vm,
 		     u64 hole_start, u64 hole_end,
+		     unsigned int page_size,
 		     unsigned long end_time)
 {
 	const u64 hole_size = hole_end - hole_start;
+	const unsigned page_shift = ilog2(page_size);
 	const unsigned long max_pages =
-		min_t(u64, ULONG_MAX - 1, hole_size >> PAGE_SHIFT);
+		min_t(u64, ULONG_MAX - 1, hole_size >> page_shift);
 	unsigned long flags;
 	u64 size;
 
@@ -534,7 +551,7 @@ static int walk_hole(struct drm_i915_private *i915,
 		u64 addr;
 		int err = 0;
 
-		obj = fake_dma_object(i915, size << PAGE_SHIFT);
+		obj = fake_dma_object(i915, size << page_shift, page_size);
 		if (IS_ERR(obj))
 			break;
 
@@ -547,7 +564,7 @@ static int walk_hole(struct drm_i915_private *i915,
 		for (addr = hole_start;
 		     addr + obj->base.size < hole_end;
 		     addr += obj->base.size) {
-			err = i915_vma_pin(vma, 0, 0, addr | flags);
+			err = i915_vma_pin(vma, 0, page_size, addr | flags);
 			if (err) {
 				pr_err("%s bind failed at %llx + %llx [hole %llx- %llx] with err=%d\n",
 				       __func__, addr, vma->size,
@@ -557,7 +574,7 @@ static int walk_hole(struct drm_i915_private *i915,
 			i915_vma_unpin(vma);
 
 			if (!drm_mm_node_allocated(&vma->node) ||
-			    i915_vma_misplaced(vma, 0, 0, addr | flags)) {
+			    i915_vma_misplaced(vma, 0, page_size, addr | flags)) {
 				pr_err("%s incorrect at %llx + %llx\n",
 				       __func__, addr, vma->size);
 				err = -EINVAL;
@@ -596,6 +613,7 @@ static int walk_hole(struct drm_i915_private *i915,
 static int pot_hole(struct drm_i915_private *i915,
 		    struct i915_address_space *vm,
 		    u64 hole_start, u64 hole_end,
+		    unsigned int page_size,
 		    unsigned long end_time)
 {
 	struct drm_i915_gem_object *obj;
@@ -608,7 +626,7 @@ static int pot_hole(struct drm_i915_private *i915,
 	if (i915_is_ggtt(vm))
 		flags |= PIN_GLOBAL;
 
-	obj = i915_gem_object_create_internal(i915, 2 * I915_GTT_PAGE_SIZE);
+	obj = fake_dma_object(i915, 2 * page_size, page_size);
 	if (IS_ERR(obj))
 		return PTR_ERR(obj);
 
@@ -620,15 +638,15 @@ static int pot_hole(struct drm_i915_private *i915,
 
 	/* Insert a pair of pages across every pot boundary within the hole */
 	for (pot = fls64(hole_end - 1) - 1;
-	     pot > ilog2(2 * I915_GTT_PAGE_SIZE);
+	     pot > ilog2(2 * page_size);
 	     pot--) {
 		u64 step = BIT_ULL(pot);
 		u64 addr;
 
-		for (addr = round_up(hole_start + I915_GTT_PAGE_SIZE, step) - I915_GTT_PAGE_SIZE;
-		     addr <= round_down(hole_end - 2*I915_GTT_PAGE_SIZE, step) - I915_GTT_PAGE_SIZE;
+		for (addr = round_up(hole_start + page_size, step) - page_size;
+		     addr <= round_down(hole_end - 2*page_size, step) - page_size;
 		     addr += step) {
-			err = i915_vma_pin(vma, 0, 0, addr | flags);
+			err = i915_vma_pin(vma, 0, page_size, addr | flags);
 			if (err) {
 				pr_err("%s failed to pin object at %llx in hole [%llx - %llx], with err=%d\n",
 				       __func__,
@@ -672,6 +690,7 @@ static int pot_hole(struct drm_i915_private *i915,
 static int drunk_hole(struct drm_i915_private *i915,
 		      struct i915_address_space *vm,
 		      u64 hole_start, u64 hole_end,
+		      unsigned int page_size,
 		      unsigned long end_time)
 {
 	I915_RND_STATE(prng);
@@ -683,7 +702,7 @@ static int drunk_hole(struct drm_i915_private *i915,
 		flags |= PIN_GLOBAL;
 
 	/* Keep creating larger objects until one cannot fit into the hole */
-	for (size = 12; (hole_end - hole_start) >> size; size++) {
+	for (size = ilog2(page_size); (hole_end - hole_start) >> size; size++) {
 		struct drm_i915_gem_object *obj;
 		unsigned int *order, count, n;
 		struct i915_vma *vma;
@@ -707,7 +726,7 @@ static int drunk_hole(struct drm_i915_private *i915,
 		 * memory. We expect to hit -ENOMEM.
 		 */
 
-		obj = fake_dma_object(i915, BIT_ULL(size));
+		obj = fake_dma_object(i915, BIT_ULL(size), page_size);
 		if (IS_ERR(obj)) {
 			kfree(order);
 			break;
@@ -724,6 +743,8 @@ static int drunk_hole(struct drm_i915_private *i915,
 		for (n = 0; n < count; n++) {
 			u64 addr = hole_start + order[n] * BIT_ULL(size);
 
+			GEM_BUG_ON(!IS_ALIGNED(addr, page_size));
+
 			err = i915_vma_pin(vma, 0, 0, addr | flags);
 			if (err) {
 				pr_err("%s failed to pin object at %llx + %llx in hole [%llx - %llx], with err=%d\n",
@@ -735,7 +756,7 @@ static int drunk_hole(struct drm_i915_private *i915,
 			}
 
 			if (!drm_mm_node_allocated(&vma->node) ||
-			    i915_vma_misplaced(vma, 0, 0, addr | flags)) {
+			    i915_vma_misplaced(vma, 0, page_size, addr | flags)) {
 				pr_err("%s incorrect at %llx + %llx\n",
 				       __func__, addr, BIT_ULL(size));
 				i915_vma_unpin(vma);
@@ -772,11 +793,12 @@ static int drunk_hole(struct drm_i915_private *i915,
 static int __shrink_hole(struct drm_i915_private *i915,
 			 struct i915_address_space *vm,
 			 u64 hole_start, u64 hole_end,
+			 unsigned int page_size,
 			 unsigned long end_time)
 {
 	struct drm_i915_gem_object *obj;
 	unsigned long flags = PIN_OFFSET_FIXED | PIN_USER;
-	unsigned int order = 12;
+	unsigned int order = ilog2(page_size);
 	LIST_HEAD(objects);
 	int err = 0;
 	u64 addr;
@@ -787,7 +809,7 @@ static int __shrink_hole(struct drm_i915_private *i915,
 		u64 size = BIT_ULL(order++);
 
 		size = min(size, hole_end - addr);
-		obj = fake_dma_object(i915, size);
+		obj = fake_dma_object(i915, size, page_size);
 		if (IS_ERR(obj)) {
 			err = PTR_ERR(obj);
 			break;
@@ -803,7 +825,7 @@ static int __shrink_hole(struct drm_i915_private *i915,
 
 		GEM_BUG_ON(vma->size != size);
 
-		err = i915_vma_pin(vma, 0, 0, addr | flags);
+		err = i915_vma_pin(vma, 0, page_size, addr | flags);
 		if (err) {
 			pr_err("%s failed to pin object at %llx + %llx in hole [%llx - %llx], with err=%d\n",
 			       __func__, addr, size, hole_start, hole_end, err);
@@ -811,7 +833,7 @@ static int __shrink_hole(struct drm_i915_private *i915,
 		}
 
 		if (!drm_mm_node_allocated(&vma->node) ||
-		    i915_vma_misplaced(vma, 0, 0, addr | flags)) {
+		    i915_vma_misplaced(vma, 0, page_size, addr | flags)) {
 			pr_err("%s incorrect at %llx + %llx\n",
 			       __func__, addr, size);
 			i915_vma_unpin(vma);
@@ -838,6 +860,7 @@ static int __shrink_hole(struct drm_i915_private *i915,
 static int shrink_hole(struct drm_i915_private *i915,
 		       struct i915_address_space *vm,
 		       u64 hole_start, u64 hole_end,
+		       unsigned int page_size,
 		       unsigned long end_time)
 {
 	unsigned long prime;
@@ -848,7 +871,8 @@ static int shrink_hole(struct drm_i915_private *i915,
 
 	for_each_prime_number_from(prime, 0, ULONG_MAX - 1) {
 		vm->fault_attr.interval = prime;
-		err = __shrink_hole(i915, vm, hole_start, hole_end, end_time);
+		err = __shrink_hole(i915, vm, hole_start, hole_end, page_size,
+				    end_time);
 		if (err)
 			break;
 	}
@@ -862,12 +886,20 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv,
 			  int (*func)(struct drm_i915_private *i915,
 				      struct i915_address_space *vm,
 				      u64 hole_start, u64 hole_end,
+				      unsigned int page_size,
 				      unsigned long end_time))
 {
 	struct drm_file *file;
 	struct i915_hw_ppgtt *ppgtt;
 	IGT_TIMEOUT(end_time);
-	int err;
+	unsigned int page_sizes[] = {
+		I915_GTT_PAGE_SIZE_4K,
+		I915_GTT_PAGE_SIZE_64K,
+		I915_GTT_PAGE_SIZE_2M,
+		I915_GTT_PAGE_SIZE_1G,
+	};
+	int err = 0;
+	int i;
 
 	if (!USES_FULL_PPGTT(dev_priv))
 		return 0;
@@ -885,7 +917,11 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv,
 	GEM_BUG_ON(offset_in_page(ppgtt->base.total));
 	GEM_BUG_ON(ppgtt->base.closed);
 
-	err = func(dev_priv, &ppgtt->base, 0, ppgtt->base.total, end_time);
+	for (i = 0; i < ARRAY_SIZE(page_sizes); ++i) {
+		if (SUPPORTS_PAGE_SIZE(dev_priv, page_sizes[i]))
+			err = func(dev_priv, &ppgtt->base, 0, ppgtt->base.total,
+				   page_sizes[i], end_time);
+	}
 
 	i915_ppgtt_close(&ppgtt->base);
 	i915_ppgtt_put(ppgtt);
@@ -941,6 +977,7 @@ static int exercise_ggtt(struct drm_i915_private *i915,
 			 int (*func)(struct drm_i915_private *i915,
 				     struct i915_address_space *vm,
 				     u64 hole_start, u64 hole_end,
+				     unsigned int page_size,
 				     unsigned long end_time))
 {
 	struct i915_ggtt *ggtt = &i915->ggtt;
@@ -962,7 +999,8 @@ static int exercise_ggtt(struct drm_i915_private *i915,
 		if (hole_start >= hole_end)
 			continue;
 
-		err = func(i915, &ggtt->base, hole_start, hole_end, end_time);
+		err = func(i915, &ggtt->base, hole_start, hole_end,
+			   I915_GTT_PAGE_SIZE, end_time);
 		if (err)
 			break;
 
@@ -1105,12 +1143,20 @@ static int exercise_mock(struct drm_i915_private *i915,
 			 int (*func)(struct drm_i915_private *i915,
 				     struct i915_address_space *vm,
 				     u64 hole_start, u64 hole_end,
+				     unsigned int page_size,
 				     unsigned long end_time))
 {
 	struct i915_gem_context *ctx;
 	struct i915_hw_ppgtt *ppgtt;
 	IGT_TIMEOUT(end_time);
+	unsigned int page_sizes[] = {
+		I915_GTT_PAGE_SIZE_4K,
+		I915_GTT_PAGE_SIZE_64K,
+		I915_GTT_PAGE_SIZE_2M,
+		I915_GTT_PAGE_SIZE_1G,
+	};
 	int err;
+	int i;
 
 	ctx = mock_context(i915, "mock");
 	if (!ctx)
@@ -1119,7 +1165,10 @@ static int exercise_mock(struct drm_i915_private *i915,
 	ppgtt = ctx->ppgtt;
 	GEM_BUG_ON(!ppgtt);
 
-	err = func(i915, &ppgtt->base, 0, ppgtt->base.total, end_time);
+	for (i = 0; i < ARRAY_SIZE(page_sizes); ++i) {
+		err = func(i915, &ppgtt->base, 0, ppgtt->base.total,
+			   page_sizes[i], end_time);
+	}
 
 	mock_context_close(ctx);
 	return err;
drivers/gpu/drm/i915/selftests/mock_gtt.c +3 -0
index 38532a008387..688d4f554a48 100644
@@ -88,6 +88,9 @@ mock_ppgtt(struct drm_i915_private *i915,
 	ppgtt->base.unbind_vma = mock_unbind_ppgtt;
 	ppgtt->base.cleanup = mock_cleanup;
 
+	/* For mock testing huge-page support */
+	ppgtt->base.mm.color_adjust = i915_page_color_adjust;
+
 	return ppgtt;
 }
 
Signature · 6 lines
2.9.3

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

PATCH 15/18 drm/i915/selftests: exercise evict-for-node page coloring

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/selftests/i915_gem_evict.c | 117 ++++++++++++++++++++++--
 1 file changed, 111 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/selftests/i915_gem_evict.c +111 -6
index 8c0b4dc9de3d..780585a202ba 100644
@@ -25,6 +25,7 @@
 #include "../i915_selftest.h"
 
 #include "mock_gem_device.h"
+#include "mock_gtt.h"
 
 static int populate_ggtt(struct drm_i915_private *i915)
 {
@@ -62,11 +63,11 @@ static int populate_ggtt(struct drm_i915_private *i915)
 	return 0;
 }
 
-static void unpin_ggtt(struct drm_i915_private *i915)
+static void unpin_vm(struct i915_address_space *vm)
 {
 	struct i915_vma *vma;
 
-	list_for_each_entry(vma, &i915->ggtt.base.inactive_list, vm_link)
+	list_for_each_entry(vma, &vm->inactive_list, vm_link)
 		i915_vma_unpin(vma);
 }
 
@@ -110,7 +111,7 @@ static int igt_evict_something(void *arg)
 		goto cleanup;
 	}
 
-	unpin_ggtt(i915);
+	unpin_vm(&ggtt->base);
 
 	/* Everything is unpinned, we should be able to evict something */
 	err = i915_gem_evict_something(&ggtt->base,
@@ -187,7 +188,7 @@ static int igt_evict_for_vma(void *arg)
 		goto cleanup;
 	}
 
-	unpin_ggtt(i915);
+	unpin_vm(&ggtt->base);
 
 	/* Everything is unpinned, we should be able to evict the node */
 	err = i915_gem_evict_for_node(&ggtt->base, &target, 0);
@@ -287,12 +288,115 @@ static int igt_evict_for_cache_color(void *arg)
 	err = 0;
 
 cleanup:
-	unpin_ggtt(i915);
+	unpin_vm(&ggtt->base);
 	cleanup_objects(i915);
 	ggtt->base.mm.color_adjust = NULL;
 	return err;
 }
 
+static int igt_evict_for_page_color(void *arg)
+{
+	struct drm_i915_private *i915 = arg;
+	struct i915_hw_ppgtt *ppgtt = mock_ppgtt(i915, "mock-page-color");
+	const unsigned long flags = PIN_USER | PIN_OFFSET_FIXED;
+	struct drm_mm_node target = {
+		/* Straddle the end of the first page-table boundary */
+		.start = (1 << GEN8_PDE_SHIFT) - I915_GTT_PAGE_SIZE_64K,
+		.size = I915_GTT_PAGE_SIZE_64K * 2,
+		.color = I915_GTT_PAGE_SIZE_4K,
+	};
+	struct drm_i915_gem_object *obj;
+	struct i915_vma *vma;
+	int err;
+
+	/* The mock ppgtt mm.color_adjust should be set to
+	 * i915_page_color_adjust.
+	 */
+	GEM_BUG_ON(!i915_vm_has_page_coloring(&ppgtt->base));
+
+	obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		err = PTR_ERR(obj);
+		goto cleanup;
+	}
+
+	vma = i915_vma_instance(obj, &ppgtt->base, NULL);
+	if (IS_ERR(vma)) {
+		pr_err("[0]i915_vma_instance failed\n");
+		err = PTR_ERR(vma);
+		goto cleanup;
+	}
+
+	err = i915_vma_pin(vma, 0, 0, flags);
+	if (err) {
+		pr_err("[0]i915_vma_pin failed with err=%d\n", err);
+		goto cleanup;
+	}
+
+	obj = i915_gem_object_create_internal(i915, I915_GTT_PAGE_SIZE);
+	if (IS_ERR(obj)) {
+		unpin_vm(&ppgtt->base);
+		err = PTR_ERR(obj);
+		goto cleanup;
+	}
+
+	vma = i915_vma_instance(obj, &ppgtt->base, NULL);
+	if (IS_ERR(vma)) {
+		pr_err("[1]i915_vma_instance failed\n");
+		err = PTR_ERR(vma);
+		goto cleanup;
+	}
+
+	err = i915_vma_pin(vma, 0, 0,
+			   ((2 << GEN8_PDE_SHIFT) - I915_GTT_PAGE_SIZE_4K) |
+			   flags);
+	if (err) {
+		unpin_vm(&ppgtt->base);
+		pr_err("[1]i915_vma_pin failed with err=%d\n", err);
+		goto cleanup;
+	}
+
+	/* Target the page-table boundary between the two already *pinned* gem
+	 * objects with the same page color - should succeed.
+	 */
+	err = i915_gem_evict_for_node(&ppgtt->base, &target, 0);
+	if (err) {
+		unpin_vm(&ppgtt->base);
+		pr_err("[0]i915_gem_evict_for_node returned err=%d\n", err);
+		goto cleanup;
+	}
+
+	target.color = I915_GTT_PAGE_SIZE_64K;
+
+	/* Again target the page-table boundary between the two already *pinned*
+	 * gem objects, but this time with conflicting page colors - should
+	 * fail.
+	 */
+	err = i915_gem_evict_for_node(&ppgtt->base, &target, 0);
+	if (!err) {
+		unpin_vm(&ppgtt->base);
+		pr_err("[1]i915_gem_evict_for_node returned err=%d\n", err);
+		err = -EINVAL;
+		goto cleanup;
+	}
+
+	unpin_vm(&ppgtt->base);
+
+	/* And finaly target the page-table boundary between the two now
+	 * *unpinned* gem objects, again with conflicting page colors - should
+	 * now succeed.
+	 */
+	err = i915_gem_evict_for_node(&ppgtt->base, &target, 0);
+	if (err)
+		pr_err("[2]i915_gem_evict_for_node returned err=%d\n", err);
+
+cleanup:
+	i915_ppgtt_close(&ppgtt->base);
+	i915_ppgtt_put(ppgtt);
+	cleanup_objects(i915);
+	return err;
+}
+
 static int igt_evict_vm(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
@@ -313,7 +417,7 @@ static int igt_evict_vm(void *arg)
 		goto cleanup;
 	}
 
-	unpin_ggtt(i915);
+	unpin_vm(&ggtt->base);
 
 	err = i915_gem_evict_vm(&ggtt->base, false);
 	if (err) {
@@ -333,6 +437,7 @@ int i915_gem_evict_mock_selftests(void)
 		SUBTEST(igt_evict_something),
 		SUBTEST(igt_evict_for_vma),
 		SUBTEST(igt_evict_for_cache_color),
+		SUBTEST(igt_evict_for_page_color),
 		SUBTEST(igt_evict_vm),
 		SUBTEST(igt_overcommit),
 	};
Signature · 6 lines
2.9.3

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

PATCH 16/18 drm/i915/debugfs: include some huge-page metrics

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_debugfs.c | 38 ++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_debugfs.c +35 -3
index d689e511744e..e8a50481c703 100644
@@ -117,6 +117,23 @@ static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj)
 	return size;
 }
 
+static const char *stringify_page_size(unsigned int page_size)
+{
+	switch(page_size) {
+	case I915_GTT_PAGE_SIZE_4K:
+		return "4K";
+	case I915_GTT_PAGE_SIZE_64K:
+		return "64K";
+	case I915_GTT_PAGE_SIZE_2M:
+		return "2M";
+	case I915_GTT_PAGE_SIZE_1G:
+		return "1G";
+	default:
+		MISSING_CASE(page_size);
+		return "";
+	}
+}
+
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
@@ -128,7 +145,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 
 	lockdep_assert_held(&obj->base.dev->struct_mutex);
 
-	seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s",
+	seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %s %s %02x %02x %s%s%s",
 		   &obj->base,
 		   get_active_flag(obj),
 		   get_pin_flag(obj),
@@ -136,6 +153,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 		   get_global_flag(obj),
 		   get_pin_mapped_flag(obj),
 		   obj->base.size / 1024,
+		   stringify_page_size(obj->page_size),
+		   stringify_page_size(obj->gtt_page_size),
 		   obj->base.read_domains,
 		   obj->base.write_domain,
 		   i915_cache_level_str(dev_priv, obj->cache_level),
@@ -399,8 +418,8 @@ 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;
 	struct drm_file *file;
 	int ret;
@@ -416,6 +435,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;
@@ -429,6 +449,11 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
+
+		if (obj->page_size > PAGE_SIZE) {
+			huge_count++;
+			huge_size += obj->base.size;
+		}
 	}
 	seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
 
@@ -451,6 +476,11 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
+
+		if (obj->page_size > PAGE_SIZE) {
+			huge_count++;
+			huge_size += obj->base.size;
+		}
 	}
 	seq_printf(m, "%u bound objects, %llu bytes\n",
 		   count, size);
@@ -458,6 +488,8 @@ 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, %llu bytes\n",
+		   huge_count, huge_size);
 	seq_printf(m, "%u display objects (pinned), %llu bytes\n",
 		   dpy_count, dpy_size);
 
Signature · 6 lines
2.9.3

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

PATCH 17/18 mm/shmem: tweak the huge-page interface

In reply to Matthew Auld

In its current form huge-pages through shmemfs are controlled at the super-block level, and are currently disabled by default, so to enable huge-pages for a shmem backed gem object we would need to re-mount the fs with the huge= argument, but for drm the mount is not user visible, so good luck with that. The other option is the global sysfs knob shmem_enabled which exposes the same huge= options, with the addition of DENY and FORCE.

Neither option seems really workable, what we probably want is to able to control the use of huge-pages at the time of pinning the backing storage for a particular gem object, and only where it makes sense given the size of the object. One caveat is when we write into the page cache prior to pinning the backing storage. I played around with a bunch of ideas but in the end just settled with driver overridable huge option embedded in shmem_inode_info. Thoughts?

---
 include/linux/shmem_fs.h |  1 +
 mm/shmem.c               | 10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)
include/linux/shmem_fs.h +1 -0
index a7d6bd2a918f..001be751420d 100644
@@ -21,6 +21,7 @@ struct shmem_inode_info {
 	struct shared_policy	policy;		/* NUMA memory alloc policy */
 	struct simple_xattrs	xattrs;		/* list of xattrs */
 	struct inode		vfs_inode;
+	bool                    huge;           /* driver override shmem_huge */
 };
 
 struct shmem_sb_info {
mm/shmem.c +8 -2
index e67d6ba4e98e..879a9e514afe 100644
@@ -1723,6 +1723,9 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
 		/* shmem_symlink() */
 		if (mapping->a_ops != &shmem_aops)
 			goto alloc_nohuge;
+		/* driver override shmem_huge */
+		if (info->huge)
+			goto alloc_huge;
 		if (shmem_huge == SHMEM_HUGE_DENY || sgp_huge == SGP_NOHUGE)
 			goto alloc_nohuge;
 		if (shmem_huge == SHMEM_HUGE_FORCE)
@@ -2000,6 +2003,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	unsigned long inflated_len;
 	unsigned long inflated_addr;
 	unsigned long inflated_offset;
+	struct shmem_inode_info *info = SHMEM_I(file_inode(file));
 
 	if (len > TASK_SIZE)
 		return -ENOMEM;
@@ -2016,7 +2020,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	if (addr > TASK_SIZE - len)
 		return addr;
 
-	if (shmem_huge == SHMEM_HUGE_DENY)
+	if (!info->huge && shmem_huge == SHMEM_HUGE_DENY)
 		return addr;
 	if (len < HPAGE_PMD_SIZE)
 		return addr;
@@ -2030,7 +2034,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	if (uaddr)
 		return addr;
 
-	if (shmem_huge != SHMEM_HUGE_FORCE) {
+	if (!info->huge && shmem_huge != SHMEM_HUGE_FORCE) {
 		struct super_block *sb;
 
 		if (file) {
@@ -4034,6 +4038,8 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
 	loff_t i_size;
 	pgoff_t off;
 
+	if (SHMEM_I(inode)->huge)
+		return true;
 	if (shmem_huge == SHMEM_HUGE_FORCE)
 		return true;
 	if (shmem_huge == SHMEM_HUGE_DENY)
Signature · 6 lines
2.9.3

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

Re: [PATCH 17/18] mm/shmem: tweak the huge-page interface

Quoted 16 lines · Matthew Auld

In its current form huge-pages through shmemfs are controlled at the super-block level, and are currently disabled by default, so to enable huge-pages for a shmem backed gem object we would need to re-mount the fs with the huge= argument, but for drm the mount is not user visible, so good luck with that. The other option is the global sysfs knob shmem_enabled which exposes the same huge= options, with the addition of DENY and FORCE.

Neither option seems really workable, what we probably want is to able to control the use of huge-pages at the time of pinning the backing storage for a particular gem object, and only where it makes sense given the size of the object. One caveat is when we write into the page cache prior to pinning the backing storage. I played around with a bunch of ideas but in the end just settled with driver overridable huge option embedded in shmem_inode_info. Thoughts?

Quoted 1 line

You need to Cc: mm folks and mailing lists for this. Ask scripts/get_maintainers.pl for the full list please. Otherwise this can't ever land (and we're looking at along time of bikeshedding anyway). -Daniel

Quoted 73 lines
---
 include/linux/shmem_fs.h |  1 +
 mm/shmem.c               | 10 ++++++++--
 2 files changed, 9 insertions(+), 2 deletions(-)
include/linux/shmem_fs.h +1 -0
index a7d6bd2a918f..001be751420d 100644
@@ -21,6 +21,7 @@ struct shmem_inode_info {
 	struct shared_policy	policy;		/* NUMA memory alloc policy */
 	struct simple_xattrs	xattrs;		/* list of xattrs */
 	struct inode		vfs_inode;
+	bool                    huge;           /* driver override shmem_huge */
 };
 
 struct shmem_sb_info {
mm/shmem.c +8 -2
index e67d6ba4e98e..879a9e514afe 100644
@@ -1723,6 +1723,9 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
 		/* shmem_symlink() */
 		if (mapping->a_ops != &shmem_aops)
 			goto alloc_nohuge;
+		/* driver override shmem_huge */
+		if (info->huge)
+			goto alloc_huge;
 		if (shmem_huge == SHMEM_HUGE_DENY || sgp_huge == SGP_NOHUGE)
 			goto alloc_nohuge;
 		if (shmem_huge == SHMEM_HUGE_FORCE)
@@ -2000,6 +2003,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	unsigned long inflated_len;
 	unsigned long inflated_addr;
 	unsigned long inflated_offset;
+	struct shmem_inode_info *info = SHMEM_I(file_inode(file));
 
 	if (len > TASK_SIZE)
 		return -ENOMEM;
@@ -2016,7 +2020,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	if (addr > TASK_SIZE - len)
 		return addr;
 
-	if (shmem_huge == SHMEM_HUGE_DENY)
+	if (!info->huge && shmem_huge == SHMEM_HUGE_DENY)
 		return addr;
 	if (len < HPAGE_PMD_SIZE)
 		return addr;
@@ -2030,7 +2034,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
 	if (uaddr)
 		return addr;
 
-	if (shmem_huge != SHMEM_HUGE_FORCE) {
+	if (!info->huge && shmem_huge != SHMEM_HUGE_FORCE) {
 		struct super_block *sb;
 
 		if (file) {
@@ -4034,6 +4038,8 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
 	loff_t i_size;
 	pgoff_t off;
 
+	if (SHMEM_I(inode)->huge)
+		return true;
 	if (shmem_huge == SHMEM_HUGE_FORCE)
 		return true;
 	if (shmem_huge == SHMEM_HUGE_DENY)
Signature · 6 lines
2.9.3

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#40 lore raw

PATCH 18/18 drm/i915: support transparent-huge-pages through shmemfs

In reply to Matthew Auld
---
 drivers/gpu/drm/i915/i915_drv.h |   3 +
 drivers/gpu/drm/i915/i915_gem.c | 187 +++++++++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/i915_vma.c |   8 ++
 3 files changed, 166 insertions(+), 32 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +3 -0
index 838ce22a0a40..07dd4d24b93e 100644
@@ -2672,6 +2672,9 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg)
  * @__pp:	page pointer (output)
  * @__iter:	'struct sgt_iter' (iterator state, internal)
  * @__sgt:	sg_table to iterate over (input)
+ *
+ * Be warned, if we using huge-pages @_pp could be a part of a compound page,
+ * so care must be taken. Too thorny?
  */
 #define for_each_sgt_page(__pp, __iter, __sgt)				\
 	for ((__iter) = __sgt_iter((__sgt)->sgl, false);		\
drivers/gpu/drm/i915/i915_gem.c +155 -32

310 lines not on this page · raw message

drivers/gpu/drm/i915/i915_vma.c +8 -0
index 4043145b4310..af295aa3b49c 100644
@@ -469,6 +469,14 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
 	if (ret)
 		return ret;
 
+	/* We don't know the final gtt page size until *after* we pin the
+	 * backing store, or that's at least the case for the shmem backend.
+	 * Therefore re-adjust the alignment if needed. This is only relevant
+	 * for huge-pages being inserted into the ppgtt.
+	 */
+	if (!i915_is_ggtt(vma->vm) && alignment < obj->gtt_page_size)
+		alignment = obj->gtt_page_size;
+
 	if (i915_vm_has_cache_coloring(vma->vm))
 		color = obj->cache_level;
 	else if (i915_vm_has_page_coloring(vma->vm))
Signature · 6 lines
2.9.3

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#41 lore raw
In reply to Matthew Auld
Quoted 3 lines · Matthew Auld

Same as before, folding in review comments. Notably we now hook in transparent huge pages through by shmem, and *attempt* to deal with all the fun which that brings. Again should be considered very much RFC.

But where's the explanation for persisting with an inflexible design? I still do not like the static page size assignments, and trying to force that down into the GTT, rather than it percolating up. -Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx