diff mbox series

drm/i915: Engine discovery, the HW bits

Message ID 20190314162417.2036-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series drm/i915: Engine discovery, the HW bits | expand

Commit Message

Chris Wilson March 14, 2019, 4:24 p.m. UTC
Not only do we want to discover the user topology of the engines,
sometimes we also want to delve into the inner most workings of the HW,
such as determining context image sizes and mmio offset, in a platform
independent way.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@intel.com>
---
 drivers/gpu/drm/i915/i915_query.c | 60 +++++++++++++++++++++++++++++++
 include/uapi/drm/i915_drm.h       | 21 +++++++++++
 2 files changed, 81 insertions(+)

Comments

kernel test robot March 15, 2019, 12:04 a.m. UTC | #1
Hi Chris,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on v5.0 next-20190306]
[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/Chris-Wilson/drm-i915-Engine-discovery-the-HW-bits/20190315-065822
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-randconfig-x015-201910 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   In file included from include/linux/slab.h:16:0,
                    from include/linux/io-mapping.h:22,
                    from drivers/gpu/drm/i915/i915_drv.h:36,
                    from drivers/gpu/drm/i915/i915_query.c:9:
   drivers/gpu/drm/i915/i915_query.c: In function 'query_engine_hw_info_v1':
>> drivers/gpu/drm/i915/i915_query.c:103:59: error: 'struct intel_runtime_info' has no member named 'num_engines'; did you mean 'num_sprites'?
     sz = struct_size(query_ptr, engines, RUNTIME_INFO(i915)->num_engines);
                                                              ^
   include/linux/overflow.h:305:14: note: in definition of macro 'struct_size'
     __ab_c_size(n,       \
                 ^
>> drivers/gpu/drm/i915/i915_query.c:107:8: error: implicit declaration of function 'copy_query_item'; did you mean 'copy_user_page'? [-Werror=implicit-function-declaration]
     ret = copy_query_item(&query, sizeof(query), sz, query_item);
           ^~~~~~~~~~~~~~~
           copy_user_page
   cc1: some warnings being treated as errors

vim +103 drivers/gpu/drm/i915/i915_query.c

     8	
   > 9	#include "i915_drv.h"
    10	#include "i915_query.h"
    11	#include <uapi/drm/i915_drm.h>
    12	
    13	static int query_topology_info(struct drm_i915_private *dev_priv,
    14				       struct drm_i915_query_item *query_item)
    15	{
    16		const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
    17		struct drm_i915_query_topology_info topo;
    18		u32 slice_length, subslice_length, eu_length, total_length;
    19	
    20		if (query_item->flags != 0)
    21			return -EINVAL;
    22	
    23		if (sseu->max_slices == 0)
    24			return -ENODEV;
    25	
    26		BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
    27	
    28		slice_length = sizeof(sseu->slice_mask);
    29		subslice_length = sseu->max_slices *
    30			DIV_ROUND_UP(sseu->max_subslices, BITS_PER_BYTE);
    31		eu_length = sseu->max_slices * sseu->max_subslices *
    32			DIV_ROUND_UP(sseu->max_eus_per_subslice, BITS_PER_BYTE);
    33	
    34		total_length = sizeof(topo) + slice_length + subslice_length + eu_length;
    35	
    36		if (query_item->length == 0)
    37			return total_length;
    38	
    39		if (query_item->length < total_length)
    40			return -EINVAL;
    41	
    42		if (copy_from_user(&topo, u64_to_user_ptr(query_item->data_ptr),
    43				   sizeof(topo)))
    44			return -EFAULT;
    45	
    46		if (topo.flags != 0)
    47			return -EINVAL;
    48	
    49		if (!access_ok(u64_to_user_ptr(query_item->data_ptr),
    50			       total_length))
    51			return -EFAULT;
    52	
    53		memset(&topo, 0, sizeof(topo));
    54		topo.max_slices = sseu->max_slices;
    55		topo.max_subslices = sseu->max_subslices;
    56		topo.max_eus_per_subslice = sseu->max_eus_per_subslice;
    57	
    58		topo.subslice_offset = slice_length;
    59		topo.subslice_stride = DIV_ROUND_UP(sseu->max_subslices, BITS_PER_BYTE);
    60		topo.eu_offset = slice_length + subslice_length;
    61		topo.eu_stride =
    62			DIV_ROUND_UP(sseu->max_eus_per_subslice, BITS_PER_BYTE);
    63	
    64		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr),
    65				   &topo, sizeof(topo)))
    66			return -EFAULT;
    67	
    68		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr + sizeof(topo)),
    69				   &sseu->slice_mask, slice_length))
    70			return -EFAULT;
    71	
    72		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr +
    73						   sizeof(topo) + slice_length),
    74				   sseu->subslice_mask, subslice_length))
    75			return -EFAULT;
    76	
    77		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr +
    78						   sizeof(topo) +
    79						   slice_length + subslice_length),
    80				   sseu->eu_mask, eu_length))
    81			return -EFAULT;
    82	
    83		return total_length;
    84	}
    85	
    86	static int
    87	query_engine_hw_info_v1(struct drm_i915_private *i915,
    88				struct drm_i915_query_item *query_item)
    89	{
    90		struct drm_i915_query_engine_hw_info_v1 __user *query_ptr =
    91			u64_to_user_ptr(query_item->data_ptr);
    92		struct drm_i915_query_engine_hw_info_v1 query;
    93		struct i915_engine_hw_info_v1 __user *out;
    94		struct i915_engine_hw_info_v1 info = {};
    95		struct intel_engine_cs *engine;
    96		enum intel_engine_id id;
    97		int ret, i;
    98		size_t sz;
    99	
   100		if (query_item->flags)
   101			return -EINVAL;
   102	
 > 103		sz = struct_size(query_ptr, engines, RUNTIME_INFO(i915)->num_engines);
   104		if (sz > INT_MAX)
   105			return -EINVAL;
   106	
 > 107		ret = copy_query_item(&query, sizeof(query), sz, query_item);
   108		if (ret)
   109			return ret;
   110	
   111		if (query.num_engines)
   112			return -EINVAL;
   113	
   114		if (query.flags)
   115			return -EINVAL;
   116	
   117		for (i = 0; i < ARRAY_SIZE(query.rsvd); i++) {
   118			if (query.rsvd[i])
   119				return -EINVAL;
   120		}
   121	
   122		query.flags |= I915_QUERY_HW_INFO_HAS_HW_ID;
   123		query.flags |= I915_QUERY_HW_INFO_HAS_MMIO_BASE;
   124		query.flags |= I915_QUERY_HW_INFO_HAS_CONTEXT_SIZE;
   125	
   126		out = query_ptr->engines;
   127		for_each_engine(engine, i915, id) {
   128			info.hw_id = engine->hw_id;
   129			info.mmio_base = engine->mmio_base;
   130			info.context_size = engine->context_size;
   131	
   132			if (__copy_to_user(out, &info, sizeof(info)))
   133				return -EFAULT;
   134	
   135			out++;
   136		}
   137		query.num_engines = out - query_ptr->engines;
   138	
   139		if (__copy_to_user(query_ptr, &query, sizeof(query)))
   140			return -EFAULT;
   141	
   142		return sz;
   143	}
   144	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot March 15, 2019, 12:23 a.m. UTC | #2
Hi Chris,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on drm-intel/for-linux-next]
[also build test ERROR on v5.0 next-20190306]
[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/Chris-Wilson/drm-i915-Engine-discovery-the-HW-bits/20190315-065822
base:   git://anongit.freedesktop.org/drm-intel for-linux-next
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   In file included from include/linux/vmalloc.h:11:0,
                    from include/asm-generic/io.h:894,
                    from arch/x86/include/asm/io.h:383,
                    from arch/x86/include/asm/realmode.h:15,
                    from arch/x86/include/asm/acpi.h:33,
                    from arch/x86/include/asm/fixmap.h:29,
                    from arch/x86/include/asm/apic.h:10,
                    from arch/x86/include/asm/smp.h:13,
                    from arch/x86/include/asm/mmzone_64.h:11,
                    from arch/x86/include/asm/mmzone.h:5,
                    from include/linux/mmzone.h:918,
                    from include/linux/gfp.h:6,
                    from include/linux/slab.h:15,
                    from include/linux/io-mapping.h:22,
                    from drivers/gpu//drm/i915/i915_drv.h:36,
                    from drivers/gpu//drm/i915/i915_query.c:9:
   drivers/gpu//drm/i915/i915_query.c: In function 'query_engine_hw_info_v1':
   drivers/gpu//drm/i915/i915_query.c:103:59: error: 'struct intel_runtime_info' has no member named 'num_engines'; did you mean 'num_sprites'?
     sz = struct_size(query_ptr, engines, RUNTIME_INFO(i915)->num_engines);
                                                              ^
   include/linux/overflow.h:305:14: note: in definition of macro 'struct_size'
     __ab_c_size(n,       \
                 ^
>> drivers/gpu//drm/i915/i915_query.c:107:8: error: implicit declaration of function 'copy_query_item'; did you mean 'copy_from_iter'? [-Werror=implicit-function-declaration]
     ret = copy_query_item(&query, sizeof(query), sz, query_item);
           ^~~~~~~~~~~~~~~
           copy_from_iter
   cc1: some warnings being treated as errors

vim +107 drivers/gpu//drm/i915/i915_query.c

     8	
   > 9	#include "i915_drv.h"
    10	#include "i915_query.h"
    11	#include <uapi/drm/i915_drm.h>
    12	
    13	static int query_topology_info(struct drm_i915_private *dev_priv,
    14				       struct drm_i915_query_item *query_item)
    15	{
    16		const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
    17		struct drm_i915_query_topology_info topo;
    18		u32 slice_length, subslice_length, eu_length, total_length;
    19	
    20		if (query_item->flags != 0)
    21			return -EINVAL;
    22	
    23		if (sseu->max_slices == 0)
    24			return -ENODEV;
    25	
    26		BUILD_BUG_ON(sizeof(u8) != sizeof(sseu->slice_mask));
    27	
    28		slice_length = sizeof(sseu->slice_mask);
    29		subslice_length = sseu->max_slices *
    30			DIV_ROUND_UP(sseu->max_subslices, BITS_PER_BYTE);
    31		eu_length = sseu->max_slices * sseu->max_subslices *
    32			DIV_ROUND_UP(sseu->max_eus_per_subslice, BITS_PER_BYTE);
    33	
    34		total_length = sizeof(topo) + slice_length + subslice_length + eu_length;
    35	
    36		if (query_item->length == 0)
    37			return total_length;
    38	
    39		if (query_item->length < total_length)
    40			return -EINVAL;
    41	
    42		if (copy_from_user(&topo, u64_to_user_ptr(query_item->data_ptr),
    43				   sizeof(topo)))
    44			return -EFAULT;
    45	
    46		if (topo.flags != 0)
    47			return -EINVAL;
    48	
    49		if (!access_ok(u64_to_user_ptr(query_item->data_ptr),
    50			       total_length))
    51			return -EFAULT;
    52	
    53		memset(&topo, 0, sizeof(topo));
    54		topo.max_slices = sseu->max_slices;
    55		topo.max_subslices = sseu->max_subslices;
    56		topo.max_eus_per_subslice = sseu->max_eus_per_subslice;
    57	
    58		topo.subslice_offset = slice_length;
    59		topo.subslice_stride = DIV_ROUND_UP(sseu->max_subslices, BITS_PER_BYTE);
    60		topo.eu_offset = slice_length + subslice_length;
    61		topo.eu_stride =
    62			DIV_ROUND_UP(sseu->max_eus_per_subslice, BITS_PER_BYTE);
    63	
    64		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr),
    65				   &topo, sizeof(topo)))
    66			return -EFAULT;
    67	
    68		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr + sizeof(topo)),
    69				   &sseu->slice_mask, slice_length))
    70			return -EFAULT;
    71	
    72		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr +
    73						   sizeof(topo) + slice_length),
    74				   sseu->subslice_mask, subslice_length))
    75			return -EFAULT;
    76	
    77		if (__copy_to_user(u64_to_user_ptr(query_item->data_ptr +
    78						   sizeof(topo) +
    79						   slice_length + subslice_length),
    80				   sseu->eu_mask, eu_length))
    81			return -EFAULT;
    82	
    83		return total_length;
    84	}
    85	
    86	static int
    87	query_engine_hw_info_v1(struct drm_i915_private *i915,
    88				struct drm_i915_query_item *query_item)
    89	{
    90		struct drm_i915_query_engine_hw_info_v1 __user *query_ptr =
    91			u64_to_user_ptr(query_item->data_ptr);
    92		struct drm_i915_query_engine_hw_info_v1 query;
    93		struct i915_engine_hw_info_v1 __user *out;
    94		struct i915_engine_hw_info_v1 info = {};
    95		struct intel_engine_cs *engine;
    96		enum intel_engine_id id;
    97		int ret, i;
    98		size_t sz;
    99	
   100		if (query_item->flags)
   101			return -EINVAL;
   102	
   103		sz = struct_size(query_ptr, engines, RUNTIME_INFO(i915)->num_engines);
   104		if (sz > INT_MAX)
   105			return -EINVAL;
   106	
 > 107		ret = copy_query_item(&query, sizeof(query), sz, query_item);
   108		if (ret)
   109			return ret;
   110	
   111		if (query.num_engines)
   112			return -EINVAL;
   113	
   114		if (query.flags)
   115			return -EINVAL;
   116	
   117		for (i = 0; i < ARRAY_SIZE(query.rsvd); i++) {
   118			if (query.rsvd[i])
   119				return -EINVAL;
   120		}
   121	
   122		query.flags |= I915_QUERY_HW_INFO_HAS_HW_ID;
   123		query.flags |= I915_QUERY_HW_INFO_HAS_MMIO_BASE;
   124		query.flags |= I915_QUERY_HW_INFO_HAS_CONTEXT_SIZE;
   125	
   126		out = query_ptr->engines;
   127		for_each_engine(engine, i915, id) {
   128			info.hw_id = engine->hw_id;
   129			info.mmio_base = engine->mmio_base;
   130			info.context_size = engine->context_size;
   131	
   132			if (__copy_to_user(out, &info, sizeof(info)))
   133				return -EFAULT;
   134	
   135			out++;
   136		}
   137		query.num_engines = out - query_ptr->engines;
   138	
   139		if (__copy_to_user(query_ptr, &query, sizeof(query)))
   140			return -EFAULT;
   141	
   142		return sz;
   143	}
   144	

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

Patch

diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 782183b78f49..778d8417ef0e 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -96,9 +96,69 @@  static int query_topology_info(struct drm_i915_private *dev_priv,
 	return total_length;
 }
 
+static int
+query_engine_hw_info_v1(struct drm_i915_private *i915,
+			struct drm_i915_query_item *query_item)
+{
+	struct drm_i915_query_engine_hw_info_v1 __user *query_ptr =
+		u64_to_user_ptr(query_item->data_ptr);
+	struct drm_i915_query_engine_hw_info_v1 query;
+	struct i915_engine_hw_info_v1 __user *out;
+	struct i915_engine_hw_info_v1 info = {};
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	int ret, i;
+	size_t sz;
+
+	if (query_item->flags)
+		return -EINVAL;
+
+	sz = struct_size(query_ptr, engines, RUNTIME_INFO(i915)->num_engines);
+	if (sz > INT_MAX)
+		return -EINVAL;
+
+	ret = copy_query_item(&query, sizeof(query), sz, query_item);
+	if (ret)
+		return ret;
+
+	if (query.num_engines)
+		return -EINVAL;
+
+	if (query.flags)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(query.rsvd); i++) {
+		if (query.rsvd[i])
+			return -EINVAL;
+	}
+
+	query.flags |= I915_QUERY_HW_INFO_HAS_HW_ID;
+	query.flags |= I915_QUERY_HW_INFO_HAS_MMIO_BASE;
+	query.flags |= I915_QUERY_HW_INFO_HAS_CONTEXT_SIZE;
+
+	out = query_ptr->engines;
+	for_each_engine(engine, i915, id) {
+		info.hw_id = engine->hw_id;
+		info.mmio_base = engine->mmio_base;
+		info.context_size = engine->context_size;
+
+		if (__copy_to_user(out, &info, sizeof(info)))
+			return -EFAULT;
+
+		out++;
+	}
+	query.num_engines = out - query_ptr->engines;
+
+	if (__copy_to_user(query_ptr, &query, sizeof(query)))
+		return -EFAULT;
+
+	return sz;
+}
+
 static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
 					struct drm_i915_query_item *query_item) = {
 	query_topology_info,
+	query_engine_hw_info_v1,
 };
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 08f680dd2b1c..3c684afd7bb6 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1982,6 +1982,27 @@  struct drm_i915_query_item {
 	__u64 data_ptr;
 };
 
+struct i915_engine_hw_info_v1 {
+	__u64 flags;
+
+	__u32 hw_id;
+	__u32 mmio_base;
+	__u32 context_size;
+
+	__u32 rsvd[9];
+};
+
+struct drm_i915_query_engine_hw_info_v1 {
+	__u32 num_engines;
+	__u32 flags;
+#define I915_QUERY_HW_INFO_HAS_HW_ID		(1u << 0)
+#define I915_QUERY_HW_INFO_HAS_MMIO_BASE	(1u << 1)
+#define I915_QUERY_HW_INFO_HAS_CONTEXT_SIZE	(1u << 2)
+	__u32 rsvd[10]; /* mbz */
+
+	struct i915_engine_hw_info_v1 engines[0];
+};
+
 struct drm_i915_query {
 	__u32 num_items;