2022-04-13 00:05:05

by Robert Beckett

[permalink] [raw]
Subject: [PATCH v3 5/5] drm/i915: stolen memory use ttm backend

refactor stolen memory region to use ttm.
this necessitates using ttm resources to track reserved stolen regions
instead of drm_mm_nodes.

Signed-off-by: Robert Beckett <[email protected]>
---
drivers/gpu/drm/i915/display/intel_fbc.c | 78 ++--
.../gpu/drm/i915/gem/i915_gem_object_types.h | 2 -
drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 416 ++++++------------
drivers/gpu/drm/i915/gem/i915_gem_stolen.h | 21 +-
drivers/gpu/drm/i915/gem/i915_gem_ttm.h | 7 +
drivers/gpu/drm/i915/gt/intel_rc6.c | 4 +-
drivers/gpu/drm/i915/gt/selftest_reset.c | 16 +-
drivers/gpu/drm/i915/i915_debugfs.c | 7 +-
drivers/gpu/drm/i915/i915_drv.h | 5 -
drivers/gpu/drm/i915/intel_region_ttm.c | 36 +-
drivers/gpu/drm/i915/intel_region_ttm.h | 8 +-
drivers/gpu/drm/i915/selftests/mock_region.c | 3 +-
12 files changed, 247 insertions(+), 356 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index b653f3ba7c66..dbad1b6471b8 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -38,6 +38,7 @@
* forcibly disable it to allow proper screen updates.
*/

+#include "gem/i915_gem_stolen.h"
#include <linux/string_helpers.h>

#include <drm/drm_fourcc.h>
@@ -51,6 +52,7 @@
#include "intel_display_types.h"
#include "intel_fbc.h"
#include "intel_frontbuffer.h"
+#include "gem/i915_gem_region.h"

#define for_each_fbc_id(__dev_priv, __fbc_id) \
for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \
@@ -93,8 +95,8 @@ struct intel_fbc {
unsigned int possible_framebuffer_bits;
unsigned int busy_bits;

- struct drm_mm_node compressed_fb;
- struct drm_mm_node compressed_llb;
+ struct ttm_resource *compressed_fb;
+ struct ttm_resource *compressed_llb;

enum intel_fbc_id id;

@@ -332,16 +334,20 @@ static void i8xx_fbc_nuke(struct intel_fbc *fbc)
static void i8xx_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
+ u64 fb_offset = i915_gem_stolen_reserve_offset(fbc->compressed_fb);
+ u64 llb_offset = i915_gem_stolen_reserve_offset(fbc->compressed_llb);

+ GEM_BUG_ON(fb_offset == I915_BO_INVALID_OFFSET);
+ GEM_BUG_ON(llb_offset == I915_BO_INVALID_OFFSET);
GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start,
- fbc->compressed_fb.start, U32_MAX));
+ fb_offset, U32_MAX));
GEM_BUG_ON(range_overflows_end_t(u64, i915->dsm.start,
- fbc->compressed_llb.start, U32_MAX));
+ llb_offset, U32_MAX));

intel_de_write(i915, FBC_CFB_BASE,
- i915->dsm.start + fbc->compressed_fb.start);
+ i915->dsm.start + fb_offset);
intel_de_write(i915, FBC_LL_BASE,
- i915->dsm.start + fbc->compressed_llb.start);
+ i915->dsm.start + llb_offset);
}

static const struct intel_fbc_funcs i8xx_fbc_funcs = {
@@ -449,8 +455,10 @@ static bool g4x_fbc_is_compressing(struct intel_fbc *fbc)
static void g4x_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
+ u64 fb_offset = i915_gem_stolen_reserve_offset(fbc->compressed_fb);

- intel_de_write(i915, DPFC_CB_BASE, fbc->compressed_fb.start);
+ GEM_BUG_ON(fb_offset == I915_BO_INVALID_OFFSET);
+ intel_de_write(i915, DPFC_CB_BASE, fb_offset);
}

static const struct intel_fbc_funcs g4x_fbc_funcs = {
@@ -500,8 +508,10 @@ static bool ilk_fbc_is_compressing(struct intel_fbc *fbc)
static void ilk_fbc_program_cfb(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
+ u64 fb_offset = i915_gem_stolen_reserve_offset(fbc->compressed_fb);

- intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), fbc->compressed_fb.start);
+ GEM_BUG_ON(fb_offset == I915_BO_INVALID_OFFSET);
+ intel_de_write(i915, ILK_DPFC_CB_BASE(fbc->id), fb_offset);
}

static const struct intel_fbc_funcs ilk_fbc_funcs = {
@@ -741,21 +751,24 @@ static int find_compression_limit(struct intel_fbc *fbc,
{
struct drm_i915_private *i915 = fbc->i915;
u64 end = intel_fbc_stolen_end(i915);
- int ret, limit = min_limit;
+ int limit = min_limit;
+ struct ttm_resource *res;

size /= limit;

/* Try to over-allocate to reduce reallocations and fragmentation. */
- ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb,
- size <<= 1, 4096, 0, end);
- if (ret == 0)
+ res = i915_gem_stolen_reserve_range(i915, size <<= 1, 0, end);
+ if (!IS_ERR(res)) {
+ fbc->compressed_fb = res;
return limit;
+ }

for (; limit <= intel_fbc_max_limit(i915); limit <<= 1) {
- ret = i915_gem_stolen_insert_node_in_range(i915, &fbc->compressed_fb,
- size >>= 1, 4096, 0, end);
- if (ret == 0)
+ res = i915_gem_stolen_reserve_range(i915, size >>= 1, 0, end);
+ if (!IS_ERR(res)) {
+ fbc->compressed_fb = res;
return limit;
+ }
}

return 0;
@@ -766,17 +779,18 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,
{
struct drm_i915_private *i915 = fbc->i915;
int ret;
+ struct ttm_resource *res;

- drm_WARN_ON(&i915->drm,
- drm_mm_node_allocated(&fbc->compressed_fb));
- drm_WARN_ON(&i915->drm,
- drm_mm_node_allocated(&fbc->compressed_llb));
+ drm_WARN_ON(&i915->drm, fbc->compressed_fb);
+ drm_WARN_ON(&i915->drm, fbc->compressed_llb);

if (DISPLAY_VER(i915) < 5 && !IS_G4X(i915)) {
- ret = i915_gem_stolen_insert_node(i915, &fbc->compressed_llb,
- 4096, 4096);
- if (ret)
+ res = i915_gem_stolen_reserve_range(i915, 4096, I915_GEM_STOLEN_BIAS, 0);
+ if (IS_ERR(res)) {
+ ret = PTR_ERR(res);
goto err;
+ }
+ fbc->compressed_llb = res;
}

ret = find_compression_limit(fbc, size, min_limit);
@@ -790,15 +804,14 @@ static int intel_fbc_alloc_cfb(struct intel_fbc *fbc,

drm_dbg_kms(&i915->drm,
"reserved %llu bytes of contiguous stolen space for FBC, limit: %d\n",
- fbc->compressed_fb.size, fbc->limit);
+ i915_gem_stolen_reserve_size(fbc->compressed_fb), fbc->limit);

return 0;

err_llb:
- if (drm_mm_node_allocated(&fbc->compressed_llb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_llb);
+ i915_gem_stolen_release_range(i915, fetch_and_zero(&fbc->compressed_llb));
err:
- if (drm_mm_initialized(&i915->mm.stolen))
+ if (IS_ERR(res) && (PTR_ERR(res) == -ENOMEM || PTR_ERR(res) == -ENXIO))
drm_info_once(&i915->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
return -ENOSPC;
}
@@ -815,10 +828,10 @@ static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc)
if (WARN_ON(intel_fbc_hw_is_active(fbc)))
return;

- if (drm_mm_node_allocated(&fbc->compressed_llb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_llb);
- if (drm_mm_node_allocated(&fbc->compressed_fb))
- i915_gem_stolen_remove_node(i915, &fbc->compressed_fb);
+ if (fbc->compressed_llb)
+ i915_gem_stolen_release_range(i915, fetch_and_zero(&fbc->compressed_llb));
+ if (fbc->compressed_fb)
+ i915_gem_stolen_release_range(i915, fetch_and_zero(&fbc->compressed_fb));
}

void intel_fbc_cleanup(struct drm_i915_private *i915)
@@ -1022,9 +1035,10 @@ static bool intel_fbc_is_cfb_ok(const struct intel_plane_state *plane_state)
{
struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
struct intel_fbc *fbc = plane->fbc;
+ u64 fb_size = i915_gem_stolen_reserve_size(fbc->compressed_fb);

return intel_fbc_min_limit(plane_state) <= fbc->limit &&
- intel_fbc_cfb_size(plane_state) <= fbc->compressed_fb.size * fbc->limit;
+ intel_fbc_cfb_size(plane_state) <= fb_size * fbc->limit;
}

static bool intel_fbc_is_ok(const struct intel_plane_state *plane_state)
@@ -1703,7 +1717,7 @@ void intel_fbc_init(struct drm_i915_private *i915)
{
enum intel_fbc_id fbc_id;

- if (!drm_mm_initialized(&i915->mm.stolen))
+ if (!i915->mm.stolen_region)
mkwrite_device_info(i915)->display.fbc_mask = 0;

if (need_fbc_vtd_wa(i915))
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 2c88bdb8ff7c..492600907e99 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -629,8 +629,6 @@ struct drm_i915_gem_object {
} userptr;
#endif

- struct drm_mm_node *stolen;
-
resource_size_t bo_offset;

unsigned long scratch;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 47b5e0e342ab..c246fdb8ca6c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -4,75 +4,101 @@
* Copyright © 2008-2012 Intel Corporation
*/

+#include "drm/ttm/ttm_placement.h"
+#include "gem/i915_gem_object_types.h"
#include <linux/errno.h>
#include <linux/mutex.h>

-#include <drm/drm_mm.h>
#include <drm/i915_drm.h>

#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "gt/intel_gt.h"
#include "gt/intel_region_lmem.h"
+#include "gem/i915_gem_ttm.h"
#include "i915_drv.h"
#include "i915_gem_stolen.h"
#include "i915_reg.h"
#include "i915_utils.h"
#include "i915_vgpu.h"
#include "intel_mchbar_regs.h"
-
-/*
- * The BIOS typically reserves some of the system's memory for the exclusive
- * use of the integrated graphics. This memory is no longer available for
- * use by the OS and so the user finds that his system has less memory
- * available than he put in. We refer to this memory as stolen.
+#include "intel_region_ttm.h"
+
+/**
+ * i915_gem_stolen_reserve_range - reserve a region of space in a given range
+ * @i915: i915 device instance
+ * @size: size of region to reserve
+ * @start: start of search area
+ * @end: end of search area
*
- * The BIOS will allocate its framebuffer from the stolen memory. Our
- * goal is try to reuse that object for our own fbcon which must always
- * be available for panics. Anything else we can reuse the stolen memory
- * for is a boon.
+ * Search for @size amount of free space within the region delimeted by @start and @end.
+ * If found reserve it from future use until later release with @i915_gem_stolen_release_range.
+ *
+ * Return: pointer to resource tracking structure on success, ERR_PTR otherwise
*/
-
-int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915,
- struct drm_mm_node *node, u64 size,
- unsigned alignment, u64 start, u64 end)
+struct ttm_resource *
+i915_gem_stolen_reserve_range(struct drm_i915_private *i915,
+ resource_size_t size,
+ u64 start, u64 end)
{
- int ret;
+ struct intel_memory_region *mem = i915->mm.stolen_region;

- if (!drm_mm_initialized(&i915->mm.stolen))
- return -ENODEV;
-
- /* WaSkipStolenMemoryFirstPage:bdw+ */
- if (GRAPHICS_VER(i915) >= 8 && start < 4096)
- start = 4096;
-
- mutex_lock(&i915->mm.stolen_lock);
- ret = drm_mm_insert_node_in_range(&i915->mm.stolen, node,
- size, alignment, 0,
- start, end, DRM_MM_INSERT_BEST);
- mutex_unlock(&i915->mm.stolen_lock);
+ if (!mem)
+ return ERR_PTR(-ENODEV);
+ return intel_region_ttm_resource_alloc(mem, size, start, end, I915_BO_ALLOC_CONTIGUOUS);
+}

- return ret;
+/**
+ * i915_gem_stolen_reserve_offset - return the offset of the reserved space
+ * @res: pointer to resource tracking structure to check
+ *
+ * Return: The offset of the reserved resource, or I915_BO_INVALID_OFFSET on error
+ */
+u64 i915_gem_stolen_reserve_offset(struct ttm_resource *res)
+{
+ if (!res)
+ return I915_BO_INVALID_OFFSET;
+ return PFN_PHYS(res->start);
}

-int i915_gem_stolen_insert_node(struct drm_i915_private *i915,
- struct drm_mm_node *node, u64 size,
- unsigned alignment)
+/**
+ * i915_gem_stolen_reserve_size - return the reserved size of the reserved space
+ * @res: pointer to resource tracking structure to check
+ *
+ * Return: The size of the reserved resource, or I915_BO_INVALID_OFFSET on error
+ */
+u64 i915_gem_stolen_reserve_size(struct ttm_resource *res)
{
- return i915_gem_stolen_insert_node_in_range(i915, node,
- size, alignment,
- I915_GEM_STOLEN_BIAS,
- U64_MAX);
+ if (!res)
+ return I915_BO_INVALID_OFFSET;
+ return PFN_PHYS(res->num_pages);
}

-void i915_gem_stolen_remove_node(struct drm_i915_private *i915,
- struct drm_mm_node *node)
+/**
+ * i915_gem_stolen_release_range - release the reserved area to be free for allocation again
+ * @i915: i915 device instance
+ * @res: pointer to resource tracking structure allocated via @i915_gem_stolen_reserve_range
+ */
+void i915_gem_stolen_release_range(struct drm_i915_private *i915,
+ struct ttm_resource *res)
{
- mutex_lock(&i915->mm.stolen_lock);
- drm_mm_remove_node(node);
- mutex_unlock(&i915->mm.stolen_lock);
+ struct intel_memory_region *mem = i915->mm.stolen_region;
+
+ intel_region_ttm_resource_free(mem, res);
}

+/*
+ * The BIOS typically reserves some of the system's memory for the exclusive
+ * use of the integrated graphics. This memory is no longer available for
+ * use by the OS and so the user finds that his system has less memory
+ * available than he put in. We refer to this memory as stolen.
+ *
+ * The BIOS will allocate its framebuffer from the stolen memory. Our
+ * goal is try to reuse that object for our own fbcon which must always
+ * be available for panics. Anything else we can reuse the stolen memory
+ * for is a boon.
+ */
+
static int i915_adjust_stolen(struct drm_i915_private *i915,
struct resource *dsm)
{
@@ -173,14 +199,6 @@ static int i915_adjust_stolen(struct drm_i915_private *i915,
return 0;
}

-static void i915_gem_cleanup_stolen(struct drm_i915_private *i915)
-{
- if (!drm_mm_initialized(&i915->mm.stolen))
- return;
-
- drm_mm_takedown(&i915->mm.stolen);
-}
-
static void g4x_get_stolen_reserved(struct drm_i915_private *i915,
struct intel_uncore *uncore,
resource_size_t *base,
@@ -395,8 +413,6 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
resource_size_t reserved_base, stolen_top;
resource_size_t reserved_total, reserved_size;

- mutex_init(&i915->mm.stolen_lock);
-
if (intel_vgpu_active(i915)) {
drm_notice(&i915->drm,
"%s, disabling use of stolen memory\n",
@@ -513,237 +529,28 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
return 0;

/* Basic memrange allocator for stolen space. */
- drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size);
-
- return 0;
+ return intel_region_ttm_init(mem);
}

-static void dbg_poison(struct i915_ggtt *ggtt,
- dma_addr_t addr, resource_size_t size,
- u8 x)
-{
-#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
- if (!drm_mm_node_allocated(&ggtt->error_capture))
- return;
-
- if (ggtt->vm.bind_async_flags & I915_VMA_GLOBAL_BIND)
- return; /* beware stop_machine() inversion */
-
- GEM_BUG_ON(!IS_ALIGNED(size, PAGE_SIZE));
-
- mutex_lock(&ggtt->error_mutex);
- while (size) {
- void __iomem *s;
-
- ggtt->vm.insert_page(&ggtt->vm, addr,
- ggtt->error_capture.start,
- I915_CACHE_NONE, 0);
- mb();
-
- s = io_mapping_map_wc(&ggtt->iomap,
- ggtt->error_capture.start,
- PAGE_SIZE);
- memset_io(s, x, PAGE_SIZE);
- io_mapping_unmap(s);
-
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- mb();
- ggtt->vm.clear_range(&ggtt->vm, ggtt->error_capture.start, PAGE_SIZE);
- mutex_unlock(&ggtt->error_mutex);
-#endif
-}
-
-static struct sg_table *
-i915_pages_create_for_stolen(struct drm_device *dev,
- resource_size_t offset, resource_size_t size)
-{
- struct drm_i915_private *i915 = to_i915(dev);
- struct sg_table *st;
- struct scatterlist *sg;
-
- GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm)));
-
- /* We hide that we have no struct page backing our stolen object
- * by wrapping the contiguous physical allocation with a fake
- * dma mapping in a single scatterlist.
- */
-
- st = kmalloc(sizeof(*st), GFP_KERNEL);
- if (st == NULL)
- return ERR_PTR(-ENOMEM);
-
- if (sg_alloc_table(st, 1, GFP_KERNEL)) {
- kfree(st);
- return ERR_PTR(-ENOMEM);
- }
-
- sg = st->sgl;
- sg->offset = 0;
- sg->length = size;
-
- sg_dma_address(sg) = (dma_addr_t)i915->dsm.start + offset;
- sg_dma_len(sg) = size;
-
- return st;
-}
-
-static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
-{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
- struct sg_table *pages =
- i915_pages_create_for_stolen(obj->base.dev,
- obj->stolen->start,
- obj->stolen->size);
- if (IS_ERR(pages))
- return PTR_ERR(pages);
-
- dbg_poison(to_gt(i915)->ggtt,
- sg_dma_address(pages->sgl),
- sg_dma_len(pages->sgl),
- POISON_INUSE);
-
- __i915_gem_object_set_pages(obj, pages, obj->stolen->size);
-
- return 0;
-}
-
-static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
- struct sg_table *pages)
-{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
- /* Should only be called from i915_gem_object_release_stolen() */
-
- dbg_poison(to_gt(i915)->ggtt,
- sg_dma_address(pages->sgl),
- sg_dma_len(pages->sgl),
- POISON_FREE);
-
- sg_free_table(pages);
- kfree(pages);
-}
-
-static void
-i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
-{
- struct drm_i915_private *i915 = to_i915(obj->base.dev);
- struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen);
-
- GEM_BUG_ON(!stolen);
- i915_gem_stolen_remove_node(i915, stolen);
- kfree(stolen);
-
- i915_gem_object_release_memory_region(obj);
-}
-
-static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
- .name = "i915_gem_object_stolen",
- .get_pages = i915_gem_object_get_pages_stolen,
- .put_pages = i915_gem_object_put_pages_stolen,
- .release = i915_gem_object_release_stolen,
-};
-
-static int __i915_gem_object_create_stolen(struct intel_memory_region *mem,
- struct drm_i915_gem_object *obj,
- struct drm_mm_node *stolen)
-{
- static struct lock_class_key lock_class;
- unsigned int cache_level;
- unsigned int flags;
- int err;
-
- /*
- * Stolen objects are always physically contiguous since we just
- * allocate one big block underneath using the drm_mm range allocator.
- */
- flags = I915_BO_ALLOC_CONTIGUOUS;
-
- drm_gem_private_object_init(&mem->i915->drm, &obj->base, stolen->size);
- i915_gem_object_init(obj, &i915_gem_object_stolen_ops, &lock_class, flags);
-
- obj->stolen = stolen;
- obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT;
- cache_level = HAS_LLC(mem->i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
- i915_gem_object_set_cache_coherency(obj, cache_level);
-
- if (WARN_ON(!i915_gem_object_trylock(obj, NULL)))
- return -EBUSY;
-
- i915_gem_object_init_memory_region(obj, mem);
-
- err = i915_gem_object_pin_pages(obj);
- if (err)
- i915_gem_object_release_memory_region(obj);
- i915_gem_object_unlock(obj);
-
- return err;
-}
-
-static int _i915_gem_object_stolen_init(struct intel_memory_region *mem,
- struct drm_i915_gem_object *obj,
- resource_size_t offset,
- resource_size_t size,
- resource_size_t page_size,
- unsigned int flags)
+struct drm_i915_gem_object *
+i915_gem_object_create_stolen(struct drm_i915_private *i915,
+ resource_size_t size)
{
- struct drm_i915_private *i915 = mem->i915;
- struct drm_mm_node *stolen;
+ struct drm_i915_gem_object *obj;
int ret;

- if (!drm_mm_initialized(&i915->mm.stolen))
- return -ENODEV;
-
- if (size == 0)
- return -EINVAL;
+ obj = i915_gem_object_create_region(i915->mm.stolen_region, size, 0,
+ I915_BO_ALLOC_CONTIGUOUS);
+ if (IS_ERR(obj))
+ return obj;

- /*
- * With discrete devices, where we lack a mappable aperture there is no
- * possible way to ever access this memory on the CPU side.
- */
- if (mem->type == INTEL_MEMORY_STOLEN_LOCAL && !mem->io_size &&
- !(flags & I915_BO_ALLOC_GPU_ONLY))
- return -ENOSPC;
-
- stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
- if (!stolen)
- return -ENOMEM;
-
- if (offset != I915_BO_INVALID_OFFSET) {
- drm_dbg(&i915->drm,
- "creating preallocated stolen object: stolen_offset=%pa, size=%pa\n",
- &offset, &size);
-
- stolen->start = offset;
- stolen->size = size;
- mutex_lock(&i915->mm.stolen_lock);
- ret = drm_mm_reserve_node(&i915->mm.stolen, stolen);
- mutex_unlock(&i915->mm.stolen_lock);
- } else {
- ret = i915_gem_stolen_insert_node(i915, stolen, size,
- mem->min_page_size);
+ ret = i915_gem_object_pin_pages_unlocked(obj);
+ if (ret) {
+ i915_gem_object_put(obj);
+ return ERR_PTR(ret);
}
- if (ret)
- goto err_free;
-
- ret = __i915_gem_object_create_stolen(mem, obj, stolen);
- if (ret)
- goto err_remove;

- return 0;
-
-err_remove:
- i915_gem_stolen_remove_node(i915, stolen);
-err_free:
- kfree(stolen);
- return ret;
-}
-
-struct drm_i915_gem_object *
-i915_gem_object_create_stolen(struct drm_i915_private *i915,
- resource_size_t size)
-{
- return i915_gem_object_create_region(i915->mm.stolen_region, size, 0, 0);
+ return obj;
}

static int init_stolen_smem(struct intel_memory_region *mem)
@@ -755,16 +562,26 @@ static int init_stolen_smem(struct intel_memory_region *mem)
return i915_gem_init_stolen(mem);
}

-static int release_stolen_smem(struct intel_memory_region *mem)
+static int stolen_object_init(struct intel_memory_region *mem,
+ struct drm_i915_gem_object *obj,
+ resource_size_t offset,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags)
{
- i915_gem_cleanup_stolen(mem->i915);
- return 0;
+ if (!mem->region_private)
+ return -ENODEV;
+
+ if (size == 0)
+ return -EINVAL;
+
+ return __i915_gem_ttm_object_init(mem, obj, offset, size, page_size, flags);
}

static const struct intel_memory_region_ops i915_region_stolen_smem_ops = {
.init = init_stolen_smem,
- .release = release_stolen_smem,
- .init_object = _i915_gem_object_stolen_init,
+ .release = intel_region_ttm_fini,
+ .init_object = stolen_object_init,
};

static int init_stolen_lmem(struct intel_memory_region *mem)
@@ -793,7 +610,7 @@ static int init_stolen_lmem(struct intel_memory_region *mem)
return 0;

err_cleanup:
- i915_gem_cleanup_stolen(mem->i915);
+ intel_region_ttm_fini(mem);
return err;
}

@@ -801,14 +618,13 @@ static int release_stolen_lmem(struct intel_memory_region *mem)
{
if (mem->io_size)
io_mapping_fini(&mem->iomap);
- i915_gem_cleanup_stolen(mem->i915);
- return 0;
+ return intel_region_ttm_fini(mem);
}

static const struct intel_memory_region_ops i915_region_stolen_lmem_ops = {
.init = init_stolen_lmem,
.release = release_stolen_lmem,
- .init_object = _i915_gem_object_stolen_init,
+ .init_object = __i915_gem_ttm_object_init,
};

struct intel_memory_region *
@@ -896,7 +712,37 @@ i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type,
return mem;
}

-bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj)
+/**
+ * i915_gem_object_stolen_offset - return offset from start of stolen region
+ * @obj: the object to return the offset of
+ *
+ * Get the offset from stolen region if this object is currently placed in stolen memory.
+ *
+ * Return: offset from stolen if successful, I915_BO_INVALID_OFFSET otherwise
+ */
+u64 i915_gem_object_stolen_offset(struct drm_i915_gem_object *obj)
{
- return obj->ops == &i915_gem_object_stolen_ops;
+ struct ttm_buffer_object *ttm_obj;
+
+ if (!obj || !i915_gem_object_is_stolen(obj))
+ return I915_BO_INVALID_OFFSET;
+
+ ttm_obj = i915_gem_to_ttm(obj);
+ if (ttm_obj->resource->mem_type != I915_PL_STOLEN)
+ return I915_BO_INVALID_OFFSET;
+
+ return PFN_PHYS(ttm_obj->resource->start);
+}
+
+bool i915_gem_object_is_stolen(struct drm_i915_gem_object *obj)
+{
+ struct intel_memory_region *mr = READ_ONCE(obj->mm.region);
+
+#ifdef CONFIG_LOCKDEP
+ if (i915_gem_object_migratable(obj) &&
+ i915_gem_object_evictable(obj))
+ assert_object_held(obj);
+#endif
+ return mr && (mr->type == INTEL_MEMORY_STOLEN_SYSTEM ||
+ mr->type == INTEL_MEMORY_STOLEN_LOCAL);
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
index d5005a39d130..b39cb6e6c768 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h
@@ -10,17 +10,9 @@

struct drm_i915_private;
struct drm_mm_node;
+struct ttm_resource;
struct drm_i915_gem_object;

-int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
- struct drm_mm_node *node, u64 size,
- unsigned alignment);
-int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
- struct drm_mm_node *node, u64 size,
- unsigned alignment, u64 start,
- u64 end);
-void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
- struct drm_mm_node *node);
struct intel_memory_region *
i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type,
u16 instance);
@@ -32,7 +24,16 @@ struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_i915_private *dev_priv,
resource_size_t size);

-bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj);
+u64 i915_gem_object_stolen_offset(struct drm_i915_gem_object *obj);
+bool i915_gem_object_is_stolen(struct drm_i915_gem_object *obj);
+struct ttm_resource *
+i915_gem_stolen_reserve_range(struct drm_i915_private *i915,
+ resource_size_t size,
+ u64 start, u64 end);
+u64 i915_gem_stolen_reserve_offset(struct ttm_resource *res);
+u64 i915_gem_stolen_reserve_size(struct ttm_resource *res);
+void i915_gem_stolen_release_range(struct drm_i915_private *i915,
+ struct ttm_resource *res);

#define I915_GEM_STOLEN_BIAS SZ_128K

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index 73e371aa3850..81654a51df51 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -49,6 +49,13 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
resource_size_t size,
resource_size_t page_size,
unsigned int flags);
+int i915_gem_ttm_object_init_in_place(struct intel_memory_region *mem,
+ struct drm_i915_gem_object *obj,
+ resource_size_t size,
+ resource_size_t page_size,
+ unsigned int flags,
+ u64 start,
+ u64 end);

/* Internal I915 TTM declarations and definitions below. */

diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index b4770690e794..269b7f467fdf 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -355,9 +355,9 @@ static int vlv_rc6_init(struct intel_rc6 *rc6)

GEM_BUG_ON(range_overflows_end_t(u64,
i915->dsm.start,
- pctx->stolen->start,
+ i915_gem_object_stolen_offset(pctx),
U32_MAX));
- pctx_paddr = i915->dsm.start + pctx->stolen->start;
+ pctx_paddr = i915->dsm.start + i915_gem_object_stolen_offset(pctx);
intel_uncore_write(uncore, VLV_PCBR, pctx_paddr);

out:
diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c
index 37c38bdd5f47..75bc7d90c9dc 100644
--- a/drivers/gpu/drm/i915/gt/selftest_reset.c
+++ b/drivers/gpu/drm/i915/gt/selftest_reset.c
@@ -6,6 +6,7 @@
#include <linux/crc32.h>

#include "gem/i915_gem_stolen.h"
+#include "intel_region_ttm.h"

#include "i915_memcpy.h"
#include "i915_selftest.h"
@@ -83,6 +84,7 @@ __igt_reset_stolen(struct intel_gt *gt,
dma_addr_t dma = (dma_addr_t)dsm->start + (page << PAGE_SHIFT);
void __iomem *s;
void *in;
+ bool busy;

ggtt->vm.insert_page(&ggtt->vm, dma,
ggtt->error_capture.start,
@@ -93,9 +95,9 @@ __igt_reset_stolen(struct intel_gt *gt,
ggtt->error_capture.start,
PAGE_SIZE);

- if (!__drm_mm_interval_first(&gt->i915->mm.stolen,
- page << PAGE_SHIFT,
- ((page + 1) << PAGE_SHIFT) - 1))
+ busy = intel_region_ttm_range_busy(gt->i915->mm.stolen_region,
+ PFN_PHYS(page), PAGE_SIZE);
+ if (!busy)
memset_io(s, STACK_MAGIC, PAGE_SIZE);

in = (void __force *)s;
@@ -124,6 +126,7 @@ __igt_reset_stolen(struct intel_gt *gt,
void __iomem *s;
void *in;
u32 x;
+ bool busy;

ggtt->vm.insert_page(&ggtt->vm, dma,
ggtt->error_capture.start,
@@ -139,10 +142,9 @@ __igt_reset_stolen(struct intel_gt *gt,
in = tmp;
x = crc32_le(0, in, PAGE_SIZE);

- if (x != crc[page] &&
- !__drm_mm_interval_first(&gt->i915->mm.stolen,
- page << PAGE_SHIFT,
- ((page + 1) << PAGE_SHIFT) - 1)) {
+ busy = intel_region_ttm_range_busy(gt->i915->mm.stolen_region,
+ PFN_PHYS(page), PAGE_SIZE);
+ if (x != crc[page] && !busy) {
pr_debug("unused stolen page %pa modified by GPU reset\n",
&page);
if (count++ == 0)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 94e5c29d2ee3..e538b8f71dcc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -32,6 +32,7 @@

#include <drm/drm_debugfs.h>

+#include "gem/i915_gem_region.h"
#include "gem/i915_gem_context.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_buffer_pool.h"
@@ -157,6 +158,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_vma *vma;
int pin_count = 0;
+ u64 offset;

seq_printf(m, "%pK: %c%c%c %8zdKiB %02x %02x %s%s%s",
&obj->base,
@@ -241,8 +243,9 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
spin_unlock(&obj->vma.lock);

seq_printf(m, " (pinned x %d)", pin_count);
- if (i915_gem_object_is_stolen(obj))
- seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
+ offset = i915_gem_object_stolen_offset(obj);
+ if (offset != I915_BO_INVALID_OFFSET)
+ seq_printf(m, " (stolen: %08llx)", offset);
if (i915_gem_object_is_framebuffer(obj))
seq_printf(m, " (fb)");
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9274417cd87a..92ecc4558d3f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -231,11 +231,6 @@ struct i915_gem_mm {
* support stolen.
*/
struct intel_memory_region *stolen_region;
- /** Memory allocator for GTT stolen memory */
- struct drm_mm stolen;
- /** Protects the usage of the GTT stolen memory allocator. This is
- * always the inner lock when overlapping with struct_mutex. */
- struct mutex stolen_lock;

/* Protects bound_list/unbound_list and #drm_i915_gem_object.mm.link */
spinlock_t obj_lock;
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 7d49ea72e33f..4450b4897d59 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -189,11 +189,12 @@ intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
}
}

-#ifdef CONFIG_DRM_I915_SELFTEST
/**
* intel_region_ttm_resource_alloc - Allocate memory resources from a region
* @mem: The memory region,
* @size: The requested size in bytes
+ * @start: start of allowed range
+ * @end: end of allowed range
* @flags: Allocation flags
*
* This functionality is provided only for callers that need to allocate
@@ -207,8 +208,9 @@ intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
*/
struct ttm_resource *
intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
- resource_size_t offset,
resource_size_t size,
+ u64 start,
+ u64 end,
unsigned int flags)
{
struct ttm_resource_manager *man = mem->region_private;
@@ -219,9 +221,9 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,

if (flags & I915_BO_ALLOC_CONTIGUOUS)
place.flags |= TTM_PL_FLAG_CONTIGUOUS;
- if (offset != I915_BO_INVALID_OFFSET) {
- place.fpfn = offset >> PAGE_SHIFT;
- place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
+ if (start || end) {
+ place.fpfn = PFN_DOWN(start);
+ place.lpfn = PFN_UP(end);
} else if (mem->io_size && mem->io_size < mem->total) {
if (flags & I915_BO_ALLOC_GPU_ONLY) {
place.flags |= TTM_PL_FLAG_TOPDOWN;
@@ -242,8 +244,6 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
return ret ? ERR_PTR(ret) : res;
}

-#endif
-
/**
* intel_region_ttm_resource_free - Free a resource allocated from a resource manager
* @mem: The region the resource was allocated from.
@@ -261,3 +261,25 @@ void intel_region_ttm_resource_free(struct intel_memory_region *mem,

man->func->free(man, res);
}
+
+/**
+ * intel_region_ttm_range_busy - check whether range has any allocations
+ * @mem: The region to check
+ * @start: the start of the range to check
+ * @size: size of the range to check
+ *
+ * Return: true if something is alloceted within the region, false otherwise.
+ */
+bool intel_region_ttm_range_busy(struct intel_memory_region *mem,
+ u64 start, u64 size)
+{
+ struct ttm_resource *dummy;
+
+ dummy = intel_region_ttm_resource_alloc(mem, size, start, start + size,
+ I915_BO_ALLOC_CONTIGUOUS);
+ if (IS_ERR(dummy))
+ return true;
+
+ intel_region_ttm_resource_free(mem, dummy);
+ return false;
+}
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h
index cf9d86dcf409..1e88472fb2ea 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.h
+++ b/drivers/gpu/drm/i915/intel_region_ttm.h
@@ -29,15 +29,17 @@ intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
void intel_region_ttm_resource_free(struct intel_memory_region *mem,
struct ttm_resource *res);

+bool intel_region_ttm_range_busy(struct intel_memory_region *mem,
+ u64 start, u64 size);
+
int intel_region_to_ttm_type(const struct intel_memory_region *mem);

struct ttm_device_funcs *i915_ttm_driver(void);

-#ifdef CONFIG_DRM_I915_SELFTEST
struct ttm_resource *
intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
- resource_size_t offset,
resource_size_t size,
+ u64 start,
+ u64 end,
unsigned int flags);
-#endif
#endif /* _INTEL_REGION_TTM_H_ */
diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c
index 670557ce1024..15be2440cdb8 100644
--- a/drivers/gpu/drm/i915/selftests/mock_region.c
+++ b/drivers/gpu/drm/i915/selftests/mock_region.c
@@ -26,8 +26,9 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj)
int err;

obj->mm.res = intel_region_ttm_resource_alloc(obj->mm.region,
- obj->bo_offset,
obj->base.size,
+ obj->bo_offset,
+ obj->bo_offset + obj->base.size,
obj->flags);
if (IS_ERR(obj->mm.res))
return PTR_ERR(obj->mm.res);
--
2.25.1


2022-04-16 00:44:06

by Thomas Hellström

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] drm/i915: stolen memory use ttm backend

Hi,


On 4/12/22 21:38, Robert Beckett wrote:
> +struct ttm_resource *
> +i915_gem_stolen_reserve_range(struct drm_i915_private *i915,
> + resource_size_t size,
> + u64 start, u64 end)
> {
> - int ret;
> + struct intel_memory_region *mem = i915->mm.stolen_region;
>
> - if (!drm_mm_initialized(&i915->mm.stolen))
> - return -ENODEV;
> -
> - /* WaSkipStolenMemoryFirstPage:bdw+ */
> - if (GRAPHICS_VER(i915) >= 8 && start < 4096)
> - start = 4096;

Did we lose this Workaround?

Need to continue reviewing this patchnext week.


Thx,

Thomas




> -
> - mutex_lock(&i915->mm.stolen_lock);
> - ret = drm_mm_insert_node_in_range(&i915->mm.stolen, node,
> - size, alignment, 0,
> - start, end, DRM_MM_INSERT_BEST);
> - mutex_unlock(&i915->mm.stolen_lock);
> + if (!mem)
> + return ERR_PTR(-ENODEV);
> + return intel_region_ttm_resource_alloc(mem, size, start, end, I915_BO_ALLOC_CONTIGUOUS);
> +}
>
> -

2022-04-16 01:57:59

by Robert Beckett

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] drm/i915: stolen memory use ttm backend



On 14/04/2022 15:41, Thomas Hellström wrote:
> Hi,
>
>
> On 4/12/22 21:38, Robert Beckett wrote:
>> +struct ttm_resource *
>> +i915_gem_stolen_reserve_range(struct drm_i915_private *i915,
>> +                  resource_size_t size,
>> +                  u64 start, u64 end)
>>   {
>> -    int ret;
>> +    struct intel_memory_region *mem = i915->mm.stolen_region;
>> -    if (!drm_mm_initialized(&i915->mm.stolen))
>> -        return -ENODEV;
>> -
>> -    /* WaSkipStolenMemoryFirstPage:bdw+ */
>> -    if (GRAPHICS_VER(i915) >= 8 && start < 4096)
>> -        start = 4096;
>
> Did we lose this Workaround?

woops, looks like we did. Nice catch.
I'll add a reservation at start of day if wa is needed when I issue v4.

>
> Need to continue reviewing this patchnext week.
>
>
> Thx,
>
> Thomas
>
>
>
>
>> -
>> -    mutex_lock(&i915->mm.stolen_lock);
>> -    ret = drm_mm_insert_node_in_range(&i915->mm.stolen, node,
>> -                      size, alignment, 0,
>> -                      start, end, DRM_MM_INSERT_BEST);
>> -    mutex_unlock(&i915->mm.stolen_lock);
>> +    if (!mem)
>> +        return ERR_PTR(-ENODEV);
>> +    return intel_region_ttm_resource_alloc(mem, size, start, end,
>> I915_BO_ALLOC_CONTIGUOUS);
>> +}
>> -

2022-04-19 18:29:11

by kernel test robot

[permalink] [raw]
Subject: [drm/i915] 9c20c625e8: WARNING:possible_recursive_locking_detected



Greeting,

FYI, we noticed the following commit (built with gcc-11):

commit: 9c20c625e8f84a42c7963db854df4439553e8bc4 ("[PATCH v3 5/5] drm/i915: stolen memory use ttm backend")
url: https://github.com/intel-lab-lkp/linux/commits/Robert-Beckett/drm-i915-ttm-for-stolen-region/20220413-034123
base: git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link: https://lore.kernel.org/dri-devel/[email protected]

in testcase: kernel-selftests
version: kernel-selftests-x86_64-a17aac1b-1_20220413
with following parameters:

group: x86
ucode: 0xec

test-description: The kernel contains a set of "self tests" under the tools/testing/selftests/ directory. These are intended to be small unit tests to exercise individual code paths in the kernel.
test-url: https://www.kernel.org/doc/Documentation/kselftest.txt


on test machine: 4 threads Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz with 32G memory

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):



If you fix the issue, kindly add following tag
Reported-by: kernel test robot <[email protected]>


[ 47.240273][ T197] WARNING: possible recursive locking detected
[ 47.246317][ T197] 5.18.0-rc2-00646-g9c20c625e8f8 #1 Not tainted
[ 47.252442][ T197] --------------------------------------------
[ 47.258478][ T197] systemd-udevd/197 is trying to acquire lock:
[ 47.264516][ T197] ffffc90000fe72b0 (reservation_ww_class_acquire){+.+.}-{0:0}, at: i915_gem_object_pin_pages_unlocked (drivers/gpu/drm/i915/gem/i915_gem_pages.c:150) i915
[ 47.277112][ T197]
[ 47.277112][ T197] but task is already holding lock:
[ 47.284369][ T197] ffffc90000fe7578 (reservation_ww_class_acquire){+.+.}-{0:0}, at: __intel_context_do_pin (drivers/gpu/drm/i915/gt/intel_context.c:301) i915
[ 47.295899][ T197]
[ 47.295899][ T197] other info that might help us debug this:
[ 47.303847][ T197] Possible unsafe locking scenario:
[ 47.303847][ T197]
[ 47.311190][ T197] CPU0
[ 47.314346][ T197] ----
[ 47.317501][ T197] lock(reservation_ww_class_acquire);
[ 47.322925][ T197] lock(reservation_ww_class_acquire);
[ 47.328349][ T197]
[ 47.328349][ T197] *** DEADLOCK ***
[ 47.328349][ T197]
[ 47.336386][ T197] May be due to missing lock nesting notation
[ 47.336386][ T197]
[ 47.344598][ T197] 3 locks held by systemd-udevd/197:
[ 47.349760][ T197] #0: ffff888103a96248 (&dev->mutex){....}-{3:3}, at: __driver_attach (drivers/base/dd.c:1140)
[ 47.358945][ T197] #1: ffffc90000fe7578 (reservation_ww_class_acquire){+.+.}-{0:0}, at: __intel_context_do_pin (drivers/gpu/drm/i915/gt/intel_context.c:301) i915
[ 47.370902][ T197] #2: ffff8882069c1068 (&ce->pin_mutex){+.+.}-{3:3}, at: intel_context_alloc_state (drivers/gpu/drm/i915/gt/intel_context.c:55) i915
[ 47.381889][ T197]
[ 47.381889][ T197] stack backtrace:
[ 47.387661][ T197] CPU: 2 PID: 197 Comm: systemd-udevd Not tainted 5.18.0-rc2-00646-g9c20c625e8f8 #1
[ 47.396923][ T197] Hardware name: Dell Inc. OptiPlex 7040/0Y7WYT, BIOS 1.8.1 12/05/2017
[ 47.405051][ T197] Call Trace:
[ 47.408209][ T197] <TASK>
[ 47.411020][ T197] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 4))
[ 47.415405][ T197] validate_chain.cold (kernel/locking/lockdep.c:2958 kernel/locking/lockdep.c:3001 kernel/locking/lockdep.c:3790)
[ 47.420400][ T197] ? check_prev_add (kernel/locking/lockdep.c:3759)
[ 47.425307][ T197] __lock_acquire (kernel/locking/lockdep.c:5029)
[ 47.429952][ T197] ? lock_downgrade (kernel/locking/lockdep.c:5652)
[ 47.434680][ T197] lock_acquire (kernel/locking/lockdep.c:436 kernel/locking/lockdep.c:5646 kernel/locking/lockdep.c:5609)
[ 47.439062][ T197] ? i915_gem_object_pin_pages_unlocked (drivers/gpu/drm/i915/gem/i915_gem_pages.c:150) i915
[ 47.446226][ T197] ? rcu_read_unlock (include/linux/rcupdate.h:723 (discriminator 5))
[ 47.450865][ T197] ? __mutex_unlock_slowpath (arch/x86/include/asm/atomic64_64.h:190 include/linux/atomic/atomic-long.h:449 include/linux/atomic/atomic-instrumented.h:1790 kernel/locking/mutex.c:910)
[ 47.456379][ T197] ? wait_for_completion_io_timeout (kernel/locking/mutex.c:888)
[ 47.462338][ T197] ? _raw_spin_unlock (arch/x86/include/asm/preempt.h:85 include/linux/spinlock_api_smp.h:143 kernel/locking/spinlock.c:186)
[ 47.467076][ T197] i915_gem_ww_ctx_init (include/linux/ww_mutex.h:152 drivers/gpu/drm/i915/i915_gem_ww.c:11) i915
[ 47.472948][ T197] ? i915_gem_object_pin_pages_unlocked (drivers/gpu/drm/i915/gem/i915_gem_pages.c:150) i915
[ 47.480109][ T197] i915_gem_object_pin_pages_unlocked (drivers/gpu/drm/i915/gem/i915_gem_pages.c:150) i915
[ 47.487094][ T197] ? __i915_gem_ttm_object_init (drivers/gpu/drm/i915/gem/i915_gem_object.h:228 drivers/gpu/drm/i915/gem/i915_gem_ttm.c:1238) i915
[ 47.493632][ T197] ? __i915_gem_object_get_pages (drivers/gpu/drm/i915/gem/i915_gem_pages.c:146) i915
[ 47.500260][ T197] ? rcu_read_lock_sched_held (kernel/rcu/update.c:125)
[ 47.505685][ T197] ? trace_i915_gem_object_create (drivers/gpu/drm/i915/i915_trace.h:22) i915
[ 47.512317][ T197] ? __i915_gem_object_create_region (drivers/gpu/drm/i915/gem/i915_gem_region.c:102) i915
[ 47.519291][ T197] i915_gem_object_create_stolen (drivers/gpu/drm/i915/gem/i915_gem_stolen.c:547) i915
[ 47.525832][ T197] intel_engine_create_ring (drivers/gpu/drm/i915/gt/intel_ring.c:120 drivers/gpu/drm/i915/gt/intel_ring.c:173) i915
[ 47.532021][ T197] lrc_alloc (drivers/gpu/drm/i915/gt/intel_lrc.c:990) i915
[ 47.536898][ T197] intel_context_alloc_state (drivers/gpu/drm/i915/gt/intel_context.c:64) i915
[ 47.543078][ T197] __intel_context_do_pin_ww (drivers/gpu/drm/i915/gt/intel_context.c:211) i915
[ 47.549516][ T197] ? lock_downgrade (kernel/locking/lockdep.c:5652)
[ 47.554245][ T197] ? rwlock_bug+0xc0/0xc0
[ 47.559062][ T197] ? intel_context_alloc_state (drivers/gpu/drm/i915/gt/intel_context.c:205) i915
[ 47.565508][ T197] ? i915_gem_ww_ctx_init (include/linux/ww_mutex.h:152 drivers/gpu/drm/i915/i915_gem_ww.c:11) i915
[ 47.571532][ T197] __intel_context_do_pin (drivers/gpu/drm/i915/gt/intel_context.c:304) i915
[ 47.577452][ T197] ? __module_address (kernel/module.c:4737)
[ 47.582878][ T197] ? __intel_context_do_pin_ww (drivers/gpu/drm/i915/gt/intel_context.c:297) i915
[ 47.589500][ T197] ? __i915_active_init (include/linux/list.h:38 drivers/gpu/drm/i915/i915_active.c:360) i915
[ 47.595344][ T197] ? intel_engine_print_breadcrumbs (drivers/gpu/drm/i915/gt/intel_context.c:371) i915
[ 47.602220][ T197] intel_engine_create_pinned_context (drivers/gpu/drm/i915/gt/intel_context.h:157 drivers/gpu/drm/i915/gt/intel_engine_cs.c:1060) i915
[ 47.609273][ T197] intel_engines_init (drivers/gpu/drm/i915/gt/intel_engine_cs.c:1100 drivers/gpu/drm/i915/gt/intel_engine_cs.c:1131 drivers/gpu/drm/i915/gt/intel_engine_cs.c:1176) i915
[ 47.614928][ T197] ? execlists_unwind_incomplete_requests (drivers/gpu/drm/i915/gt/intel_execlists_submission.c:3485) i915
[ 47.622148][ T197] intel_gt_init (drivers/gpu/drm/i915/gt/intel_gt.c:716) i915
[ 47.627370][ T197] i915_gem_init (drivers/gpu/drm/i915/i915_gem.c:1121) i915
[ 47.632605][ T197] ? intel_modeset_init_nogem (drivers/gpu/drm/i915/display/intel_display.c:9780) i915
[ 47.638984][ T197] i915_driver_probe (drivers/gpu/drm/i915/i915_driver.c:872) i915
[ 47.644545][ T197] ? i915_print_iommu_status (drivers/gpu/drm/i915/i915_driver.c:822) i915
[ 47.650627][ T197] ? drm_privacy_screen_get (drivers/gpu/drm/drm_privacy_screen.c:167)
[ 47.656054][ T197] i915_pci_probe (drivers/gpu/drm/i915/i915_pci.c:1202) i915
[ 47.661357][ T197] ? i915_pci_remove (drivers/gpu/drm/i915/i915_pci.c:1202) i915
[ 47.666741][ T197] ? lockdep_hardirqs_on_prepare (kernel/locking/lockdep.c:4501)
[ 47.673211][ T197] ? _raw_spin_unlock_irqrestore (arch/x86/include/asm/irqflags.h:45 arch/x86/include/asm/irqflags.h:80 arch/x86/include/asm/irqflags.h:138 include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194)
[ 47.678899][ T197] ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:50 (discriminator 22))
[ 47.683804][ T197] ? _raw_spin_unlock_irqrestore (arch/x86/include/asm/irqflags.h:45 arch/x86/include/asm/irqflags.h:80 arch/x86/include/asm/irqflags.h:138 include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194)
[ 47.689497][ T197] ? i915_pci_remove (drivers/gpu/drm/i915/i915_pci.c:1202) i915
[ 47.694894][ T197] local_pci_probe (drivers/pci/pci-driver.c:323)
[ 47.699455][ T197] pci_call_probe (drivers/pci/pci-driver.c:391)
[ 47.704017][ T197] ? rwlock_bug+0xc0/0xc0
[ 47.708840][ T197] ? pci_pm_suspend_noirq (drivers/pci/pci-driver.c:351)
[ 47.714106][ T197] ? pci_match_device (drivers/pci/pci-driver.c:107 drivers/pci/pci-driver.c:158)
[ 47.719016][ T197] ? kernfs_put (arch/x86/include/asm/atomic.h:123 (discriminator 1) include/linux/atomic/atomic-instrumented.h:576 (discriminator 1) fs/kernfs/dir.c:513 (discriminator 1))
[ 47.723233][ T197] pci_device_probe (drivers/pci/pci-driver.c:460)
[ 47.727881][ T197] ? pci_dma_configure (drivers/pci/pci-driver.c:1620)
[ 47.732789][ T197] really_probe (drivers/base/dd.c:541 drivers/base/dd.c:620)
[ 47.737174][ T197] __driver_probe_device (drivers/base/dd.c:751)
[ 47.742339][ T197] ? lockdep_hardirqs_on_prepare (kernel/locking/lockdep.c:4501)
[ 47.748815][ T197] driver_probe_device (drivers/base/dd.c:781)
[ 47.753721][ T197] __driver_attach (drivers/base/dd.c:1141)
[ 47.758366][ T197] ? __device_attach_driver (drivers/base/dd.c:1093)
[ 47.763792][ T197] bus_for_each_dev (drivers/base/bus.c:301)
[ 47.768523][ T197] ? lockdep_init_map_type (kernel/locking/lockdep.c:4812)
[ 47.773864][ T197] ? subsys_dev_iter_exit (drivers/base/bus.c:290)
[ 47.778948][ T197] bus_add_driver (drivers/base/bus.c:619)
[ 47.783507][ T197] driver_register (drivers/base/driver.c:171)
[ 47.788151][ T197] ? __pci_register_driver (include/linux/list.h:37 drivers/pci/pci-driver.c:1413)
[ 47.793491][ T197] i915_init (drivers/gpu/drm/i915/i915_driver.c:1008) i915
[ 47.798293][ T197] ? 0xffffffffc1201000
[ 47.802324][ T197] do_one_initcall (init/main.c:1298)
[ 47.806878][ T197] ? trace_event_raw_event_initcall_level (init/main.c:1289)
[ 47.813525][ T197] ? memset_erms (arch/x86/lib/memset_64.S:65)
[ 47.817734][ T197] ? kasan_unpoison (mm/kasan/shadow.c:108 mm/kasan/shadow.c:142)
[ 47.822290][ T197] do_init_module (kernel/module.c:3731)
[ 47.826848][ T197] __do_sys_finit_module (kernel/module.c:4222)
[ 47.832015][ T197] ? __ia32_sys_init_module (kernel/module.c:4190)
[ 47.837269][ T197] ? __seccomp_filter (arch/x86/include/asm/bitops.h:214 include/asm-generic/bitops/instrumented-non-atomic.h:135 kernel/seccomp.c:351 kernel/seccomp.c:378 kernel/seccomp.c:410 kernel/seccomp.c:1183)
[ 47.842180][ T197] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
[ 47.846475][ T197] ? lockdep_hardirqs_on_prepare (kernel/locking/lockdep.c:4501)
[ 47.852948][ T197] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:115)
[ 47.858725][ T197] RIP: 0033:0x7fc6644eb989
[ 47.863018][ T197] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d d7 64 0c 00 f7 d8 64 89 01 48
All code
========
0: 00 c3 add %al,%bl
2: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
9: 00 00 00
c: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
11: 48 89 f8 mov %rdi,%rax
14: 48 89 f7 mov %rsi,%rdi
17: 48 89 d6 mov %rdx,%rsi
1a: 48 89 ca mov %rcx,%rdx
1d: 4d 89 c2 mov %r8,%r10
20: 4d 89 c8 mov %r9,%r8
23: 4c 8b 4c 24 08 mov 0x8(%rsp),%r9
28: 0f 05 syscall
2a:* 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax <-- trapping instruction
30: 73 01 jae 0x33
32: c3 retq
33: 48 8b 0d d7 64 0c 00 mov 0xc64d7(%rip),%rcx # 0xc6511
3a: f7 d8 neg %eax
3c: 64 89 01 mov %eax,%fs:(%rcx)
3f: 48 rex.W

Code starting with the faulting instruction
===========================================
0: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
6: 73 01 jae 0x9
8: c3 retq
9: 48 8b 0d d7 64 0c 00 mov 0xc64d7(%rip),%rcx # 0xc64e7
10: f7 d8 neg %eax
12: 64 89 01 mov %eax,%fs:(%rcx)
15: 48 rex.W


To reproduce:

git clone https://github.com/intel/lkp-tests.git
cd lkp-tests
sudo bin/lkp install job.yaml # job file is attached in this email
bin/lkp split-job --compatible job.yaml # generate the yaml file for lkp run
sudo bin/lkp run generated-yaml-file

# if come across any failure that blocks the test,
# please remove ~/.lkp and /lkp dir to run from a clean state.



--
0-DAY CI Kernel Test Service
https://01.org/lkp



Attachments:
(No filename) (12.96 kB)
config-5.18.0-rc2-00646-g9c20c625e8f8 (169.78 kB)
job-script (5.92 kB)
dmesg.xz (41.45 kB)
kernel-selftests (140.73 kB)
job.yaml (4.96 kB)
reproduce (150.00 B)
Download all attachments