All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Intel-gfx@lists.freedesktop.org,
	Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Subject: [igt-dev] [PATCH i-g-t 2/2] tests/i915_query: Engine discovery tests
Date: Wed, 22 May 2019 14:32:40 +0100	[thread overview]
Message-ID: <20190522133240.26624-2-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20190522133240.26624-1-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Test the new engine discovery query.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@intel.com>
---
 tests/i915/i915_query.c | 247 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 247 insertions(+)

diff --git a/tests/i915/i915_query.c b/tests/i915/i915_query.c
index 7d0c0e3a061c..ecbec3ae141d 100644
--- a/tests/i915/i915_query.c
+++ b/tests/i915/i915_query.c
@@ -483,6 +483,241 @@ test_query_topology_known_pci_ids(int fd, int devid)
 	free(topo_info);
 }
 
+static bool query_engine_info_supported(int fd)
+{
+	struct drm_i915_query_item item = {
+		.query_id = DRM_I915_QUERY_ENGINE_INFO,
+	};
+
+	return __i915_query_items(fd, &item, 1) == 0 && item.length > 0;
+}
+
+static void engines_invalid(int fd)
+{
+	struct drm_i915_query_engine_info *engines;
+	struct drm_i915_query_item item;
+	unsigned int len;
+
+	/* Flags is MBZ. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.flags = 1;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	/* Length not zero and not greater or equal required size. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = 1;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	/* Query correct length. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	i915_query_items(fd, &item, 1);
+	igt_assert(item.length >= 0);
+	len = item.length;
+
+	engines = malloc(len);
+	igt_assert(engines);
+
+	/* Ivalid pointer. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+
+	/* All fields in engines query are MBZ and only filled by the kernel. */
+
+	memset(engines, 0, len);
+	engines->num_engines = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[0] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[1] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[2] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	free(engines);
+
+	igt_assert(len <= 4096);
+	engines = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
+		       -1, 0);
+	igt_assert(engines != MAP_FAILED);
+
+	/* PROT_NONE is similar to unmapped area. */
+	memset(engines, 0, len);
+	igt_assert_eq(mprotect(engines, len, PROT_NONE), 0);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+	igt_assert_eq(mprotect(engines, len, PROT_WRITE), 0);
+
+	/* Read-only so kernel cannot fill the data back. */
+	memset(engines, 0, len);
+	igt_assert_eq(mprotect(engines, len, PROT_READ), 0);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+
+	munmap(engines, 4096);
+}
+
+static bool
+has_engine(struct drm_i915_query_engine_info *engines,
+	   unsigned class, unsigned instance)
+{
+	unsigned int i;
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct drm_i915_engine_info *engine =
+			(struct drm_i915_engine_info *)&engines->engines[i];
+
+		if (engine->engine.engine_class == class &&
+		    engine->engine.engine_instance == instance)
+			return true;
+	}
+
+	return false;
+}
+
+static void engines(int fd)
+{
+	struct drm_i915_query_engine_info *engines;
+	struct drm_i915_query_item item;
+	unsigned int len, i;
+
+	engines = malloc(4096);
+	igt_assert(engines);
+
+	/* Query required buffer length. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert(item.length >= 0);
+	igt_assert(item.length <= 4096);
+	len = item.length;
+
+	/* Check length larger than required works and reports same length. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = 4096;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, len);
+
+	/* Actual query. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, len);
+
+	/* Every GPU has at least one engine. */
+	igt_assert(engines->num_engines > 0);
+
+	/* MBZ fields. */
+	igt_assert_eq(engines->rsvd[0], 0);
+	igt_assert_eq(engines->rsvd[1], 0);
+	igt_assert_eq(engines->rsvd[2], 0);
+
+	/* Check results match the legacy GET_PARAM (where we can). */
+	for (i = 0; i < engines->num_engines; i++) {
+		struct drm_i915_engine_info *engine =
+			(struct drm_i915_engine_info *)&engines->engines[i];
+
+		igt_debug("%u: class=%u instance=%u flags=%llx capabilities=%llx\n",
+			  i,
+			  engine->engine.engine_class,
+			  engine->engine.engine_instance,
+			  engine->flags,
+			  engine->capabilities);
+
+		/* MBZ fields. */
+		igt_assert_eq(engine->rsvd0, 0);
+		igt_assert_eq(engine->rsvd1[0], 0);
+		igt_assert_eq(engine->rsvd1[1], 0);
+
+		switch (engine->engine.engine_class) {
+		case I915_ENGINE_CLASS_RENDER:
+			/* Will be tested later. */
+			break;
+		case I915_ENGINE_CLASS_COPY:
+			igt_assert(gem_has_blt(fd));
+			break;
+		case I915_ENGINE_CLASS_VIDEO:
+			switch (engine->engine.engine_instance) {
+			case 0:
+				igt_assert(gem_has_bsd(fd));
+				break;
+			case 1:
+				igt_assert(gem_has_bsd2(fd));
+				break;
+			}
+			break;
+		case I915_ENGINE_CLASS_VIDEO_ENHANCE:
+			igt_assert(gem_has_vebox(fd));
+			break;
+		default:
+			igt_assert(0);
+		}
+	}
+
+	/* Reverse check to the above - all GET_PARAM engines are present. */
+	igt_assert(has_engine(engines, I915_ENGINE_CLASS_RENDER, 0));
+	if (gem_has_blt(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_COPY, 0));
+	if (gem_has_bsd(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 0));
+	if (gem_has_bsd2(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 1));
+	if (gem_has_vebox(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO_ENHANCE,
+				       0));
+
+	free(engines);
+}
+
 igt_main
 {
 	int fd = -1;
@@ -530,6 +765,18 @@ igt_main
 		test_query_topology_known_pci_ids(fd, devid);
 	}
 
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(query_engine_info_supported(fd));
+		}
+
+		igt_subtest("engine-info-invalid")
+			engines_invalid(fd);
+
+		igt_subtest("engine-info")
+			engines(fd);
+	}
+
 	igt_fixture {
 		close(fd);
 	}
-- 
2.20.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

WARNING: multiple messages have this Message-ID (diff)
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Intel-gfx@lists.freedesktop.org
Subject: [PATCH i-g-t 2/2] tests/i915_query: Engine discovery tests
Date: Wed, 22 May 2019 14:32:40 +0100	[thread overview]
Message-ID: <20190522133240.26624-2-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20190522133240.26624-1-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Test the new engine discovery query.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@intel.com>
---
 tests/i915/i915_query.c | 247 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 247 insertions(+)

diff --git a/tests/i915/i915_query.c b/tests/i915/i915_query.c
index 7d0c0e3a061c..ecbec3ae141d 100644
--- a/tests/i915/i915_query.c
+++ b/tests/i915/i915_query.c
@@ -483,6 +483,241 @@ test_query_topology_known_pci_ids(int fd, int devid)
 	free(topo_info);
 }
 
+static bool query_engine_info_supported(int fd)
+{
+	struct drm_i915_query_item item = {
+		.query_id = DRM_I915_QUERY_ENGINE_INFO,
+	};
+
+	return __i915_query_items(fd, &item, 1) == 0 && item.length > 0;
+}
+
+static void engines_invalid(int fd)
+{
+	struct drm_i915_query_engine_info *engines;
+	struct drm_i915_query_item item;
+	unsigned int len;
+
+	/* Flags is MBZ. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.flags = 1;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	/* Length not zero and not greater or equal required size. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = 1;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	/* Query correct length. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	i915_query_items(fd, &item, 1);
+	igt_assert(item.length >= 0);
+	len = item.length;
+
+	engines = malloc(len);
+	igt_assert(engines);
+
+	/* Ivalid pointer. */
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+
+	/* All fields in engines query are MBZ and only filled by the kernel. */
+
+	memset(engines, 0, len);
+	engines->num_engines = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[0] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[1] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	memset(engines, 0, len);
+	engines->rsvd[2] = 1;
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EINVAL);
+
+	free(engines);
+
+	igt_assert(len <= 4096);
+	engines = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
+		       -1, 0);
+	igt_assert(engines != MAP_FAILED);
+
+	/* PROT_NONE is similar to unmapped area. */
+	memset(engines, 0, len);
+	igt_assert_eq(mprotect(engines, len, PROT_NONE), 0);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+	igt_assert_eq(mprotect(engines, len, PROT_WRITE), 0);
+
+	/* Read-only so kernel cannot fill the data back. */
+	memset(engines, 0, len);
+	igt_assert_eq(mprotect(engines, len, PROT_READ), 0);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, -EFAULT);
+
+	munmap(engines, 4096);
+}
+
+static bool
+has_engine(struct drm_i915_query_engine_info *engines,
+	   unsigned class, unsigned instance)
+{
+	unsigned int i;
+
+	for (i = 0; i < engines->num_engines; i++) {
+		struct drm_i915_engine_info *engine =
+			(struct drm_i915_engine_info *)&engines->engines[i];
+
+		if (engine->engine.engine_class == class &&
+		    engine->engine.engine_instance == instance)
+			return true;
+	}
+
+	return false;
+}
+
+static void engines(int fd)
+{
+	struct drm_i915_query_engine_info *engines;
+	struct drm_i915_query_item item;
+	unsigned int len, i;
+
+	engines = malloc(4096);
+	igt_assert(engines);
+
+	/* Query required buffer length. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert(item.length >= 0);
+	igt_assert(item.length <= 4096);
+	len = item.length;
+
+	/* Check length larger than required works and reports same length. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = 4096;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, len);
+
+	/* Actual query. */
+	memset(engines, 0, 4096);
+	memset(&item, 0, sizeof(item));
+	item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	item.length = len;
+	item.data_ptr = to_user_pointer(engines);
+	i915_query_items(fd, &item, 1);
+	igt_assert_eq(item.length, len);
+
+	/* Every GPU has at least one engine. */
+	igt_assert(engines->num_engines > 0);
+
+	/* MBZ fields. */
+	igt_assert_eq(engines->rsvd[0], 0);
+	igt_assert_eq(engines->rsvd[1], 0);
+	igt_assert_eq(engines->rsvd[2], 0);
+
+	/* Check results match the legacy GET_PARAM (where we can). */
+	for (i = 0; i < engines->num_engines; i++) {
+		struct drm_i915_engine_info *engine =
+			(struct drm_i915_engine_info *)&engines->engines[i];
+
+		igt_debug("%u: class=%u instance=%u flags=%llx capabilities=%llx\n",
+			  i,
+			  engine->engine.engine_class,
+			  engine->engine.engine_instance,
+			  engine->flags,
+			  engine->capabilities);
+
+		/* MBZ fields. */
+		igt_assert_eq(engine->rsvd0, 0);
+		igt_assert_eq(engine->rsvd1[0], 0);
+		igt_assert_eq(engine->rsvd1[1], 0);
+
+		switch (engine->engine.engine_class) {
+		case I915_ENGINE_CLASS_RENDER:
+			/* Will be tested later. */
+			break;
+		case I915_ENGINE_CLASS_COPY:
+			igt_assert(gem_has_blt(fd));
+			break;
+		case I915_ENGINE_CLASS_VIDEO:
+			switch (engine->engine.engine_instance) {
+			case 0:
+				igt_assert(gem_has_bsd(fd));
+				break;
+			case 1:
+				igt_assert(gem_has_bsd2(fd));
+				break;
+			}
+			break;
+		case I915_ENGINE_CLASS_VIDEO_ENHANCE:
+			igt_assert(gem_has_vebox(fd));
+			break;
+		default:
+			igt_assert(0);
+		}
+	}
+
+	/* Reverse check to the above - all GET_PARAM engines are present. */
+	igt_assert(has_engine(engines, I915_ENGINE_CLASS_RENDER, 0));
+	if (gem_has_blt(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_COPY, 0));
+	if (gem_has_bsd(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 0));
+	if (gem_has_bsd2(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO, 1));
+	if (gem_has_vebox(fd))
+		igt_assert(has_engine(engines, I915_ENGINE_CLASS_VIDEO_ENHANCE,
+				       0));
+
+	free(engines);
+}
+
 igt_main
 {
 	int fd = -1;
@@ -530,6 +765,18 @@ igt_main
 		test_query_topology_known_pci_ids(fd, devid);
 	}
 
+	igt_subtest_group {
+		igt_fixture {
+			igt_require(query_engine_info_supported(fd));
+		}
+
+		igt_subtest("engine-info-invalid")
+			engines_invalid(fd);
+
+		igt_subtest("engine-info")
+			engines(fd);
+	}
+
 	igt_fixture {
 		close(fd);
 	}
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2019-05-22 13:32 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-22 13:32 [igt-dev] [PATCH i-g-t 1/2] drm-uapi: Import i915_drm.h upto c5d3e39caa456b1e061644b739131f2b54c84c08 Tvrtko Ursulin
2019-05-22 13:32 ` Tvrtko Ursulin
2019-05-22 13:32 ` Tvrtko Ursulin [this message]
2019-05-22 13:32   ` [PATCH i-g-t 2/2] tests/i915_query: Engine discovery tests Tvrtko Ursulin
2019-05-22 13:53 ` [Intel-gfx] [igt-dev] [PATCH i-g-t 1/2] drm-uapi: Import i915_drm.h upto c5d3e39caa456b1e061644b739131f2b54c84c08 Chris Wilson
2019-05-22 13:53   ` Chris Wilson
2019-05-22 14:27 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,1/2] " Patchwork
2019-05-22 21:12 ` [Intel-gfx] [PATCH i-g-t 1/2] " Andi Shyti
2019-05-22 21:12   ` Andi Shyti
2019-05-23 10:29 ` [igt-dev] ✗ Fi.CI.IGT: failure for series starting with [i-g-t,1/2] " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-05-01 11:42 [igt-dev] [PATCH i-g-t 0/2] Engine discovery tests Tvrtko Ursulin
2019-05-01 11:42 ` [igt-dev] [PATCH i-g-t 2/2] tests/i915_query: " Tvrtko Ursulin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190522133240.26624-2-tvrtko.ursulin@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=Intel-gfx@lists.freedesktop.org \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=tvrtko.ursulin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.