[igt-dev] [PATCH i-g-t 2/4] lib/intel_batchbuffer: Extend intel_bb

Dominik Grzegorzek dominik.grzegorzek at intel.com
Mon Jun 29 11:10:02 UTC 2020


From: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>

As we're going toward removing libdrm from rendercopy tests some
additional code in intel_bb is required. So add new functions
and fix memory issues in the reset path.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
---
 lib/intel_batchbuffer.c | 189 ++++++++++++++++++++++++++++++++++++----
 lib/intel_batchbuffer.h |  12 +++
 2 files changed, 185 insertions(+), 16 deletions(-)

diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 2a882627..c041465d 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1250,24 +1250,32 @@ static void __do_nothing(void *node)
 	(void) node;
 }
 
-static void __intel_bb_destroy_objects(struct intel_bb *ibb)
+static void __intel_bb_destroy_relocations(struct intel_bb *ibb)
 {
 	uint32_t i;
 
 	/* Free relocations */
-	for (i = 0; i < ibb->num_objects; i++)
+	for (i = 0; i < ibb->num_objects; i++) {
 		free(from_user_pointer(ibb->objects[i].relocs_ptr));
+		ibb->objects[i].relocs_ptr = to_user_pointer(NULL);
+		ibb->objects[i].relocation_count = 0;
+	}
 
-	free(ibb->objects);
-	tdestroy(ibb->root, __do_nothing);
+	ibb->relocs = NULL;
+	ibb->num_relocs = 0;
+	ibb->allocated_relocs = 0;
+}
 
+static void __intel_bb_destroy_objects(struct intel_bb *ibb)
+{
+	free(ibb->objects);
 	ibb->objects = NULL;
+
+	tdestroy(ibb->root, __do_nothing);
 	ibb->root = NULL;
+
 	ibb->num_objects = 0;
-	ibb->num_relocs = 0;
 	ibb->allocated_objects = 0;
-	ibb->allocated_relocs = 0;
-	ibb->ptr = ibb->batch;
 }
 
 /**
@@ -1280,6 +1288,7 @@ void intel_bb_destroy(struct intel_bb *ibb)
 {
 	igt_assert(ibb);
 
+	__intel_bb_destroy_relocations(ibb);
 	__intel_bb_destroy_objects(ibb);
 	gem_close(ibb->i915, ibb->handle);
 
@@ -1295,6 +1304,8 @@ void intel_bb_destroy(struct intel_bb *ibb)
 */
 void intel_bb_reset(struct intel_bb *ibb, bool purge_objects_cache)
 {
+	__intel_bb_destroy_relocations(ibb);
+
 	if (purge_objects_cache) {
 		__intel_bb_destroy_objects(ibb);
 		__reallocate_objects(ibb);
@@ -1305,6 +1316,61 @@ void intel_bb_reset(struct intel_bb *ibb, bool purge_objects_cache)
 
 	intel_bb_add_object(ibb, ibb->handle, 0, false);
 	ibb->ptr = ibb->batch;
+	memset(ibb->batch, 0, ibb->size);
+}
+
+/*
+ * intel_bb_sync:
+ * @ibb: pointer to intel_bb
+ *
+ * Waits for bb completion.
+ */
+void intel_bb_sync(struct intel_bb *ibb)
+{
+	gem_sync(ibb->i915, ibb->handle);
+}
+
+/*
+ * intel_bb_print:
+ * @ibb: pointer to intel_bb
+ *
+ * Prints batch to stdout.
+ */
+void intel_bb_print(struct intel_bb *ibb)
+{
+	igt_info("drm fd: %d, gen: %d, devid: %u, debug: %d\n",
+		 ibb->i915, ibb->gen, ibb->devid, ibb->debug);
+	igt_info("handle: %u, size: %u, batch: %p, ptr: %p\n",
+		 ibb->handle, ibb->size, ibb->batch, ibb->ptr);
+	igt_info("prng: %u, gtt_size: %" PRIu64 ", supports 48bit: %d\n",
+		 ibb->prng, ibb->gtt_size, ibb->supports_48b_address);
+	igt_info("ctx: %u\n", ibb->ctx);
+	igt_info("root: %p\n", ibb->root);
+	igt_info("objects: %p, num_objects: %u, allocated obj: %u\n",
+		 ibb->objects, ibb->num_objects, ibb->allocated_objects);
+	igt_info("relocs: %p, num_relocs: %u, allocated_relocs: %u\n----\n",
+		 ibb->relocs, ibb->num_relocs, ibb->allocated_relocs);
+}
+
+/*
+ * intel_bb_dump:
+ * @ibb: pointer to intel_bb
+ * @filename: name to which write bb
+ *
+ * Dump batch bo to file.
+ */
+void intel_bb_dump(struct intel_bb *ibb, const char *filename)
+{
+	FILE *out;
+	void *ptr;
+
+	ptr = gem_mmap__device_coherent(ibb->i915, ibb->handle, 0, ibb->size,
+					PROT_READ);
+	out = fopen(filename, "wb");
+	igt_assert(out);
+	fwrite(ptr, ibb->size, 1, out);
+	fclose(out);
+	munmap(ptr, ibb->size);
 }
 
 /**
@@ -1382,6 +1448,23 @@ intel_bb_add_object(struct intel_bb *ibb, uint32_t handle,
 	return object;
 }
 
+static bool intel_bb_object_set_fence(struct intel_bb *ibb, uint32_t handle)
+{
+	struct drm_i915_gem_exec_object2 object = { .handle = handle };
+	struct drm_i915_gem_exec_object2 **found;
+
+	found = tfind((void *) &object, &ibb->root, __compare_objects);
+	if (!found) {
+		igt_warn("Trying to set fence on not found handle: %u\n",
+			 handle);
+		return false;
+	}
+
+	(*found)->flags |= EXEC_OBJECT_NEEDS_FENCE;
+
+	return true;
+}
+
 /*
  * intel_bb_add_reloc:
  * @ibb: pointer to intel_bb
@@ -1431,9 +1514,10 @@ static uint64_t intel_bb_add_reloc(struct intel_bb *ibb,
 	igt_debug("add reloc: handle: %u, r/w: 0x%x/0x%x, "
 		  "delta: 0x%" PRIx64 ", "
 		  "offset: 0x%" PRIx64 ", "
-		  "poffset: 0x%" PRIx64 "\n",
+		  "poffset: %p\n",
 		  handle, read_domains, write_domain,
-		  delta, offset, presumed_offset);
+		  delta, offset,
+		  from_user_pointer(relocs[i].presumed_offset));
 
 	return object->offset;
 }
@@ -1479,6 +1563,38 @@ uint64_t intel_bb_emit_reloc(struct intel_bb *ibb,
 	return address;
 }
 
+/**
+ * intel_bb_emit_reloc_fenced:
+ * @ibb: pointer to intel_bb
+ * @handle: object handle which address will be taken to patch the bb
+ * @read_domains: gem domain bits for the relocation
+ * @write_domain: gem domain bit for the relocation
+ * @delta: delta value to add to @buffer's gpu address
+ * @presumed_offset: address of the object in address space, important for
+ * I915_EXEC_NO_RELOC flag
+ * @write: does a handle is a render target
+ *
+ * Function works similar to intel_bb_emit_reloc but additionally marks an
+ * object with EXEC_OBJECT_NEEDS_FENCE to ensure appropriate fence will
+ * be configured when it is required on older gens.
+ */
+uint64_t intel_bb_emit_reloc_fenced(struct intel_bb *ibb,
+				    uint32_t handle,
+				    uint32_t read_domains,
+				    uint32_t write_domain,
+				    uint64_t delta,
+				    uint64_t presumed_offset)
+{
+	uint64_t address;
+
+	address = intel_bb_emit_reloc(ibb, handle, read_domains, write_domain,
+				      delta, presumed_offset);
+
+	intel_bb_object_set_fence(ibb, handle);
+
+	return address;
+}
+
 /**
  * intel_bb_offset_reloc:
  * @ibb: pointer to intel_bb
@@ -1509,7 +1625,8 @@ uint64_t intel_bb_offset_reloc(struct intel_bb *ibb,
 				  0, offset, presumed_offset);
 }
 
-static void intel_bb_dump_execbuf(struct drm_i915_gem_execbuffer2 *execbuf)
+static void intel_bb_dump_execbuf(struct intel_bb *ibb,
+				  struct drm_i915_gem_execbuffer2 *execbuf)
 {
 	struct drm_i915_gem_exec_object2 *objects;
 	struct drm_i915_gem_relocation_entry *relocs, *reloc;
@@ -1535,7 +1652,8 @@ static void intel_bb_dump_execbuf(struct drm_i915_gem_execbuffer2 *execbuf)
 			 i, objects->handle, objects->relocation_count,
 			 relocs,
 			 objects->alignment,
-			 objects->offset, objects->flags,
+			 objects->offset & (ibb->gtt_size - 1),
+			 objects->flags,
 			 objects->rsvd1, objects->rsvd2);
 		if (objects->relocation_count) {
 			igt_info("\texecbuf relocs:\n");
@@ -1548,7 +1666,7 @@ static void intel_bb_dump_execbuf(struct drm_i915_gem_execbuffer2 *execbuf)
 					 "write_domain: 0x%x\n",
 					 j, reloc->target_handle,
 					 reloc->offset, reloc->delta,
-					 reloc->presumed_offset,
+					 reloc->presumed_offset & (ibb->gtt_size - 1),
 					 reloc->read_domains,
 					 reloc->write_domain);
 			}
@@ -1609,14 +1727,16 @@ int __intel_bb_exec(struct intel_bb *ibb, uint32_t end_offset,
 	execbuf.flags = flags | I915_EXEC_BATCH_FIRST;
 
 	ret = __gem_execbuf(ibb->i915, &execbuf);
-	if (ret)
+	if (ret) {
+		intel_bb_dump_execbuf(ibb, &execbuf);
 		return ret;
+	}
 
 	if (sync || ibb->debug)
 		gem_sync(ibb->i915, ibb->handle);
 
 	if (ibb->debug) {
-		intel_bb_dump_execbuf(&execbuf);
+		intel_bb_dump_execbuf(ibb, &execbuf);
 		if (intel_bb_debug_tree) {
 			igt_info("\nTree:\n");
 			twalk(ibb->root, print_node);
@@ -1679,7 +1799,7 @@ uint64_t intel_bb_get_object_offset(struct intel_bb *ibb, uint32_t handle)
 	if (!found)
 		return 0;
 
-	return (*found)->offset;
+	return (*found)->offset & (ibb->gtt_size - 1);
 }
 
 /**
@@ -1706,8 +1826,45 @@ bool intel_bb_object_offset_to_buf(struct intel_bb *ibb, struct intel_buf *buf)
 		return false;
 	}
 
-	buf->addr.offset = (*found)->offset;
+	buf->addr.offset = (*found)->offset & (ibb->gtt_size - 1);
 	buf->addr.ctx = ibb->ctx;
 
 	return true;
 }
+
+/*
+ * intel_bb_out_flush:
+ * @ibb: batchbuffer
+ *
+ * Outputs flushing code to the batch.
+ */
+#define CMD_POLY_STIPPLE_OFFSET       0x7906
+uint32_t intel_bb_out_flush(struct intel_bb *ibb)
+{
+	if (intel_bb_offset(ibb) == 0)
+		return 0;
+
+	if (ibb->gen == 5) {
+		intel_bb_out(ibb, CMD_POLY_STIPPLE_OFFSET << 16);
+		intel_bb_out(ibb, 0);
+	}
+
+	/* Round batchbuffer usage to 2 DWORDs. */
+	intel_bb_ptr_align(ibb, 8);
+
+	if (ibb->gen <= 4) {
+		intel_bb_out(ibb, MI_FLUSH);
+	} else {
+		intel_bb_out(ibb, MI_FLUSH_DW | 2);
+		intel_bb_out(ibb, 0);
+		intel_bb_out(ibb, 0);
+		intel_bb_out(ibb, 0);
+	}
+
+	/* Mark the end of the buffer. */
+	intel_bb_out(ibb, MI_BATCH_BUFFER_END); /* noop */
+	intel_bb_out(ibb, 0);
+
+	return intel_bb_offset(ibb);
+}
+
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index 0649fc22..2ced3ea6 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -460,6 +460,9 @@ struct intel_bb *intel_bb_create(int i915, uint32_t size);
 
 void intel_bb_destroy(struct intel_bb *ibb);
 void intel_bb_reset(struct intel_bb *ibb, bool purge_objects_cache);
+void intel_bb_sync(struct intel_bb *ibb);
+void intel_bb_print(struct intel_bb *ibb);
+void intel_bb_dump(struct intel_bb *ibb, const char *filename);
 void intel_bb_set_debug(struct intel_bb *ibb, bool debug);
 
 static inline uint32_t intel_bb_offset(struct intel_bb *ibb)
@@ -510,6 +513,13 @@ uint64_t intel_bb_emit_reloc(struct intel_bb *ibb,
 			 uint64_t delta,
 			 uint64_t presumed_offset);
 
+uint64_t intel_bb_emit_reloc_fenced(struct intel_bb *ibb,
+				    uint32_t handle,
+				    uint32_t read_domains,
+				    uint32_t write_domain,
+				    uint64_t delta,
+				    uint64_t presumed_offset);
+
 uint64_t intel_bb_offset_reloc(struct intel_bb *ibb,
 			       uint32_t handle,
 			       uint32_t read_domains,
@@ -529,4 +539,6 @@ void intel_bb_exec_with_context(struct intel_bb *ibb, uint32_t end_offset,
 uint64_t intel_bb_get_object_offset(struct intel_bb *ibb, uint32_t handle);
 bool intel_bb_object_offset_to_buf(struct intel_bb *ibb, struct intel_buf *buf);
 
+uint32_t intel_bb_out_flush(struct intel_bb *ibb);
+
 #endif
-- 
2.20.1



More information about the igt-dev mailing list