Skip to contentSkip to conversation

21st century intel_gpu_top & Co.

RFC New Tvrtko Ursulin 2 participants 9 messages Oct 3, 2018 – Oct 4, 2018

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

cover 21st century intel_gpu_top & Co.

From: Tvrtko Ursulin <[email protected]>

IGT patches accompanying the similary named i915 series. Most notably to sketch an improved intel_gpu_top which now, like the real top, can show the per client engine utilisation:

intel-gpu-top - load avg 3.30, 1.51, 0.08; 949/ 949 MHz; 0% RC6; 14.66 Watts; 3605 irqs/s

IMC reads: 4651 MiB/s
IMC writes: 25 MiB/s

ENGINE BUSY Q r R MI_SEMA MI_WAIT
Render/3D/0 61.51% |█████████████████████████████████████████████▌ | 3 0 1 0% 0%
Blitter/0 0.00% | | 0 0 0 0% 0%
Video/0 60.86% |█████████████████████████████████████████████ | 1 0 1 0% 0%
Video/1 59.04% |███████████████████████████████████████████▋ | 1 0 1 0% 0%
VideoEnhance/0 0.00% | | 0 0 0 0% 0%

PID NAME Render/3D/0 Blitter/0 Video/0 Video/1 VideoEnhance/0

23373        gem_wsim |█████▎              ||                    ||████████▍           ||█████▎              ||                    |
23374        gem_wsim |███▉                ||                    ||██▏                 ||███                 ||                    |
23375        gem_wsim |███                 ||                    ||█▍                  ||███▌                ||                    |

Tvrtko Ursulin (6):
include: DRM uAPI headers update
intel-gpu-overlay: Add engine queue stats
intel-gpu-overlay: Show 1s, 30s and 15m GPU load tests/perf_pmu: Add tests for engine queued/runnable/running stats
intel-gpu-top: Add queue depths and load average
intel-gpu-top: Support for client stats

 include/drm-uapi/amdgpu_drm.h  |  52 +++-
 include/drm-uapi/drm.h         |  16 ++
 include/drm-uapi/drm_fourcc.h  | 215 ++++++++++++++
 include/drm-uapi/drm_mode.h    |  26 +-
 include/drm-uapi/etnaviv_drm.h |   6 +
 include/drm-uapi/exynos_drm.h  | 240 ++++++++++++++++
 include/drm-uapi/i915_drm.h    |  49 +++-
 include/drm-uapi/msm_drm.h     |   2 +
 include/drm-uapi/tegra_drm.h   | 492 ++++++++++++++++++++++++++++++++-
 include/drm-uapi/v3d_drm.h     | 194 +++++++++++++
 include/drm-uapi/vc4_drm.h     |  13 +-
 include/drm-uapi/virtgpu_drm.h |   1 +
 include/drm-uapi/vmwgfx_drm.h  | 166 ++++++++---
 overlay/gpu-top.c              |  81 +++++-
 overlay/gpu-top.h              |  22 +-
 overlay/overlay.c              |  35 ++-
 tests/perf_pmu.c               | 259 +++++++++++++++++
 tools/Makefile.am              |   2 +-
 tools/intel_gpu_top.c          | 480 ++++++++++++++++++++++++++++++--
 tools/meson.build              |   2 +-
 20 files changed, 2264 insertions(+), 89 deletions(-)
 create mode 100644 include/drm-uapi/v3d_drm.h
Signature · 6 lines
2.17.1

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

RFC 1/6 include: DRM uAPI headers update

From: Tvrtko Ursulin <[email protected]>

---
 include/drm-uapi/amdgpu_drm.h  |  52 +++-
 include/drm-uapi/drm.h         |  16 ++
 include/drm-uapi/drm_fourcc.h  | 215 ++++++++++++++
 include/drm-uapi/drm_mode.h    |  26 +-
 include/drm-uapi/etnaviv_drm.h |   6 +
 include/drm-uapi/exynos_drm.h  | 240 ++++++++++++++++
 include/drm-uapi/i915_drm.h    |  49 +++-
 include/drm-uapi/msm_drm.h     |   2 +
 include/drm-uapi/tegra_drm.h   | 492 ++++++++++++++++++++++++++++++++-
 include/drm-uapi/v3d_drm.h     | 194 +++++++++++++
 include/drm-uapi/vc4_drm.h     |  13 +-
 include/drm-uapi/virtgpu_drm.h |   1 +
 include/drm-uapi/vmwgfx_drm.h  | 166 ++++++++---
 13 files changed, 1415 insertions(+), 57 deletions(-)
 create mode 100644 include/drm-uapi/v3d_drm.h
include/drm-uapi/amdgpu_drm.h +51 -1
index 1816bd8200d1..370e9a5536ef 100644
@@ -72,12 +72,41 @@ extern "C" {
 #define DRM_IOCTL_AMDGPU_FENCE_TO_HANDLE DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_FENCE_TO_HANDLE, union drm_amdgpu_fence_to_handle)
 #define DRM_IOCTL_AMDGPU_SCHED		DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_SCHED, union drm_amdgpu_sched)
 
+/**
+ * DOC: memory domains
+ *
+ * %AMDGPU_GEM_DOMAIN_CPU	System memory that is not GPU accessible.
+ * Memory in this pool could be swapped out to disk if there is pressure.
+ *
+ * %AMDGPU_GEM_DOMAIN_GTT	GPU accessible system memory, mapped into the
+ * GPU's virtual address space via gart. Gart memory linearizes non-contiguous
+ * pages of system memory, allows GPU access system memory in a linezrized
+ * fashion.
+ *
+ * %AMDGPU_GEM_DOMAIN_VRAM	Local video memory. For APUs, it is memory
+ * carved out by the BIOS.
+ *
+ * %AMDGPU_GEM_DOMAIN_GDS	Global on-chip data storage used to share data
+ * across shader threads.
+ *
+ * %AMDGPU_GEM_DOMAIN_GWS	Global wave sync, used to synchronize the
+ * execution of all the waves on a device.
+ *
+ * %AMDGPU_GEM_DOMAIN_OA	Ordered append, used by 3D or Compute engines
+ * for appending data.
+ */
 #define AMDGPU_GEM_DOMAIN_CPU		0x1
 #define AMDGPU_GEM_DOMAIN_GTT		0x2
 #define AMDGPU_GEM_DOMAIN_VRAM		0x4
 #define AMDGPU_GEM_DOMAIN_GDS		0x8
 #define AMDGPU_GEM_DOMAIN_GWS		0x10
 #define AMDGPU_GEM_DOMAIN_OA		0x20
+#define AMDGPU_GEM_DOMAIN_MASK		(AMDGPU_GEM_DOMAIN_CPU | \
+					 AMDGPU_GEM_DOMAIN_GTT | \
+					 AMDGPU_GEM_DOMAIN_VRAM | \
+					 AMDGPU_GEM_DOMAIN_GDS | \
+					 AMDGPU_GEM_DOMAIN_GWS | \
+					 AMDGPU_GEM_DOMAIN_OA)
 
 /* Flag that CPU access will be required for the case of VRAM domain */
 #define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED	(1 << 0)
@@ -95,6 +124,10 @@ extern "C" {
 #define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID	(1 << 6)
 /* Flag that BO sharing will be explicitly synchronized */
 #define AMDGPU_GEM_CREATE_EXPLICIT_SYNC		(1 << 7)
+/* Flag that indicates allocating MQD gart on GFX9, where the mtype
+ * for the second page onward should be set to NC.
+ */
+#define AMDGPU_GEM_CREATE_MQD_GFX9		(1 << 8)
 
 struct drm_amdgpu_gem_create_in  {
 	/** the requested memory size */
@@ -473,7 +506,8 @@ struct drm_amdgpu_gem_va {
 #define AMDGPU_HW_IP_UVD_ENC      5
 #define AMDGPU_HW_IP_VCN_DEC      6
 #define AMDGPU_HW_IP_VCN_ENC      7
-#define AMDGPU_HW_IP_NUM          8
+#define AMDGPU_HW_IP_VCN_JPEG     8
+#define AMDGPU_HW_IP_NUM          9
 
 #define AMDGPU_HW_IP_INSTANCE_MAX_COUNT 1
 
@@ -482,6 +516,7 @@ struct drm_amdgpu_gem_va {
 #define AMDGPU_CHUNK_ID_DEPENDENCIES	0x03
 #define AMDGPU_CHUNK_ID_SYNCOBJ_IN      0x04
 #define AMDGPU_CHUNK_ID_SYNCOBJ_OUT     0x05
+#define AMDGPU_CHUNK_ID_BO_HANDLES      0x06
 
 struct drm_amdgpu_cs_chunk {
 	__u32		chunk_id;
@@ -520,6 +555,10 @@ union drm_amdgpu_cs {
 /* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */
 #define AMDGPU_IB_FLAG_PREEMPT (1<<2)
 
+/* The IB fence should do the L2 writeback but not invalidate any shader
+ * caches (L2/vL1/sL1/I$). */
+#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3)
+
 struct drm_amdgpu_cs_chunk_ib {
 	__u32 _pad;
 	/** AMDGPU_IB_FLAG_* */
@@ -618,6 +657,16 @@ struct drm_amdgpu_cs_chunk_data {
 	#define AMDGPU_INFO_FW_SOS		0x0c
 	/* Subquery id: Query PSP ASD firmware version */
 	#define AMDGPU_INFO_FW_ASD		0x0d
+	/* Subquery id: Query VCN firmware version */
+	#define AMDGPU_INFO_FW_VCN		0x0e
+	/* Subquery id: Query GFX RLC SRLC firmware version */
+	#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f
+	/* Subquery id: Query GFX RLC SRLG firmware version */
+	#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10
+	/* Subquery id: Query GFX RLC SRLS firmware version */
+	#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
+	/* Subquery id: Query DMCU firmware version */
+	#define AMDGPU_INFO_FW_DMCU		0x12
 /* number of bytes moved for TTM migration */
 #define AMDGPU_INFO_NUM_BYTES_MOVED		0x0f
 /* the used VRAM size */
@@ -806,6 +855,7 @@ struct drm_amdgpu_info_firmware {
 #define AMDGPU_VRAM_TYPE_GDDR5 5
 #define AMDGPU_VRAM_TYPE_HBM   6
 #define AMDGPU_VRAM_TYPE_DDR3  7
+#define AMDGPU_VRAM_TYPE_DDR4  8
 
 struct drm_amdgpu_info_device {
 	/** PCI Device ID */
include/drm-uapi/drm.h +16 -0
index f0bd91de0cf9..85c685a2075e 100644
@@ -674,6 +674,22 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_ATOMIC	3
 
+/**
+ * DRM_CLIENT_CAP_ASPECT_RATIO
+ *
+ * If set to 1, the DRM core will provide aspect ratio information in modes.
+ */
+#define DRM_CLIENT_CAP_ASPECT_RATIO    4
+
+/**
+ * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
+ *
+ * If set to 1, the DRM core will expose special connectors to be used for
+ * writing back to memory the scene setup in the commit. Depends on client
+ * also supporting DRM_CLIENT_CAP_ATOMIC
+ */
+#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS	5
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;
include/drm-uapi/drm_fourcc.h +215 -0

250 lines not on this page · raw message

include/drm-uapi/drm_mode.h +22 -4
index 2c575794fb52..d3e0fe31efc5 100644
@@ -93,6 +93,15 @@ extern "C" {
 #define DRM_MODE_PICTURE_ASPECT_NONE		0
 #define DRM_MODE_PICTURE_ASPECT_4_3		1
 #define DRM_MODE_PICTURE_ASPECT_16_9		2
+#define DRM_MODE_PICTURE_ASPECT_64_27		3
+#define DRM_MODE_PICTURE_ASPECT_256_135		4
+
+/* Content type options */
+#define DRM_MODE_CONTENT_TYPE_NO_DATA		0
+#define DRM_MODE_CONTENT_TYPE_GRAPHICS		1
+#define DRM_MODE_CONTENT_TYPE_PHOTO		2
+#define DRM_MODE_CONTENT_TYPE_CINEMA		3
+#define DRM_MODE_CONTENT_TYPE_GAME		4
 
 /* Aspect ratio flag bitmask (4 bits 22:19) */
 #define DRM_MODE_FLAG_PIC_AR_MASK		(0x0F<<19)
@@ -102,6 +111,10 @@ extern "C" {
 			(DRM_MODE_PICTURE_ASPECT_4_3<<19)
 #define  DRM_MODE_FLAG_PIC_AR_16_9 \
 			(DRM_MODE_PICTURE_ASPECT_16_9<<19)
+#define  DRM_MODE_FLAG_PIC_AR_64_27 \
+			(DRM_MODE_PICTURE_ASPECT_64_27<<19)
+#define  DRM_MODE_FLAG_PIC_AR_256_135 \
+			(DRM_MODE_PICTURE_ASPECT_256_135<<19)
 
 #define  DRM_MODE_FLAG_ALL	(DRM_MODE_FLAG_PHSYNC |		\
 				 DRM_MODE_FLAG_NHSYNC |		\
@@ -173,8 +186,9 @@ extern "C" {
 /*
  * DRM_MODE_REFLECT_<axis>
  *
- * Signals that the contents of a drm plane is reflected in the <axis> axis,
+ * Signals that the contents of a drm plane is reflected along the <axis> axis,
  * in the same way as mirroring.
+ * See kerneldoc chapter "Plane Composition Properties" for more details.
  *
  * This define is provided as a convenience, looking up the property id
  * using the name->prop id lookup is the preferred method.
@@ -338,6 +352,7 @@ enum drm_mode_subconnector {
 #define DRM_MODE_CONNECTOR_VIRTUAL      15
 #define DRM_MODE_CONNECTOR_DSI		16
 #define DRM_MODE_CONNECTOR_DPI		17
+#define DRM_MODE_CONNECTOR_WRITEBACK	18
 
 struct drm_mode_get_connector {
 
@@ -363,7 +378,7 @@ struct drm_mode_get_connector {
 	__u32 pad;
 };
 
-#define DRM_MODE_PROP_PENDING	(1<<0)
+#define DRM_MODE_PROP_PENDING	(1<<0) /* deprecated, do not use */
 #define DRM_MODE_PROP_RANGE	(1<<1)
 #define DRM_MODE_PROP_IMMUTABLE	(1<<2)
 #define DRM_MODE_PROP_ENUM	(1<<3) /* enumerated type with text strings */
@@ -598,8 +613,11 @@ struct drm_mode_crtc_lut {
 };
 
 struct drm_color_ctm {
-	/* Conversion matrix in S31.32 format. */
-	__s64 matrix[9];
+	/*
+	 * Conversion matrix in S31.32 sign-magnitude
+	 * (not two's complement!) format.
+	 */
+	__u64 matrix[9];
 };
 
 struct drm_color_lut {
include/drm-uapi/etnaviv_drm.h +6 -0
index e9b997a0ef27..0d5c49dc478c 100644
@@ -55,6 +55,12 @@ struct drm_etnaviv_timespec {
 #define ETNAVIV_PARAM_GPU_FEATURES_4                0x07
 #define ETNAVIV_PARAM_GPU_FEATURES_5                0x08
 #define ETNAVIV_PARAM_GPU_FEATURES_6                0x09
+#define ETNAVIV_PARAM_GPU_FEATURES_7                0x0a
+#define ETNAVIV_PARAM_GPU_FEATURES_8                0x0b
+#define ETNAVIV_PARAM_GPU_FEATURES_9                0x0c
+#define ETNAVIV_PARAM_GPU_FEATURES_10               0x0d
+#define ETNAVIV_PARAM_GPU_FEATURES_11               0x0e
+#define ETNAVIV_PARAM_GPU_FEATURES_12               0x0f
 
 #define ETNAVIV_PARAM_GPU_STREAM_COUNT              0x10
 #define ETNAVIV_PARAM_GPU_REGISTER_MAX              0x11
include/drm-uapi/exynos_drm.h +240 -0

266 lines not on this page · raw message

include/drm-uapi/i915_drm.h +48 -1

75 lines not on this page · raw message

include/drm-uapi/msm_drm.h +2 -0
index bbbaffad772d..c06d0a5bdd80 100644
@@ -201,10 +201,12 @@ struct drm_msm_gem_submit_bo {
 #define MSM_SUBMIT_NO_IMPLICIT   0x80000000 /* disable implicit sync */
 #define MSM_SUBMIT_FENCE_FD_IN   0x40000000 /* enable input fence_fd */
 #define MSM_SUBMIT_FENCE_FD_OUT  0x20000000 /* enable output fence_fd */
+#define MSM_SUBMIT_SUDO          0x10000000 /* run submitted cmds from RB */
 #define MSM_SUBMIT_FLAGS                ( \
 		MSM_SUBMIT_NO_IMPLICIT   | \
 		MSM_SUBMIT_FENCE_FD_IN   | \
 		MSM_SUBMIT_FENCE_FD_OUT  | \
+		MSM_SUBMIT_SUDO          | \
 		0)
 
 /* Each cmdstream submit consists of a table of buffers involved, and
include/drm-uapi/tegra_drm.h +482 -10

632 lines not on this page · raw message

include/drm-uapi/v3d_drm.h new file +194 -0

194 lines not on this page · raw message

include/drm-uapi/vc4_drm.h +10 -3
index 4117117b4204..31f50de39acb 100644
@@ -183,10 +183,17 @@ struct drm_vc4_submit_cl {
 	/* ID of the perfmon to attach to this job. 0 means no perfmon. */
 	__u32 perfmonid;
 
-	/* Unused field to align this struct on 64 bits. Must be set to 0.
-	 * If one ever needs to add an u32 field to this struct, this field
-	 * can be used.
+	/* Syncobj handle to wait on. If set, processing of this render job
+	 * will not start until the syncobj is signaled. 0 means ignore.
 	 */
+	__u32 in_sync;
+
+	/* Syncobj handle to export fence to. If set, the fence in the syncobj
+	 * will be replaced with a fence that signals upon completion of this
+	 * render job. 0 means ignore.
+	 */
+	__u32 out_sync;
+
 	__u32 pad2;
 };
 
include/drm-uapi/virtgpu_drm.h +1 -0
index 91a31ffed828..9a781f0611df 100644
@@ -63,6 +63,7 @@ struct drm_virtgpu_execbuffer {
 };
 
 #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
+#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */
 
 struct drm_virtgpu_getparam {
 	__u64 param;
include/drm-uapi/vmwgfx_drm.h +128 -38

254 lines not on this page · raw message

Signature · 6 lines
2.17.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#2 lore raw

RFC 2/6 intel-gpu-overlay: Add engine queue stats

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

Use new PMU engine queue stats (queued, runnable and running) and display them per engine.

v2:
* Compact per engine stats. (Chris Wilson)

---
 overlay/gpu-top.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 overlay/gpu-top.h | 11 +++++++++++
 overlay/overlay.c |  7 +++++++
 3 files changed, 60 insertions(+)
overlay/gpu-top.c +42 -0
index 61b8f62fd78c..22e9badb22c1 100644
@@ -72,6 +72,18 @@ static int perf_init(struct gpu_top *gt)
 				 gt->fd) >= 0)
 		gt->have_sema = 1;
 
+	if (perf_i915_open_group(I915_PMU_ENGINE_QUEUED(d->class, d->inst),
+				 gt->fd) >= 0)
+		gt->have_queued = 1;
+
+	if (perf_i915_open_group(I915_PMU_ENGINE_RUNNABLE(d->class, d->inst),
+				 gt->fd) >= 0)
+		gt->have_runnable = 1;
+
+	if (perf_i915_open_group(I915_PMU_ENGINE_RUNNING(d->class, d->inst),
+				 gt->fd) >= 0)
+		gt->have_running = 1;
+
 	gt->ring[0].name = d->name;
 	gt->num_rings = 1;
 
@@ -93,6 +105,24 @@ static int perf_init(struct gpu_top *gt)
 				   gt->fd) < 0)
 			return -1;
 
+		if (gt->have_queued &&
+		    perf_i915_open_group(I915_PMU_ENGINE_QUEUED(d->class,
+								d->inst),
+				   gt->fd) < 0)
+			return -1;
+
+		if (gt->have_runnable &&
+		    perf_i915_open_group(I915_PMU_ENGINE_RUNNABLE(d->class,
+								  d->inst),
+				   gt->fd) < 0)
+			return -1;
+
+		if (gt->have_running &&
+		    perf_i915_open_group(I915_PMU_ENGINE_RUNNING(d->class,
+								 d->inst),
+				   gt->fd) < 0)
+			return -1;
+
 		gt->ring[gt->num_rings++].name = d->name;
 	}
 
@@ -298,6 +328,12 @@ int gpu_top_update(struct gpu_top *gt)
 				s->wait[n] = sample[m++];
 			if (gt->have_sema)
 				s->sema[n] = sample[m++];
+			if (gt->have_queued)
+				s->queued[n] = sample[m++];
+			if (gt->have_runnable)
+				s->runnable[n] = sample[m++];
+			if (gt->have_running)
+				s->running[n] = sample[m++];
 		}
 
 		if (gt->count == 1)
@@ -310,6 +346,12 @@ int gpu_top_update(struct gpu_top *gt)
 				gt->ring[n].u.u.wait = (100 * (s->wait[n] - d->wait[n]) + d_time/2) / d_time;
 			if (gt->have_sema)
 				gt->ring[n].u.u.sema = (100 * (s->sema[n] - d->sema[n]) + d_time/2) / d_time;
+			if (gt->have_queued)
+				gt->ring[n].queued = (double)((s->queued[n] - d->queued[n])) / I915_SAMPLE_QUEUED_DIVISOR * 1e9 / d_time;
+			if (gt->have_runnable)
+				gt->ring[n].runnable = (double)((s->runnable[n] - d->runnable[n])) / I915_SAMPLE_RUNNABLE_DIVISOR  * 1e9 / d_time;
+			if (gt->have_running)
+				gt->ring[n].running = (double)((s->running[n] - d->running[n])) / I915_SAMPLE_RUNNING_DIVISOR * 1e9 / d_time;
 
 			/* in case of rounding + sampling errors, fudge */
 			if (gt->ring[n].u.u.busy > 100)
overlay/gpu-top.h +11 -0
index d3cdd779760f..cb4310c82a94 100644
@@ -36,6 +36,9 @@ struct gpu_top {
 	int num_rings;
 	int have_wait;
 	int have_sema;
+	int have_queued;
+	int have_runnable;
+	int have_running;
 
 	struct gpu_top_ring {
 		const char *name;
@@ -47,6 +50,10 @@ struct gpu_top {
 			} u;
 			uint32_t payload;
 		} u;
+
+		double queued;
+		double runnable;
+		double running;
 	} ring[MAX_RINGS];
 
 	struct gpu_top_stat {
@@ -54,7 +61,11 @@ struct gpu_top {
 		uint64_t busy[MAX_RINGS];
 		uint64_t wait[MAX_RINGS];
 		uint64_t sema[MAX_RINGS];
+		uint64_t queued[MAX_RINGS];
+		uint64_t runnable[MAX_RINGS];
+		uint64_t running[MAX_RINGS];
 	} stat[2];
+
 	int count;
 };
 
overlay/overlay.c +7 -0
index eae5ddfa8823..7087d5e5b24e 100644
@@ -256,6 +256,13 @@ static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt
 		len = sprintf(txt, "%s: %3d%% busy",
 			      gt->gpu_top.ring[n].name,
 			      gt->gpu_top.ring[n].u.u.busy);
+		if (gt->gpu_top.have_queued &&
+		    gt->gpu_top.have_runnable &&
+		    gt->gpu_top.have_running)
+			len += sprintf(txt + len, " (%.2f / %.2f / %.2f)",
+				       gt->gpu_top.ring[n].queued,
+				       gt->gpu_top.ring[n].runnable,
+				       gt->gpu_top.ring[n].running);
 		if (gt->gpu_top.ring[n].u.u.wait)
 			len += sprintf(txt + len, ", %d%% wait",
 				       gt->gpu_top.ring[n].u.u.wait);
Signature · 6 lines
2.17.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#3 lore raw

RFC 3/6 intel-gpu-overlay: Show 1s, 30s and 15m GPU load

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

Show total GPU loads in the window banner.

Engine load is defined as total of runnable and running requests on an engine.

Total, non-normalized, load is display. In other words if N engines are busy with exactly one request, the load will be shown as N.

v2:
* Different flavour of load avg. (Chris Wilson)
* Simplify code. (Chris Wilson)

---
 overlay/gpu-top.c | 39 ++++++++++++++++++++++++++++++++++++++-
 overlay/gpu-top.h | 11 ++++++++++-
 overlay/overlay.c | 28 ++++++++++++++++++++++------
 3 files changed, 70 insertions(+), 8 deletions(-)
overlay/gpu-top.c +38 -1
index 22e9badb22c1..501429b86379 100644
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <math.h>
 #include <errno.h>
 #include <assert.h>
 
@@ -126,6 +127,10 @@ static int perf_init(struct gpu_top *gt)
 		gt->ring[gt->num_rings++].name = d->name;
 	}
 
+	gt->have_load_avg = gt->have_queued &&
+			    gt->have_runnable &&
+			    gt->have_running;
+
 	return 0;
 }
 
@@ -290,17 +295,32 @@ static void mmio_init(struct gpu_top *gt)
 	}
 }
 
-void gpu_top_init(struct gpu_top *gt)
+void gpu_top_init(struct gpu_top *gt, unsigned int period_us)
 {
+	const double period = (double)period_us / 1e6;
+	const double load_period[NUM_LOADS] = { 1.0, 30.0, 900.0 };
+	const char *load_names[NUM_LOADS] = { "1s", "30s", "15m" };
+	unsigned int i;
+
 	memset(gt, 0, sizeof(*gt));
 	gt->fd = -1;
 
+	for (i = 0; i < NUM_LOADS; i++) {
+		gt->load_name[i] = load_names[i];
+		gt->exp[i] = exp(-period / load_period[i]);
+	}
+
 	if (perf_init(gt) == 0)
 		return;
 
 	mmio_init(gt);
 }
 
+static double update_load(double load, double exp, double val)
+{
+	return val + exp * (load - val);
+}
+
 int gpu_top_update(struct gpu_top *gt)
 {
 	uint32_t data[1024];
@@ -313,6 +333,8 @@ int gpu_top_update(struct gpu_top *gt)
 		struct gpu_top_stat *s = &gt->stat[gt->count++&1];
 		struct gpu_top_stat *d = &gt->stat[gt->count&1];
 		uint64_t *sample, d_time;
+		double gpu_qd = 0.0;
+		unsigned int i;
 		int n, m;
 
 		len = read(gt->fd, data, sizeof(data));
@@ -341,6 +363,8 @@ int gpu_top_update(struct gpu_top *gt)
 
 		d_time = s->time - d->time;
 		for (n = 0; n < gt->num_rings; n++) {
+			double qd = 0.0;
+
 			gt->ring[n].u.u.busy = (100 * (s->busy[n] - d->busy[n]) + d_time/2) / d_time;
 			if (gt->have_wait)
 				gt->ring[n].u.u.wait = (100 * (s->wait[n] - d->wait[n]) + d_time/2) / d_time;
@@ -353,6 +377,14 @@ int gpu_top_update(struct gpu_top *gt)
 			if (gt->have_running)
 				gt->ring[n].running = (double)((s->running[n] - d->running[n])) / I915_SAMPLE_RUNNING_DIVISOR * 1e9 / d_time;
 
+			qd = gt->ring[n].runnable + gt->ring[n].running;
+			gpu_qd += qd;
+
+			for (i = 0; i < NUM_LOADS; i++)
+				gt->ring[n].load[i] =
+					update_load(gt->ring[n].load[i],
+						    gt->exp[i], qd);
+
 			/* in case of rounding + sampling errors, fudge */
 			if (gt->ring[n].u.u.busy > 100)
 				gt->ring[n].u.u.busy = 100;
@@ -362,6 +394,11 @@ int gpu_top_update(struct gpu_top *gt)
 				gt->ring[n].u.u.sema = 100;
 		}
 
+		for (i = 0; i < NUM_LOADS; i++) {
+			gt->load[i] = update_load(gt->load[i], gt->exp[i],
+						  gpu_qd);
+			gt->norm_load[i] = gt->load[i] / gt->num_rings;
+		}
 		update = 1;
 	} else {
 		while ((len = read(gt->fd, data, sizeof(data))) > 0) {
overlay/gpu-top.h +10 -1
index cb4310c82a94..115ce8c482c1 100644
@@ -26,6 +26,7 @@
 #define GPU_TOP_H
 
 #define MAX_RINGS 16
+#define NUM_LOADS 3
 
 #include <stdint.h>
 
@@ -39,6 +40,12 @@ struct gpu_top {
 	int have_queued;
 	int have_runnable;
 	int have_running;
+	int have_load_avg;
+
+	double exp[NUM_LOADS];
+	double load[NUM_LOADS];
+	double norm_load[NUM_LOADS];
+	const char *load_name[NUM_LOADS];
 
 	struct gpu_top_ring {
 		const char *name;
@@ -54,6 +61,8 @@ struct gpu_top {
 		double queued;
 		double runnable;
 		double running;
+
+		double load[NUM_LOADS];
 	} ring[MAX_RINGS];
 
 	struct gpu_top_stat {
@@ -69,7 +78,7 @@ struct gpu_top {
 	int count;
 };
 
-void gpu_top_init(struct gpu_top *gt);
+void gpu_top_init(struct gpu_top *gt, unsigned int period_us);
 int gpu_top_update(struct gpu_top *gt);
 
 #endif /* GPU_TOP_H */
overlay/overlay.c +22 -6
index 7087d5e5b24e..1a1d01db082b 100644
@@ -141,7 +141,8 @@ struct overlay_context {
 };
 
 static void init_gpu_top(struct overlay_context *ctx,
-			 struct overlay_gpu_top *gt)
+			 struct overlay_gpu_top *gt,
+			 unsigned int period_us)
 {
 	const double rgba[][4] = {
 		{ 1, 0.25, 0.25, 1 },
@@ -153,7 +154,7 @@ static void init_gpu_top(struct overlay_context *ctx,
 	int n;
 
 	cpu_top_init(&gt->cpu_top);
-	gpu_top_init(&gt->gpu_top);
+	gpu_top_init(&gt->gpu_top, period_us);
 
 	chart_init(&gt->cpu, "CPU", 120);
 	chart_set_position(&gt->cpu, PAD, PAD);
@@ -928,13 +929,13 @@ int main(int argc, char **argv)
 
 	debugfs_init();
 
-	init_gpu_top(&ctx, &ctx.gpu_top);
+	sample_period = get_sample_period(&config);
+
+	init_gpu_top(&ctx, &ctx.gpu_top, sample_period);
 	init_gpu_perf(&ctx, &ctx.gpu_perf);
 	init_gpu_freq(&ctx, &ctx.gpu_freq);
 	init_gem_objects(&ctx, &ctx.gem_objects);
 
-	sample_period = get_sample_period(&config);
-
 	i = 0;
 	while (1) {
 		ctx.time = time(NULL);
@@ -950,9 +951,24 @@ int main(int argc, char **argv)
 		show_gem_objects(&ctx, &ctx.gem_objects);
 
 		{
-			char buf[80];
+			struct gpu_top *gt = &ctx.gpu_top.gpu_top;
 			cairo_text_extents_t extents;
+			char buf[256];
+
 			gethostname(buf, sizeof(buf));
+
+			if (gt->have_load_avg) {
+				int len = strlen(buf);
+
+				snprintf(buf + len, sizeof(buf) - len,
+					 "%s; %u engines; load %s %.2f, %s %.2f, %s %.2f",
+					 buf,
+					 gt->num_rings,
+					 gt->load_name[0], gt->load[0],
+					 gt->load_name[1], gt->load[1],
+					 gt->load_name[2], gt->load[2]);
+			}
+
 			cairo_set_source_rgb(ctx.cr, .5, .5, .5);
 			cairo_set_font_size(ctx.cr, PAD-2);
 			cairo_text_extents(ctx.cr, buf, &extents);
Signature · 6 lines
2.17.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#4 lore raw

RFC 4/6 tests/perf_pmu: Add tests for engine queued/runnable/running stats

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

Simple tests to check reported queue depths are correct.

v2:
* Improvements similar to ones from i915_query.c.

v3:
* Rebase for __igt_spin_batch_new.

---
 tests/perf_pmu.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 259 insertions(+)
tests/perf_pmu.c +259 -0
index 6ab2595b114d..6f064b605a4c 100644
@@ -169,6 +169,7 @@ static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
 #define TEST_RUNTIME_PM (8)
 #define FLAG_LONG (16)
 #define FLAG_HANG (32)
+#define TEST_CONTEXTS (64)
 
 static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
 {
@@ -959,6 +960,224 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
 	assert_within_epsilon(val[1], perf_slept[1], tolerance);
 }
 
+static double calc_queued(uint64_t d_val, uint64_t d_ns)
+{
+	return (double)d_val * 1e9 / I915_SAMPLE_QUEUED_DIVISOR / d_ns;
+}
+
+static void
+queued(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+{
+	const unsigned long engine = e2ring(gem_fd, e);
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	const unsigned int max_rq = 10;
+	double queued[max_rq + 1];
+	unsigned int n, i;
+	uint64_t val[2];
+	uint64_t ts[2];
+	uint32_t bo;
+	int fd;
+
+	igt_require_sw_sync();
+	if (flags & TEST_CONTEXTS)
+		gem_require_contexts(gem_fd);
+
+	memset(queued, 0, sizeof(queued));
+
+	bo = gem_create(gem_fd, 4096);
+	gem_write(gem_fd, bo, 4092, &bbe, sizeof(bbe));
+
+	fd = open_pmu(I915_PMU_ENGINE_QUEUED(e->class, e->instance));
+
+	for (n = 0; n <= max_rq; n++) {
+		IGT_CORK_FENCE(cork);
+		int fence = -1;
+
+		gem_quiescent_gpu(gem_fd);
+
+		if (n)
+			fence = igt_cork_plug(&cork, -1);
+
+		for (i = 0; i < n; i++) {
+			struct drm_i915_gem_exec_object2 obj = { };
+			struct drm_i915_gem_execbuffer2 eb = { };
+
+			obj.handle = bo;
+
+			eb.buffer_count = 1;
+			eb.buffers_ptr = to_user_pointer(&obj);
+
+			eb.flags = engine | I915_EXEC_FENCE_IN;
+			if (flags & TEST_CONTEXTS)
+				eb.rsvd1 = gem_context_create(gem_fd);
+			eb.rsvd2 = fence;
+
+			gem_execbuf(gem_fd, &eb);
+
+			if (flags & TEST_CONTEXTS)
+				gem_context_destroy(gem_fd, eb.rsvd1);
+		}
+
+		val[0] = __pmu_read_single(fd, &ts[0]);
+		usleep(batch_duration_ns / 1000);
+		val[1] = __pmu_read_single(fd, &ts[1]);
+
+		queued[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
+		igt_info("n=%u queued=%.2f\n", n, queued[n]);
+
+		if (fence >= 0)
+			igt_cork_unplug(&cork);
+
+		for (i = 0; i < n; i++)
+			gem_sync(gem_fd, bo);
+	}
+
+	close(fd);
+
+	gem_close(gem_fd, bo);
+
+	for (i = 0; i <= max_rq; i++)
+		assert_within_epsilon(queued[i], i, tolerance);
+}
+
+static unsigned long __query_wait(igt_spin_t *spin, unsigned int n)
+{
+	struct timespec ts = { };
+	unsigned long t;
+
+	igt_nsec_elapsed(&ts);
+
+	if (spin->running) {
+		igt_spin_busywait_until_running(spin);
+	} else {
+		igt_debug("__spin_wait - usleep mode\n");
+		usleep(500e3); /* Better than nothing! */
+	}
+
+	t = igt_nsec_elapsed(&ts);
+
+	return spin->running ? t : 500e6 / n;
+}
+
+static void
+runnable(int gem_fd, const struct intel_execution_engine2 *e)
+{
+	const unsigned long engine = e2ring(gem_fd, e);
+	bool contexts = gem_has_contexts(gem_fd);
+	const unsigned int max_rq = 10;
+	igt_spin_t *spin[max_rq + 1];
+	double runnable[max_rq + 1];
+	uint32_t ctx[max_rq];
+	unsigned int n, i;
+	uint64_t val[2];
+	uint64_t ts[2];
+	int fd;
+
+	memset(runnable, 0, sizeof(runnable));
+
+	if (contexts) {
+		for (i = 0; i < max_rq; i++)
+			ctx[i] = gem_context_create(gem_fd);
+	}
+
+	fd = open_pmu(I915_PMU_ENGINE_RUNNABLE(e->class, e->instance));
+
+	for (n = 0; n <= max_rq; n++) {
+		gem_quiescent_gpu(gem_fd);
+
+		for (i = 0; i < n; i++) {
+			uint32_t ctx_ = contexts ? ctx[i] : 0;
+
+			if (i == 0)
+				spin[i] = __spin_poll(gem_fd, ctx_, engine);
+			else
+				spin[i] = __igt_spin_batch_new(gem_fd,
+							       .ctx = ctx_,
+							       .engine = engine);
+		}
+
+		if (n)
+			usleep(__query_wait(spin[0], n) * n);
+
+		val[0] = __pmu_read_single(fd, &ts[0]);
+		usleep(batch_duration_ns / 1000);
+		val[1] = __pmu_read_single(fd, &ts[1]);
+
+		runnable[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
+		igt_info("n=%u runnable=%.2f\n", n, runnable[n]);
+
+		for (i = 0; i < n; i++) {
+			end_spin(gem_fd, spin[i], FLAG_SYNC);
+			igt_spin_batch_free(gem_fd, spin[i]);
+		}
+	}
+
+	if (contexts) {
+		for (i = 0; i < max_rq; i++)
+			gem_context_destroy(gem_fd, ctx[i]);
+	}
+
+	close(fd);
+
+	assert_within_epsilon(runnable[0], 0, tolerance);
+	igt_assert(runnable[max_rq] > 0.0);
+
+	if (contexts)
+		assert_within_epsilon(runnable[max_rq] - runnable[max_rq - 1],
+				      1, tolerance);
+}
+
+static void
+running(int gem_fd, const struct intel_execution_engine2 *e)
+{
+	const unsigned long engine = e2ring(gem_fd, e);
+	const unsigned int max_rq = 10;
+	igt_spin_t *spin[max_rq + 1];
+	double running[max_rq + 1];
+	unsigned int n, i;
+	uint64_t val[2];
+	uint64_t ts[2];
+	int fd;
+
+	memset(running, 0, sizeof(running));
+	memset(spin, 0, sizeof(spin));
+
+	fd = open_pmu(I915_PMU_ENGINE_RUNNING(e->class, e->instance));
+
+	for (n = 0; n <= max_rq; n++) {
+		gem_quiescent_gpu(gem_fd);
+
+		for (i = 0; i < n; i++) {
+			if (i == 0)
+				spin[i] = __spin_poll(gem_fd, 0, engine);
+			else
+				spin[i] = __igt_spin_batch_new(gem_fd,
+							       .engine = engine);
+		}
+
+		if (n)
+			usleep(__query_wait(spin[0], n) * n);
+
+		val[0] = __pmu_read_single(fd, &ts[0]);
+		usleep(batch_duration_ns / 1000);
+		val[1] = __pmu_read_single(fd, &ts[1]);
+
+		running[n] = calc_queued(val[1] - val[0], ts[1] - ts[0]);
+		igt_info("n=%u running=%.2f\n", n, running[n]);
+
+		for (i = 0; i < n; i++) {
+			end_spin(gem_fd, spin[i], FLAG_SYNC);
+			igt_spin_batch_free(gem_fd, spin[i]);
+		}
+	}
+
+	close(fd);
+
+	assert_within_epsilon(running[0], 0, tolerance);
+	for (i = 1; i <= max_rq; i++)
+		igt_assert(running[i] > 0);
+}
+
 /**
  * Tests that i915 PMU corectly errors out in invalid initialization.
  * i915 PMU is uncore PMU, thus:
@@ -1709,6 +1928,15 @@ igt_main
 		igt_subtest_f("init-sema-%s", e->name)
 			init(fd, e, I915_SAMPLE_SEMA);
 
+		igt_subtest_f("init-queued-%s", e->name)
+			init(fd, e, I915_SAMPLE_QUEUED);
+
+		igt_subtest_f("init-runnable-%s", e->name)
+			init(fd, e, I915_SAMPLE_RUNNABLE);
+
+		igt_subtest_f("init-running-%s", e->name)
+			init(fd, e, I915_SAMPLE_RUNNING);
+
 		igt_subtest_group {
 			igt_fixture {
 				gem_require_engine(fd, e->class, e->instance);
@@ -1814,6 +2042,27 @@ igt_main
 
 			igt_subtest_f("busy-hang-%s", e->name)
 				single(fd, e, TEST_BUSY | FLAG_HANG);
+
+			/**
+			 * Test that queued metric works.
+			 */
+			igt_subtest_f("queued-%s", e->name)
+				queued(fd, e, 0);
+
+			igt_subtest_f("queued-contexts-%s", e->name)
+				queued(fd, e, TEST_CONTEXTS);
+
+			/**
+			 * Test that runnable metric works.
+			 */
+			igt_subtest_f("runnable-%s", e->name)
+				runnable(fd, e);
+
+			/**
+			 * Test that running metric works.
+			 */
+			igt_subtest_f("running-%s", e->name)
+				running(fd, e);
 		}
 
 		/**
@@ -1906,6 +2155,16 @@ igt_main
 					      e->name)
 					single(render_fd, e,
 					       TEST_BUSY | TEST_TRAILING_IDLE);
+				igt_subtest_f("render-node-queued-%s", e->name)
+					queued(render_fd, e, 0);
+				igt_subtest_f("render-node-queued-contexts-%s",
+					      e->name)
+					queued(render_fd, e, TEST_CONTEXTS);
+				igt_subtest_f("render-node-runnable-%s",
+					      e->name)
+					runnable(render_fd, e);
+				igt_subtest_f("render-node-running-%s", e->name)
+					running(render_fd, e);
 			}
 		}
 
Signature · 6 lines
2.17.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#5 lore raw

RFC 5/6 intel-gpu-top: Add queue depths and load average

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

With the driver now exporting various request queue depths for each engine, we can display this information here. Both as raw counters, and by adding a load average like metrics composed from number of runnable and running requests in a given time period. 1s, 30s and 5m periods are used for load average.

---
 tools/Makefile.am     |   2 +-
 tools/intel_gpu_top.c | 122 +++++++++++++++++++++++++++++++++++++-----
 tools/meson.build     |   2 +-
 3 files changed, 110 insertions(+), 16 deletions(-)
tools/Makefile.am +1 -1
index e7de4d90241c..e03842afce8d 100644
@@ -29,7 +29,7 @@ intel_aubdump_la_LDFLAGS = -module -avoid-version -no-undefined
 intel_aubdump_la_SOURCES = aubdump.c
 intel_aubdump_la_LIBADD = $(top_builddir)/lib/libintel_tools.la -ldl
 
-intel_gpu_top_LDADD = $(top_builddir)/lib/libigt_perf.la
+intel_gpu_top_LDADD = $(top_builddir)/lib/libigt_perf.la -lm
 
 bin_SCRIPTS = intel_aubdump
 CLEANFILES = $(bin_SCRIPTS)
tools/intel_gpu_top.c +108 -14

246 lines not on this page · raw message

tools/meson.build +1 -1
index e4517d667299..c1dd71fada79 100644
@@ -97,7 +97,7 @@ shared_library('intel_aubdump', 'aubdump.c',
 executable('intel_gpu_top', 'intel_gpu_top.c',
 	   install : true,
 	   install_rpath : bindir_rpathdir,
-	   dependencies : tool_deps + [ lib_igt_perf ])
+	   dependencies : tool_deps + [ lib_igt_perf, math ])
 
 conf_data = configuration_data()
 conf_data.set('prefix', prefix)
Signature · 6 lines
2.17.1

_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev
#6 lore raw

RFC 6/6 intel-gpu-top: Support for client stats

In reply to Tvrtko Ursulin

From: Tvrtko Ursulin <[email protected]>

---
 tools/intel_gpu_top.c | 360 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 351 insertions(+), 9 deletions(-)
tools/intel_gpu_top.c +351 -9
index 8990ef17b771..02c5a7d77614 100644
@@ -20,9 +20,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Authors:
- *    Eric Anholt <[email protected]>
- *    Eugeni Dodonov <[email protected]>
  */
 
 #include <stdio.h>
@@ -41,6 +38,8 @@
 #include <errno.h>
 #include <math.h>
 #include <locale.h>
+#include <limits.h>
+#include <signal.h>
 
 #include "igt_perf.h"
 
@@ -701,8 +700,300 @@ static void pmu_sample(struct engines *engines)
 	}
 }
 
+enum client_status {
+	FREE = 0, /* mbz */
+	ALIVE,
+	PROBE
+};
+
+struct client {
+	enum client_status status;
+	unsigned int id;
+	unsigned int pid;
+	char name[128];
+	unsigned int samples;
+	unsigned long total;
+	struct engines *engines;
+	unsigned long *val;
+	uint64_t *last;
+};
+
+#define SYSFS_ENABLE "/sys/class/drm/card0/clients/enable_stats"
+
+bool __stats_enabled;
+
+static int __set_stats(bool val)
+{
+	int fd, ret;
+
+	fd = open(SYSFS_ENABLE, O_WRONLY);
+	if (fd < 0)
+		return -errno;
+
+	ret = write(fd, val ? "1" : "0", 2);
+	if (ret < 0)
+		return -errno;
+	else if (ret < 2)
+		return 1;
+
+	close(fd);
+
+	return 0;
+}
+
+static void __restore_stats(void)
+{
+	int ret;
+
+	if (__stats_enabled)
+		return;
+
+	ret = __set_stats(false);
+	if (ret)
+		fprintf(stderr, "Failed to disable per-client stats! (%d)\n",
+			ret);
+}
+
+static void __restore_stats_signal(int sig)
+{
+	exit(0);
+}
+
+static void enable_stats(void)
+{
+	int fd, ret;
+
+	fd = open(SYSFS_ENABLE, O_RDONLY);
+	if (fd < 0)
+		return;
+
+	close(fd);
+
+	__stats_enabled = filename_to_u64(SYSFS_ENABLE, 10);
+	if (__stats_enabled)
+		return;
+
+	ret = __set_stats(true);
+	if (!ret) {
+		if (atexit(__restore_stats))
+			fprintf(stderr, "Failed to register exit handler!");
+
+		if (signal(SIGINT, __restore_stats_signal))
+			fprintf(stderr, "Failed to register signal handler!");
+	} else {
+		fprintf(stderr, "Failed to enable per-client stats! (%d)\n",
+			ret);
+	}
+}
+
+#define SYSFS_CLIENTS "/sys/class/drm/card0/clients/"
+
+static struct client *clients;
+static unsigned int num_clients;
+
+#define for_each_client(c, tmp) \
+	for (tmp = num_clients, c = clients; tmp > 0; tmp--, c++)
+
+static uint64_t read_client_busy(unsigned int id, const char *engine)
+{
+	char buf[256];
+	ssize_t ret;
+
+	ret = snprintf(buf, sizeof(buf), SYSFS_CLIENTS "/%u/busy/%s",
+		       id, engine);
+	assert(ret > 0 && ret < sizeof(buf));
+	if (ret <= 0 || ret == sizeof(buf))
+		return 0;
+
+	return filename_to_u64(buf, 10);
+}
+
+static struct client *find_client(enum client_status status, unsigned int id)
+{
+	struct client *c;
+	unsigned int tmp;
+
+	for_each_client(c, tmp) {
+		if ((status == FREE && c->status == FREE) ||
+		    (status == c->status && c->id == id))
+			return c;
+	}
+
+	return NULL;
+}
+
+static void update_client(struct client *c, unsigned int pid, char *name)
+{
+	uint64_t val[c->engines->num_engines];
+	unsigned int i;
+
+	if (c->pid != pid)
+		c->pid = pid;
+
+	if (strncmp(c->name, name, sizeof(c->name)))
+		strncpy(c->name, name, sizeof(c->name));
+
+	for (i = 0; i < c->engines->num_engines; i++) {
+		struct engine *engine = engine_ptr(c->engines, i);
+
+		val[i] = read_client_busy(c->id, engine->name);
+	}
+
+	c->total = 0;
+
+	for (i = 0; i < c->engines->num_engines; i++) {
+		assert(val[i] >= c->last[i]);
+		c->val[i] = val[i] - c->last[i];
+		c->total += c->val[i];
+		c->last[i] = val[i];
+	}
+
+	c->samples++;
+	c->status = ALIVE;
+}
+
+static void
+add_client(unsigned int id, unsigned int pid, char *name,
+	   struct engines *engines)
+{
+	struct client *c;
+
+	assert(!find_client(ALIVE, id));
+
+	c = find_client(FREE, 0);
+	if (!c) {
+		unsigned int idx = num_clients;
+
+		num_clients += (num_clients + 2) / 2;
+		clients = realloc(clients, num_clients * sizeof(*c));
+		assert(clients);
+		c = &clients[idx];
+		memset(c, 0, (num_clients - idx) * sizeof(*c));
+	}
+
+	c->id = id;
+	c->engines = engines;
+	c->val = calloc(engines->num_engines, sizeof(c->val));
+	c->last = calloc(engines->num_engines, sizeof(c->last));
+	assert(c->val && c->last);
+
+	update_client(c, pid, name);
+}
+
+static void free_client(struct client *c)
+{
+	free(c->val);
+	free(c->last);
+	memset(c, 0, sizeof(*c));
+}
+
+static char *read_client_sysfs(unsigned int id, const char *field)
+{
+	char buf[256];
+	ssize_t ret;
+
+	ret = snprintf(buf, sizeof(buf), SYSFS_CLIENTS "/%u/%s", id, field);
+	assert(ret > 0 && ret < sizeof(buf));
+	if (ret <= 0 || ret == sizeof(buf))
+		return NULL;
+
+	ret = filename_to_buf(buf, buf, sizeof(buf));
+	assert(ret == 0);
+	if (ret)
+		return NULL;
+
+	return strdup(buf);
+}
+
+static void scan(struct engines *engines)
+{
+	struct dirent *dent;
+	struct client *c;
+	char *pid, *name;
+	unsigned int tmp;
+	unsigned int id;
+	DIR *d;
+
+	for_each_client(c, tmp) {
+		if (c->status == ALIVE)
+			c->status = PROBE;
+	}
+
+	d = opendir(SYSFS_CLIENTS);
+	if (!d)
+		return;
+
+	while ((dent = readdir(d)) != NULL) {
+		if (dent->d_type != DT_DIR)
+			continue;
+		if (!isdigit(dent->d_name[0]))
+			continue;
+
+		id = atoi(dent->d_name);
+
+		name = read_client_sysfs(id, "name");
+		assert(name);
+		if (!name)
+			continue;
+
+		pid = read_client_sysfs(id, "pid");
+		assert(pid);
+		if (!pid) {
+			free(name);
+			continue;
+		}
+
+		c = find_client(PROBE, id);
+		if (c) {
+			update_client(c, atoi(pid), name);
+			continue;
+		}
+
+		add_client(id, atoi(pid), name, engines);
+
+		free(name);
+		free(pid);
+	}
+
+	closedir(d);
+
+	for_each_client(c, tmp) {
+		if (c->status == PROBE)
+			free_client(c);
+	}
+}
+
+static int cmp(const void *_a, const void *_b)
+{
+	const struct client *a = _a;
+	const struct client *b = _b;
+	long tot_a = a->total;
+	long tot_b = b->total;
+
+	tot_a *= a->status == ALIVE && a->samples > 1;
+	tot_b *= b->status == ALIVE && b->samples > 1;
+
+	tot_b -= tot_a;
+
+	if (!tot_b)
+		return (int)b->id - a->id;
+
+	while (tot_b > INT_MAX || tot_b < INT_MIN)
+		tot_b /= 2;
+
+	return tot_b;
+}
+
 static const char *bars[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
 
+static void n_spaces(const unsigned int n)
+{
+	unsigned int i;
+
+	for (i = 0; i < n; i++)
+		putchar(' ');
+}
+
 static void
 print_percentage_bar(double percent, int max_len)
 {
@@ -716,8 +1007,10 @@ print_percentage_bar(double percent, int max_len)
 	if (i)
 		printf("%s", bars[i]);
 
-	for (i = 0; i < (max_len - 2 - (bar_len + 7) / 8); i++)
-		putchar(' ');
+	bar_len = max_len - 2 - (bar_len + 7) / 8;
+	if (bar_len > max_len)
+		bar_len = max_len;
+	n_spaces(bar_len);
 
 	putchar('|');
 }
@@ -784,12 +1077,15 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
+	enable_stats();
+
 	/* Load average setup. */
 	period = (double)period_us / 1e6;
 	for (i = 0; i < NUM_LOADS; i++)
 		engines->load_exp[i] = exp(-period / load_period[i]);
 
 	pmu_sample(engines);
+	scan(engines);
 
 	for (;;) {
 		double t, qd = 0;
@@ -802,7 +1098,8 @@ int main(int argc, char **argv)
 		char reads[BUFSZ];
 		char writes[BUFSZ];
 		struct winsize ws;
-		unsigned int j;
+		unsigned int len, engine_w, j;
+		struct client *c;
 		int lines = 0;
 
 		/* Update terminal size. */
@@ -812,9 +1109,10 @@ int main(int argc, char **argv)
 		}
 
 		pmu_sample(engines);
-		t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;
+		scan(engines);
+		qsort(clients, num_clients, sizeof(*c), cmp);
 
-		printf("\033[H\033[J");
+		t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;
 
 		pmu_calc(&engines->freq_req, freq, BUFSZ, 4, 0, 1.0, t, 1);
 		pmu_calc(&engines->freq_act, fact, BUFSZ, 4, 0, 1.0, t, 1);
@@ -860,6 +1158,8 @@ int main(int argc, char **argv)
 					    qd);
 		}
 
+		printf("\033[H\033[J");
+
 		if (lines++ < con_h)
 			printf("intel-gpu-top - load avg %5.2f, %5.2f, %5.2f; %s/%s MHz;  %s%% RC6; %s %s; %s irqs/s\n",
 			       engines->load_avg[0],
@@ -903,7 +1203,6 @@ int main(int argc, char **argv)
 			struct engine *engine = engine_ptr(engines, i);
 			unsigned int max_w = con_w - 1;
 			char qdbuf[NUM_LOADS][BUFSZ];
-			unsigned int len;
 			char sema[BUFSZ];
 			char wait[BUFSZ];
 			char busy[BUFSZ];
@@ -941,6 +1240,49 @@ int main(int argc, char **argv)
 		if (lines++ < con_h)
 			printf("\n");
 
+		if (lines++ < con_h) {
+			printf("\033[7m");
+			len = printf("%5s%16s", "PID", "NAME");
+
+			engine_w = (con_w - len) / engines->num_engines;
+			for (i = 0; i < engines->num_engines; i++) {
+				struct engine *engine = engine_ptr(engines, i);
+				unsigned int name_len =
+					strlen(engine->display_name);
+				unsigned int pad = (engine_w - name_len) / 2;
+
+
+				n_spaces(pad);
+				printf("%s", engine->display_name);
+				n_spaces(engine_w - pad - name_len);
+				len += pad + name_len + (engine_w - pad -
+				       name_len);
+			}
+			n_spaces(con_w - len);
+			printf("\033[0m\n");
+		}
+
+		for_each_client(c, i) {
+			if (lines++ > con_h)
+				break;
+
+			assert(c->status != PROBE);
+			if (c->status != ALIVE || c->samples < 2)
+				break;
+
+			printf("%5u%16s ", c->pid, c->name);
+
+			for (j = 0; j < engines->num_engines; j++) {
+				double pct;
+
+				pct = (double)c->val[j] / period_us / 1e3 * 100;
+
+				print_percentage_bar(pct, engine_w);
+			}
+
+			putchar('\n');
+		}
+
 		usleep(period_us);
 	}
 
Signature · 6 lines
2.17.1

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

[igt-dev] ✓ Fi.CI.BAT: success for 21st century intel_gpu_top & Co.

In reply to Tvrtko Ursulin
== Series Details ==

== Series Details ==

Series: 21st century intel_gpu_top & Co.
URL : https://patchwork.freedesktop.org/series/50499/
State : success

== Summary ==

= CI Bug Log - changes from CI_DRM_4918 -> IGTPW_1901 =

== Summary - SUCCESS ==

No regressions found.

External URL: https://patchwork.freedesktop.org/api/1.0/series/50499/revisions/1/mbox/

== Known issues ==

Here are the changes found in IGTPW_1901 that come from known issues:

=== IGT changes ===

    ==== Issues hit ====

    igt@drv_module_reload@basic-reload-inject:
      fi-glk-j4005:       PASS -> DMESG-WARN (fdo#106725, fdo#106248) +1

    igt@gem_wait@basic-busy-all:
      fi-skl-gvtdvm:      PASS -> DMESG-WARN (fdo#105541)

    igt@kms_cursor_legacy@basic-flip-before-cursor-atomic:
      fi-glk-j4005:       PASS -> DMESG-WARN (fdo#105719)

    igt@kms_flip@basic-flip-vs-modeset:
      fi-glk-j4005:       PASS -> DMESG-WARN (fdo#106000)

    igt@kms_flip@basic-flip-vs-wf_vblank:
      fi-glk-j4005:       PASS -> FAIL (fdo#100368)

    igt@kms_flip@basic-plain-flip:
      fi-glk-j4005:       PASS -> DMESG-WARN (fdo#106097)

    igt@kms_pipe_crc_basic@read-crc-pipe-a-frame-sequence:
      fi-byt-clapper:     PASS -> FAIL (fdo#103191, fdo#107362)

fdo#100368 https://bugs.freedesktop.org/show_bug.cgi?id=100368
fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
fdo#105541 https://bugs.freedesktop.org/show_bug.cgi?id=105541
fdo#105719 https://bugs.freedesktop.org/show_bug.cgi?id=105719
fdo#106000 https://bugs.freedesktop.org/show_bug.cgi?id=106000
fdo#106097 https://bugs.freedesktop.org/show_bug.cgi?id=106097
fdo#106248 https://bugs.freedesktop.org/show_bug.cgi?id=106248
fdo#106725 https://bugs.freedesktop.org/show_bug.cgi?id=106725
fdo#107362 https://bugs.freedesktop.org/show_bug.cgi?id=107362

== Participating hosts (48 -> 43) ==

Additional (1): fi-cfl-guc
Missing (6): fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-icl-u2 fi-snb-2520m fi-bdw-samus

== Build changes ==

* IGT: IGT_4662 -> IGTPW_1901

CI_DRM_4918: f595aba3a6e2f6972bb158eb8434b58d22d0e5f0 @ git://anongit.freedesktop.org/gfx-ci/linux
IGTPW_1901: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1901/
IGT_4662: ebf6a1dd1795e2f014ff3c47fe2eb4d5255845bd @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Testlist changes ==

+igt@perf_pmu@init-queued-bcs0
+igt@perf_pmu@init-queued-rcs0
+igt@perf_pmu@init-queued-vcs0
+igt@perf_pmu@init-queued-vcs1
+igt@perf_pmu@init-queued-vecs0
+igt@perf_pmu@init-runnable-bcs0
+igt@perf_pmu@init-runnable-rcs0
+igt@perf_pmu@init-runnable-vcs0
+igt@perf_pmu@init-runnable-vcs1
+igt@perf_pmu@init-runnable-vecs0
+igt@perf_pmu@init-running-bcs0
+igt@perf_pmu@init-running-rcs0
+igt@perf_pmu@init-running-vcs0
+igt@perf_pmu@init-running-vcs1
+igt@perf_pmu@init-running-vecs0
+igt@perf_pmu@queued-bcs0
+igt@perf_pmu@queued-contexts-bcs0
+igt@perf_pmu@queued-contexts-rcs0
+igt@perf_pmu@queued-contexts-vcs0
+igt@perf_pmu@queued-contexts-vcs1
+igt@perf_pmu@queued-contexts-vecs0
+igt@perf_pmu@queued-rcs0
+igt@perf_pmu@queued-vcs0
+igt@perf_pmu@queued-vcs1
+igt@perf_pmu@queued-vecs0
+igt@perf_pmu@render-node-queued-bcs0
+igt@perf_pmu@render-node-queued-contexts-bcs0
+igt@perf_pmu@render-node-queued-contexts-rcs0
+igt@perf_pmu@render-node-queued-contexts-vcs0
+igt@perf_pmu@render-node-queued-contexts-vcs1
+igt@perf_pmu@render-node-queued-contexts-vecs0
+igt@perf_pmu@render-node-queued-rcs0
+igt@perf_pmu@render-node-queued-vcs0
+igt@perf_pmu@render-node-queued-vcs1
+igt@perf_pmu@render-node-queued-vecs0
+igt@perf_pmu@render-node-runnable-bcs0
+igt@perf_pmu@render-node-runnable-rcs0
+igt@perf_pmu@render-node-runnable-vcs0
+igt@perf_pmu@render-node-runnable-vcs1
+igt@perf_pmu@render-node-runnable-vecs0
+igt@perf_pmu@render-node-running-bcs0
+igt@perf_pmu@render-node-running-rcs0
+igt@perf_pmu@render-node-running-vcs0
+igt@perf_pmu@render-node-running-vcs1
+igt@perf_pmu@render-node-running-vecs0
+igt@perf_pmu@runnable-bcs0
+igt@perf_pmu@runnable-rcs0
+igt@perf_pmu@runnable-vcs0
+igt@perf_pmu@runnable-vcs1
+igt@perf_pmu@runnable-vecs0
+igt@perf_pmu@running-bcs0
+igt@perf_pmu@running-rcs0
+igt@perf_pmu@running-vcs0
+igt@perf_pmu@running-vcs1
+igt@perf_pmu@running-vecs0

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1901/issues.html
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev

#8 lore raw

[igt-dev] ✗ Fi.CI.IGT: failure for 21st century intel_gpu_top & Co.

In reply to Tvrtko Ursulin
== Series Details ==

== Series Details ==

Series: 21st century intel_gpu_top & Co.
URL : https://patchwork.freedesktop.org/series/50499/
State : failure

== Summary ==

= CI Bug Log - changes from IGT_4662_full -> IGTPW_1901_full =

== Summary - FAILURE ==

Serious unknown changes coming with IGTPW_1901_full absolutely need to be verified manually.

If you think the reported changes have nothing to do with the changes introduced in IGTPW_1901_full, please notify your bug team to allow them to document this new failure mode, which will reduce false positives in CI.

External URL: https://patchwork.freedesktop.org/api/1.0/series/50499/revisions/1/mbox/

== Possible new issues ==

Here are the unknown changes that may have been introduced in IGTPW_1901_full:

=== IGT changes ===

    ==== Possible regressions ====

    igt@perf_pmu@queued-contexts-bcs0:
      shard-hsw:          NOTRUN -> FAIL +43

    igt@perf_pmu@render-node-runnable-vcs0:
      shard-apl:          NOTRUN -> FAIL +43

    igt@perf_pmu@runnable-bcs0:
      shard-snb:          NOTRUN -> FAIL +24

    igt@perf_pmu@running-vcs1:
      shard-kbl:          NOTRUN -> FAIL +54

== Known issues ==

Here are the changes found in IGTPW_1901_full that come from known issues:

=== IGT changes ===

    ==== Issues hit ====

    igt@drv_suspend@shrink:
      shard-snb:          PASS -> INCOMPLETE (fdo#106886, fdo#105411)
      shard-kbl:          PASS -> INCOMPLETE (fdo#106886, fdo#103665)

    igt@kms_available_modes_crc@available_mode_test_crc:
      shard-apl:          PASS -> FAIL (fdo#106641)

    igt@kms_busy@extended-modeset-hang-newfb-with-reset-render-a:
      shard-snb:          NOTRUN -> DMESG-WARN (fdo#107956)

    igt@kms_color@pipe-a-ctm-max:
      shard-apl:          PASS -> FAIL (fdo#108147)

    igt@kms_cursor_crc@cursor-128x128-onscreen:
      shard-kbl:          PASS -> FAIL (fdo#103232)
      shard-apl:          PASS -> FAIL (fdo#103232)

    igt@kms_cursor_crc@cursor-64x64-suspend:
      shard-apl:          PASS -> FAIL (fdo#103191, fdo#103232)

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-wc:
      shard-apl:          PASS -> FAIL (fdo#103167) +1

    igt@kms_frontbuffer_tracking@fbc-1p-rte:
      shard-apl:          PASS -> DMESG-WARN (fdo#103558, fdo#108131)

    igt@kms_plane_multiple@atomic-pipe-c-tiling-x:
      shard-kbl:          PASS -> FAIL (fdo#103166) +1

    igt@kms_plane_multiple@atomic-pipe-c-tiling-y:
      shard-apl:          PASS -> FAIL (fdo#103166) +1

    igt@kms_setmode@basic:
      shard-apl:          PASS -> FAIL (fdo#99912)
      shard-kbl:          PASS -> FAIL (fdo#99912)

    igt@kms_vblank@pipe-c-ts-continuation-idle-hang:
      shard-apl:          PASS -> DMESG-WARN (fdo#105602, fdo#103558) +7

    
    ==== Possible fixes ====

    igt@gem_pwrite@big-gtt-fbr:
      shard-snb:          INCOMPLETE (fdo#105411) -> PASS

    igt@kms_available_modes_crc@available_mode_test_crc:
      shard-snb:          FAIL (fdo#106641) -> PASS

    igt@kms_color@pipe-a-degamma:
      shard-apl:          FAIL (fdo#108145) -> PASS

    igt@kms_cursor_crc@cursor-128x128-suspend:
      shard-apl:          FAIL (fdo#103191, fdo#103232) -> PASS
      shard-kbl:          FAIL (fdo#103191, fdo#103232) -> PASS

    igt@kms_cursor_crc@cursor-256x85-random:
      shard-apl:          FAIL (fdo#103232) -> PASS +4

    igt@kms_cursor_crc@cursor-64x21-onscreen:
      shard-kbl:          FAIL (fdo#103232) -> PASS +1

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-pwrite:
      shard-apl:          FAIL (fdo#103167) -> PASS +1
      shard-kbl:          FAIL (fdo#103167) -> PASS

    igt@kms_plane_multiple@atomic-pipe-a-tiling-y:
      shard-apl:          FAIL (fdo#103166) -> PASS +1

    igt@kms_rotation_crc@sprite-rotation-180:
      shard-snb:          FAIL (fdo#103925) -> PASS

    igt@pm_rpm@system-suspend-modeset:
      shard-kbl:          INCOMPLETE (fdo#107807, fdo#103665) -> PASS

fdo#103166 https://bugs.freedesktop.org/show_bug.cgi?id=103166
fdo#103167 https://bugs.freedesktop.org/show_bug.cgi?id=103167
fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
fdo#103232 https://bugs.freedesktop.org/show_bug.cgi?id=103232
fdo#103558 https://bugs.freedesktop.org/show_bug.cgi?id=103558
fdo#103665 https://bugs.freedesktop.org/show_bug.cgi?id=103665
fdo#103925 https://bugs.freedesktop.org/show_bug.cgi?id=103925
fdo#105411 https://bugs.freedesktop.org/show_bug.cgi?id=105411
fdo#105602 https://bugs.freedesktop.org/show_bug.cgi?id=105602
fdo#106641 https://bugs.freedesktop.org/show_bug.cgi?id=106641
fdo#106886 https://bugs.freedesktop.org/show_bug.cgi?id=106886
fdo#107807 https://bugs.freedesktop.org/show_bug.cgi?id=107807
fdo#107956 https://bugs.freedesktop.org/show_bug.cgi?id=107956
fdo#108131 https://bugs.freedesktop.org/show_bug.cgi?id=108131
fdo#108145 https://bugs.freedesktop.org/show_bug.cgi?id=108145
fdo#108147 https://bugs.freedesktop.org/show_bug.cgi?id=108147
fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912

== Participating hosts (6 -> 4) ==

Missing (2): shard-skl shard-glk

== Build changes ==

* IGT: IGT_4662 -> IGTPW_1901
* Linux: CI_DRM_4915 -> CI_DRM_4918

CI_DRM_4915: 26e7a7d954a9c28b97af8ca7813f430fd9117232 @ git://anongit.freedesktop.org/gfx-ci/linux
CI_DRM_4918: f595aba3a6e2f6972bb158eb8434b58d22d0e5f0 @ git://anongit.freedesktop.org/gfx-ci/linux
IGTPW_1901: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1901/
IGT_4662: ebf6a1dd1795e2f014ff3c47fe2eb4d5255845bd @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1901/shards.html
_______________________________________________
igt-dev mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/igt-dev