[igt-dev] [PATCH i-g-t] i915/perf_pmu: Emit a semaphore to measure

Ramalingam C ramalingam.c at intel.com
Fri Aug 21 09:27:40 UTC 2020


On 2020-08-10 at 13:44:15 +0100, Chris Wilson wrote:
> Don't assume the kernel will emit a semaphore to synchronise between two
> engine, and emit the semaphore ourselves for the basis of our
> measurements. The purpose of the test is to try and ascertain the
> accuracy of the two sampling methods, semaphore busyness uses register
> polling, whereas the engine busyness may use ktime_t of the CS events.

Looks good to me.

Reviewed-by: Ramalingam C <ramalingam.c at intel.com>

Tested on the platform too.
> 
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> Cc: Ramalingam C <ramalingam.c at intel.com>
> ---
>  tests/i915/perf_pmu.c | 94 +++++++++++++++++++++++++++++--------------
>  1 file changed, 64 insertions(+), 30 deletions(-)
> 
> diff --git a/tests/i915/perf_pmu.c b/tests/i915/perf_pmu.c
> index 13e1bd93e..ecd4afbd6 100644
> --- a/tests/i915/perf_pmu.c
> +++ b/tests/i915/perf_pmu.c
> @@ -650,6 +650,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
>  #define MI_SEMAPHORE_WAIT	MI_INSTR(0x1c, 2) /* GEN8+ */
>  #define   MI_SEMAPHORE_POLL		(1<<15)
>  #define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
> +#define   MI_SEMAPHORE_SAD_NEQ_SDD      (5 << 12)
>  
>  static void
>  sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
> @@ -751,10 +752,39 @@ sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
>  	assert_within_epsilon(val[1] - val[0], slept, tolerance);
>  }
>  
> +static uint32_t
> +create_sema(int gem_fd, struct drm_i915_gem_relocation_entry *reloc)
> +{
> +	uint32_t cs[] = {
> +		/* Reset our semaphore wait */
> +		MI_STORE_DWORD_IMM,
> +		0,
> +		0,
> +		1,
> +
> +		/* Wait until the semaphore value is set to 0 [by caller] */
> +		MI_SEMAPHORE_WAIT | MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_NEQ_SDD,
> +		1,
> +		0,
> +		0,
> +
> +		MI_BATCH_BUFFER_END
> +	};
> +	uint32_t handle = gem_create(gem_fd, 4096);
> +
> +	memset(reloc, 0, 2 * sizeof(*reloc));
> +	reloc[0].target_handle = handle;
> +	reloc[0].offset = 64 + 1 * sizeof(uint32_t);
> +	reloc[1].target_handle = handle;
> +	reloc[1].offset = 64 + 6 * sizeof(uint32_t);
> +
> +	gem_write(gem_fd, handle, 64, cs, sizeof(cs));
> +	return handle;
> +}
> +
>  static void
>  __sema_busy(int gem_fd, int pmu,
>  	    const struct intel_execution_engine2 *e,
> -	    const struct intel_execution_engine2 *signal,
>  	    int sema_pct,
>  	    int busy_pct)
>  {
> @@ -764,39 +794,54 @@ __sema_busy(int gem_fd, int pmu,
>  	};
>  	uint64_t total, sema, busy;
>  	uint64_t start[2], val[2];
> -	igt_spin_t *spin[2];
> +	struct drm_i915_gem_relocation_entry reloc[2];
> +	struct drm_i915_gem_exec_object2 obj = {
> +		.handle = create_sema(gem_fd, reloc),
> +		.relocation_count = 2,
> +		.relocs_ptr = to_user_pointer(reloc),
> +	};
> +	struct drm_i915_gem_execbuffer2 eb = {
> +		.batch_start_offset = 64,
> +		.buffer_count = 1,
> +		.buffers_ptr = to_user_pointer(&obj),
> +		.flags = e->flags,
> +	};
> +	igt_spin_t *spin;
> +	uint32_t *map;
>  
>  	/* Time spent being busy includes time waiting on semaphores */
>  	igt_assert(busy_pct >= sema_pct);
>  
>  	gem_quiescent_gpu(gem_fd);
>  
> -	spin[0] = igt_spin_new(gem_fd,
> -			       .engine = signal->flags,
> -			       .flags = IGT_SPIN_FENCE_OUT | IGT_SPIN_POLL_RUN);
> -	spin[1] = igt_spin_new(gem_fd,
> -			       .engine = e->flags,
> -			       .fence = spin[0]->out_fence,
> -			       .flags = IGT_SPIN_FENCE_IN);
> +	map = gem_mmap__wc(gem_fd, obj.handle, 0, 4096, PROT_WRITE);
> +	gem_execbuf(gem_fd, &eb);
> +	spin = igt_spin_new(gem_fd, .engine = e->flags);
>  
> -	igt_spin_busywait_until_started(spin[0]);
> +	/* Wait until the batch is executed and the semaphore is busy-waiting */
> +	while (!READ_ONCE(*map) && gem_bo_busy(gem_fd, obj.handle))
> +		;
> +	igt_assert(gem_bo_busy(gem_fd, obj.handle));
> +	gem_close(gem_fd, obj.handle);
>  
>  	total = pmu_read_multi(pmu, 2, start);
>  
>  	sema = measured_usleep(batch_duration_ns * sema_pct / 100 / 1000);
> -	igt_spin_end(spin[0]);
> +	*map = 0; __sync_synchronize();
>  	busy = measured_usleep(batch_duration_ns * (busy_pct - sema_pct) / 100 / 1000);
> -	igt_spin_end(spin[1]);
> +	igt_spin_end(spin);
>  	measured_usleep(batch_duration_ns * (100 - busy_pct) / 100 / 1000);
>  
>  	total = pmu_read_multi(pmu, 2, val) - total;
> +	igt_spin_free(gem_fd, spin);
> +	munmap(map, 4096);
>  
>  	busy += sema;
>  	val[SEMA] -= start[SEMA];
>  	val[BUSY] -= start[BUSY];
>  
> -	igt_info("%s<-%s, target: {%.1f%% [%d], %.1f%% [%d]}, measured: {%.1f%%, %.1f%%}\n",
> -		 e->name, signal->name,
> +	igt_info("%s, target: {%.1f%% [%d], %.1f%% [%d]}, measured: {%.1f%%, %.1f%%}\n",
> +		 e->name,
>  		 sema * 100. / total, sema_pct,
>  		 busy * 100. / total, busy_pct,
>  		 val[SEMA] * 100. / total,
> @@ -809,8 +854,6 @@ __sema_busy(int gem_fd, int pmu,
>  		     val[SEMA] * 1e-3, val[SEMA] * 100. / total,
>  		     val[BUSY] * 1e-3, val[BUSY] * 100. / total);
>  
> -	igt_spin_free(gem_fd, spin[1]);
> -	igt_spin_free(gem_fd, spin[0]);
>  }
>  
>  static void
> @@ -818,25 +861,16 @@ sema_busy(int gem_fd,
>  	  const struct intel_execution_engine2 *e,
>  	  unsigned int flags)
>  {
> -	const struct intel_execution_engine2 *signal;
>  	int fd;
>  
> -	igt_require(gem_scheduler_has_semaphores(gem_fd));
> -	igt_require(gem_scheduler_has_preemption(gem_fd));
> +	igt_require(intel_gen(intel_get_drm_devid(gem_fd)) >= 8);
>  
> -	fd = open_group(gem_fd,
> -			I915_PMU_ENGINE_SEMA(e->class, e->instance), -1);
> +	fd = open_group(gem_fd, I915_PMU_ENGINE_SEMA(e->class, e->instance), -1);
>  	open_group(gem_fd, I915_PMU_ENGINE_BUSY(e->class, e->instance), fd);
>  
> -	__for_each_physical_engine(gem_fd, signal) {
> -		if (e->class == signal->class &&
> -		    e->instance == signal->instance)
> -			continue;
> -
> -		__sema_busy(gem_fd, fd, e, signal, 50, 100);
> -		__sema_busy(gem_fd, fd, e, signal, 25, 50);
> -		__sema_busy(gem_fd, fd, e, signal, 75, 75);
> -	}
> +	__sema_busy(gem_fd, fd, e, 50, 100);
> +	__sema_busy(gem_fd, fd, e, 25, 50);
> +	__sema_busy(gem_fd, fd, e, 75, 75);
>  
>  	close(fd);
>  }
> -- 
> 2.28.0
> 


More information about the igt-dev mailing list