* [PATCH i-g-t v2 1/7] ioctl_wrappers: make gem_has_ring non static
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks Derek Morton
` (5 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
For tests that use multiple rings to test interactions it is
useful to know if a ring exists without triggering the test to skip.
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
lib/ioctl_wrappers.c | 2 +-
lib/ioctl_wrappers.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index 5d49729..f42e2c9 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -1396,7 +1396,7 @@ void gem_require_caching(int fd)
errno = 0;
}
-static int gem_has_ring(int fd, int ring)
+int gem_has_ring(int fd, int ring)
{
uint32_t bbe = MI_BATCH_BUFFER_END;
struct drm_i915_gem_execbuffer2 execbuf;
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index f59eafb..e095c41 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -150,6 +150,7 @@ uint64_t gem_global_aperture_size(int fd);
uint64_t gem_mappable_aperture_size(void);
bool gem_has_softpin(int fd);
+int gem_has_ring(int fd, int ring);
/* check functions which auto-skip tests by calling igt_skip() */
void gem_require_caching(int fd);
void gem_require_ring(int fd, int ring_id);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 1/7] ioctl_wrappers: make gem_has_ring non static Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 18:41 ` Chris Wilson
2016-03-07 11:56 ` Dave Gordon
2016-03-02 18:10 ` [PATCH i-g-t v2 3/7] lib/intel_batchbuffer: Add functions to be used in the scheduler test Derek Morton
` (4 subsequent siblings)
6 siblings, 2 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
Some platforms have ring BSD available but no BSD2.
Because of the current verification, tests involving ring BSD1
will be skipped if no BSD2 is available.
Decoupling the checks will allow running the BSD1 specific tests
on these platforms.
Based on a patch originally submitted by Gabriel Feceoru to
patchwork-hook-test branch.
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
lib/ioctl_wrappers.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index f42e2c9..a4c6aa4 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -1432,8 +1432,10 @@ void gem_require_ring(int fd, int ring_id)
/* silly ABI, the kernel thinks everyone who has BSD also has BSD2 */
if ((ring_id & ~(3<<13)) == I915_EXEC_BSD) {
- if (ring_id & (3 << 13))
+ if (ring_id & (2 << 13))
igt_require(gem_has_bsd2(fd));
+ if (ring_id & (1 << 13))
+ igt_require(gem_has_bsd(fd));
}
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
2016-03-02 18:10 ` [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks Derek Morton
@ 2016-03-02 18:41 ` Chris Wilson
2016-03-04 15:14 ` Morton, Derek J
2016-03-07 11:56 ` Dave Gordon
1 sibling, 1 reply; 15+ messages in thread
From: Chris Wilson @ 2016-03-02 18:41 UTC (permalink / raw)
To: Derek Morton; +Cc: daniel.vetter, intel-gfx
On Wed, Mar 02, 2016 at 06:10:40PM +0000, Derek Morton wrote:
> Some platforms have ring BSD available but no BSD2.
> Because of the current verification, tests involving ring BSD1
> will be skipped if no BSD2 is available.
The code does what exactly what we want. We run
BSD or BSD, BSD1, BSD2 (because in this case we have no idea what BSD
actually is).
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
2016-03-02 18:41 ` Chris Wilson
@ 2016-03-04 15:14 ` Morton, Derek J
0 siblings, 0 replies; 15+ messages in thread
From: Morton, Derek J @ 2016-03-04 15:14 UTC (permalink / raw)
To: Chris Wilson; +Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org
I need to control exactly which ring each batchbuffer is submitted to if there is more than 1 BSD ring as I need to fill the queues in a known manner. My understanding is that if I submit to BSD when there is BSD1 and BSD2 the kernel will choose which ring it gets submitted to.
If this logic breaks other tests I will remove this patch and put the logic in the scheduler test.
//Derek
-----Original Message-----
From: Chris Wilson [mailto:chris@chris-wilson.co.uk]
Sent: Wednesday, March 2, 2016 6:42 PM
To: Morton, Derek J <derek.j.morton@intel.com>
Cc: intel-gfx@lists.freedesktop.org; daniel.vetter@ffwll.ch
Subject: Re: [Intel-gfx] [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
On Wed, Mar 02, 2016 at 06:10:40PM +0000, Derek Morton wrote:
> Some platforms have ring BSD available but no BSD2.
> Because of the current verification, tests involving ring BSD1 will be
> skipped if no BSD2 is available.
The code does what exactly what we want. We run BSD or BSD, BSD1, BSD2 (because in this case we have no idea what BSD actually is).
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
2016-03-02 18:10 ` [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks Derek Morton
2016-03-02 18:41 ` Chris Wilson
@ 2016-03-07 11:56 ` Dave Gordon
2016-03-07 12:34 ` Dave Gordon
1 sibling, 1 reply; 15+ messages in thread
From: Dave Gordon @ 2016-03-07 11:56 UTC (permalink / raw)
To: Derek Morton, intel-gfx
On 02/03/16 18:10, Derek Morton wrote:
> Some platforms have ring BSD available but no BSD2.
> Because of the current verification, tests involving ring BSD1
> will be skipped if no BSD2 is available.
>
> Decoupling the checks will allow running the BSD1 specific tests
> on these platforms.
>
> Based on a patch originally submitted by Gabriel Feceoru to
> patchwork-hook-test branch.
>
> Signed-off-by: Derek Morton <derek.j.morton@intel.com>
> ---
> lib/ioctl_wrappers.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
> index f42e2c9..a4c6aa4 100644
> --- a/lib/ioctl_wrappers.c
> +++ b/lib/ioctl_wrappers.c
> @@ -1432,8 +1432,10 @@ void gem_require_ring(int fd, int ring_id)
>
> /* silly ABI, the kernel thinks everyone who has BSD also has BSD2 */
> if ((ring_id & ~(3<<13)) == I915_EXEC_BSD) {
> - if (ring_id & (3 << 13))
> + if (ring_id & (2 << 13))
> igt_require(gem_has_bsd2(fd));
> + if (ring_id & (1 << 13))
> + igt_require(gem_has_bsd(fd));
> }
> }
>
Isn't the first (unchanged) line rather unclear?
Why not test for (ring_id & I915_EXEC_BSD)?
And then you only need to additionally test bit 14.
if (ring_id & I915_EXEC_BSD) {
/* require at least one BSD ring */
igt_require(gem_has_bsd(fd));
if (ring_id & (2 << 13)) {
/* specifically require BSD2 */
igt_require(gem_has_bsd2(fd));
}
}
.Dave.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks
2016-03-07 11:56 ` Dave Gordon
@ 2016-03-07 12:34 ` Dave Gordon
0 siblings, 0 replies; 15+ messages in thread
From: Dave Gordon @ 2016-03-07 12:34 UTC (permalink / raw)
To: Derek Morton, intel-gfx
On 07/03/16 11:56, Dave Gordon wrote:
> On 02/03/16 18:10, Derek Morton wrote:
>> Some platforms have ring BSD available but no BSD2.
>> Because of the current verification, tests involving ring BSD1
>> will be skipped if no BSD2 is available.
>>
>> Decoupling the checks will allow running the BSD1 specific tests
>> on these platforms.
>>
>> Based on a patch originally submitted by Gabriel Feceoru to
>> patchwork-hook-test branch.
>>
>> Signed-off-by: Derek Morton <derek.j.morton@intel.com>
>> ---
>> lib/ioctl_wrappers.c | 4 +++-
>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
>> index f42e2c9..a4c6aa4 100644
>> --- a/lib/ioctl_wrappers.c
>> +++ b/lib/ioctl_wrappers.c
>> @@ -1432,8 +1432,10 @@ void gem_require_ring(int fd, int ring_id)
>>
>> /* silly ABI, the kernel thinks everyone who has BSD also has
>> BSD2 */
>> if ((ring_id & ~(3<<13)) == I915_EXEC_BSD) {
>> - if (ring_id & (3 << 13))
>> + if (ring_id & (2 << 13))
>> igt_require(gem_has_bsd2(fd));
>> + if (ring_id & (1 << 13))
>> + igt_require(gem_has_bsd(fd));
>> }
>> }
>>
>
> Isn't the first (unchanged) line rather unclear?
> Why not test for (ring_id & I915_EXEC_BSD)?
> And then you only need to additionally test bit 14.
>
> if (ring_id & I915_EXEC_BSD) {
Oops, no, this should be:
if ((ring_id & I915_EXEC_RING_MASK) == I915_EXEC_BSD) {
> /* require at least one BSD ring */
> igt_require(gem_has_bsd(fd));
>
> if (ring_id & (2 << 13)) {
Or better (and symbolically):
if ((ring_id & I915_EXEC_BSD_MASK) == I915_EXEC_BSD_RING2) {
> /* specifically require BSD2 */
> igt_require(gem_has_bsd2(fd));
> }
> }
>
> .Dave.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH i-g-t v2 3/7] lib/intel_batchbuffer: Add functions to be used in the scheduler test
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 1/7] ioctl_wrappers: make gem_has_ring non static Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 2/7] lib/ioctl_wrappers: Separate ring BSD1 from BSD2 checks Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test Derek Morton
` (3 subsequent siblings)
6 siblings, 0 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
Adds functions to create a number of different batch buffers to perform
several functions including:
Batch buffer which will run for a long duration to provide a delay on a
specified ring.
Function to calibrate the delay batch buffer to run for a specified period
of time.
Function to create a batch buffer which writes timestamps to a buffer object.
Function to compare timestamps allowing for wrapping of the values.
v2: Moved code to intel_batchbuffer (Daniel Vetter)
Addressed review comments from Daniele Ceraolo Spurio
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
lib/intel_batchbuffer.c | 384 +++++++++++++++++++++++++++++++++++++++++++++++-
lib/intel_batchbuffer.h | 14 ++
2 files changed, 393 insertions(+), 5 deletions(-)
diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c
index 692521f..30e78c5 100644
--- a/lib/intel_batchbuffer.c
+++ b/lib/intel_batchbuffer.c
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,7 +22,7 @@
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
#include <inttypes.h>
@@ -30,6 +30,8 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <stdint.h>
+#include <time.h>
#include "drm.h"
#include "drmtest.h"
@@ -42,6 +44,7 @@
#include "ioctl_wrappers.h"
#include "media_spin.h"
#include "gpgpu_fill.h"
+#include "igt_gt.h"
#include <i915_drm.h>
@@ -817,3 +820,374 @@ igt_media_spinfunc_t igt_get_media_spinfunc(int devid)
return spin;
}
+
+#define SEC_TO_NSEC (1000 * 1000 * 1000)
+#define DWORDS_TO_BYTES(x) ((x)*4)
+
+#define MI_STORE_REGISTER_MEM(LENGTH) ((0x024 << 23) | ((LENGTH - 2) & 0xff))
+#define MI_MATH(NrInst) ((0x01A << 23) | ((NrInst - 1) & 0x3f))
+#define MI_CONDITIONAL_BATCH_BUFFER_END ((0x036 << 23) | (1 << 21) | 2)
+#define MI_COPY_MEM_MEM ((0x02E << 23) | (3))
+
+#define ALU_LOAD(TO, FROM) ((0x080 << 20) | ((TO) << 10) | (FROM))
+#define ALU_SUB ( 0x101 << 20)
+#define ALU_STORE(TO, FROM) ((0x180 << 20) | ((TO) << 10) | (FROM))
+
+#define TIMESTAMP_offset (0x358) /* Elapsed time from system start */
+#define CTX_TIMESTAMP_offset (0x3A8) /* Elapsed Time from context creation */
+#define ALU_GPU_R0_LSB_offset (0x600)
+#define ALU_GPU_R0_MSB_offset (0x604)
+#define ALU_GPU_R1_LSB_offset (0x608)
+#define ALU_GPU_R1_MSB_offset (0x60C)
+#define ALU_GPU_R2_LSB_offset (0x610)
+#define ALU_GPU_R2_MSB_offset (0x614)
+
+#define ALU_R0_ENCODING (0x00)
+#define ALU_R1_ENCODING (0x01)
+#define ALU_SRCA_ENCODING (0x20)
+#define ALU_SRCB_ENCODING (0x21)
+#define ALU_ACCU_ENCODING (0x31)
+
+static int bb_address_size_dw(int fd)
+{
+ if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ return 2;
+ else
+ return 1;
+}
+
+static uint32_t get_mmio_base(int ringid)
+{
+ switch (ringid) {
+ case I915_EXEC_RENDER:
+ return 0x02000;
+ case I915_EXEC_BSD:
+ case I915_EXEC_BSD | 1<<13: /* BSD1 */
+ return 0x12000;
+ case I915_EXEC_BSD | 2<<13: /* BSD2 */
+ return 0x1c000;
+ case I915_EXEC_BLT:
+ return 0x22000;
+ case I915_EXEC_VEBOX:
+ return 0x1A000;
+ default:
+ igt_assert_f(0, "Invalid ringid %d passed to get_mmio_base()\n", ringid);
+ }
+}
+
+/**
+ * igt_batch_used
+ * @batch batchbuffer to get offset from
+ *
+ * This returns the number of bytes of the batchbuffer that have been used.
+ * e.g. The offset into the batchbuffer that the next OUT_BATCH would write to.
+ *
+ * Returns:
+ * The number of bytes of the batchbuffer that have been used.
+ */
+uint32_t igt_batch_used(struct intel_batchbuffer *batch)
+{
+ return batch->ptr - batch->buffer;
+}
+
+/**
+ * igt_create_delay_bb:
+ * @fd: file descriptor for i915 driver instance
+ * @batch: Batch buffer to write to
+ * ringid: Ring to create batch buffer for. e.g. I915_EXEC_RENDER
+ * loops: Number of times to loop
+ * dest: Buffer to use for saving the current loop count and timestamp.
+ *
+ * This creates a batch buffer which will iterate a loop a specified number
+ * of times. Intended for creating batch buffers which take an arbitarily
+ * long time to execute. This can be useful to keep a ring busy while
+ * constructing a test scenario.
+ *
+ * The dest buffer will have a number of Dwords written by the batch buffer
+ * when it runs. They are:
+ * DW0 & DW1 - These are loaded with the value of 'loops' and are decremented
+ * as the batch buffer executes. They will be 0 after the batch
+ * buffer completes if it finished succesfully.
+ * DW2 Timestamp - An indication of when the batch buffer ran allowing a
+ * comparison between batch buffers to show execution order.
+ * May wrap so igt_compare_timestamps() should be used to
+ * compare timestamps.
+ * The timestamp will wrap every few minutes.
+ *
+ */
+void igt_create_delay_bb(int fd, struct intel_batchbuffer *batch,
+ int ringid, uint32_t loops, drm_intel_bo *dest)
+{
+ int addr_size_dw;
+ uint32_t mmio_base, jump_offset;
+
+ /* CMD parser blocks reading TIMESTAMP register on gen 7.5 */
+ igt_require(intel_gen(intel_get_drm_devid(fd)) >= 8);
+
+ addr_size_dw = bb_address_size_dw(fd);
+ mmio_base = get_mmio_base(ringid);
+ igt_assert(batch);
+ BEGIN_BATCH(32, 5);
+
+ /* store current timestamp in DW2 */
+ OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
+ OUT_BATCH(mmio_base + TIMESTAMP_offset);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(2));
+
+ /* Load R0 with loops */
+ OUT_BATCH(MI_LOAD_REGISTER_IMM);
+ OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
+ OUT_BATCH(loops);
+ OUT_BATCH(MI_LOAD_REGISTER_IMM);
+ OUT_BATCH(mmio_base + ALU_GPU_R0_MSB_offset);
+ OUT_BATCH(0x00000000);
+ /* Load R1 with 1 */
+ OUT_BATCH(MI_LOAD_REGISTER_IMM);
+ OUT_BATCH(mmio_base + ALU_GPU_R1_LSB_offset);
+ OUT_BATCH(0x00000001);
+ OUT_BATCH(MI_LOAD_REGISTER_IMM);
+ OUT_BATCH(mmio_base + ALU_GPU_R1_MSB_offset);
+ OUT_BATCH(0x00000000);
+ /* Copy R0 / R1 into SRCA / SRCB, Perform R0 - R1, Store result in R0 */
+ /* e.g. R0 -= 1 */
+ jump_offset=igt_batch_used(batch);
+ OUT_BATCH(MI_MATH(4));
+ OUT_BATCH(ALU_LOAD(ALU_SRCA_ENCODING, ALU_R0_ENCODING));
+ OUT_BATCH(ALU_LOAD(ALU_SRCB_ENCODING, ALU_R1_ENCODING));
+ OUT_BATCH(ALU_SUB);
+ OUT_BATCH(ALU_STORE(ALU_R0_ENCODING, ALU_ACCU_ENCODING));
+ /* Copy R0 to dest
+ * On Gen8 MI_CONDITIONAL_BATCH_BUFFER_END BSD ring Compare address
+ * points to 2 Dwords, a mask (DW0) and data (DW1) which are ANDed
+ * together.
+ * On Gen9+, and the other rings on Gen8 Compare address points to
+ * just Data (DW0). For simplicity always copy R0 LSB to DW0 and DW1.
+ */
+ OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
+ OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
+ OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
+ OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(1));
+ /* Repeat until R0 == 0 */
+ OUT_BATCH(MI_CONDITIONAL_BATCH_BUFFER_END);
+ OUT_BATCH(0x00000000);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
+ OUT_BATCH(MI_BATCH_BUFFER_START | (addr_size_dw - 1));
+ OUT_RELOC(batch->bo, I915_GEM_DOMAIN_INSTRUCTION, 0, jump_offset);
+
+ /* Should never get here, but end if it happens */
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ ADVANCE_BATCH();
+}
+
+/**
+ * igt_create_timestamp_bb:
+ * @fd: file descriptor for i915 driver instance
+ * @batch: Batch buffer to write to
+ * ringid: Ring to create batch buffer for. e.g. I915_EXEC_RENDER
+ * dest: Buffer to use for saving the timestamps.
+ * load: Buffer to access. Set NULL if not required.
+ * write: If true and load is not NULL, will also write a timestamp to load
+ * buffer. If false and load is not NULL, will read from load buffer into dest.
+ * Intended for dependency checking.
+ *
+ * This creates a batch buffer which writes timestamps into a buffer object.
+ * If 'load' is non null, data is either written to 'load' or copied from 'load'
+ * depending on whether 'write' is set.
+ *
+ * The dest buffer will have a number of Dwords written by the batch buffer
+ * when it runs. They are:
+ * DW0 Reported timestamp - An indication of when the batch buffer ran allowing a
+ * comparison between batch buffers to show execution order.
+ * May wrap so igt_compare_timestamps() should be used to
+ * compare timestamps.
+ * The timestamp will wrap every few minutes.
+ * DW2 Value copied from DW0 of load if write == false
+ *
+ */
+void igt_create_timestamp_bb(int fd, struct intel_batchbuffer *batch, int ringid,
+ drm_intel_bo *dest, drm_intel_bo *load, bool write)
+{
+ int addr_size_dw;
+ uint32_t mmio_base;
+
+ /* CMD parser blocks reading TIMESTAMP register on gen 7.5 */
+ igt_require(intel_gen(intel_get_drm_devid(fd)) >= 8);
+
+ addr_size_dw = bb_address_size_dw(fd);
+ mmio_base = get_mmio_base(ringid);
+ igt_assert(batch);
+
+ BEGIN_BATCH(3, 1);
+ /* store current reported timestamp in DW0 */
+ OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
+ OUT_BATCH(mmio_base + TIMESTAMP_offset);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(0));
+
+ ADVANCE_BATCH();
+
+ if(load != NULL) {
+ if(write) {
+ BEGIN_BATCH(3, 1);
+ OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
+ OUT_BATCH(mmio_base + TIMESTAMP_offset);
+ OUT_RELOC(load, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(0));
+ ADVANCE_BATCH();
+ }
+ else {
+ BEGIN_BATCH(3, 2);
+ OUT_BATCH(MI_COPY_MEM_MEM);
+ OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(2));
+ OUT_RELOC(load, I915_GEM_DOMAIN_INSTRUCTION, 0, DWORDS_TO_BYTES(0));
+ ADVANCE_BATCH();
+ }
+ }
+
+ BEGIN_BATCH(1, 0);
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ ADVANCE_BATCH();
+}
+
+/**
+ * igt_create_noop_bb:
+ * @batch: Batch buffer to write to
+ * noops: Number of MI_NOOP instructions to add to the batch buffer.
+ *
+ * This creates a batch buffer with a specified number of MI_NOOP instructions.
+ */
+void igt_create_noop_bb(struct intel_batchbuffer *batch, int noops)
+{
+ int loop;
+
+ igt_assert(batch);
+
+ BEGIN_BATCH(noops + 1, 0);
+ for(loop = 0; loop < noops; loop++)
+ OUT_BATCH(MI_NOOP);
+ OUT_BATCH(MI_BATCH_BUFFER_END);
+ ADVANCE_BATCH();
+
+}
+
+/* Store calibrated values so they only need calculating once.
+ * Use intel_execution_engines array as list of supported rings
+ */
+static uint32_t *calibrated_ring_value = NULL;
+
+/**
+ * igt_calibrate_delay_bb:
+ * @fd: file descriptor for i915 driver instance
+ * @bufmgr: Buffer manager to be used for creation of batch buffers
+ * ringid: Ring to calibrate. e.g. I915_EXEC_RENDER
+ *
+ * This calculates the value of loops that would need to be passed to
+ * igt_create_delay_bb() to create a delay of about 1 second on the specified
+ * ring.
+ *
+ * Returns:
+ * uint32_t to be passed to igt_create_delay_bb().
+ */
+/* 0x100000 will run for about 0.6 - 0.8 seconds (dependant on ring) on BXT HW */
+#define CAL_SEED (0x100000)
+uint32_t igt_calibrate_delay_bb(int fd, drm_intel_bufmgr *bufmgr, int ringid)
+{
+ uint32_t buf[2];
+ struct intel_batchbuffer *bb;
+ struct timespec start, end;
+ uint64_t duration;
+ uint64_t calibrated;
+ drm_intel_bo *target_bo;
+ int ring_index=0;
+
+/* igt_assert(ringid < 8);
+ if(calibrated_ring_value[ringid] != 0)
+ return calibrated_ring_value[ringid];*/
+
+ if(calibrated_ring_value == NULL) {
+ int count;
+ for(count = 0; intel_execution_engines[count].name != NULL; count++) {}
+ calibrated_ring_value = calloc(count, sizeof(uint32_t));
+ igt_assert(calibrated_ring_value);
+ }
+
+ /* Check if there is already a calibration value for this ring */
+ while(intel_execution_engines[ring_index].name != NULL) {
+ if((intel_execution_engines[ring_index].exec_id |
+ intel_execution_engines[ring_index].flags) == ringid) {
+ if(calibrated_ring_value[ring_index] != 0) {
+ return calibrated_ring_value[ring_index];
+ }
+ break;
+ }
+ ring_index++;
+ }
+
+ target_bo = drm_intel_bo_alloc(bufmgr, "target bo", BATCH_SZ, BATCH_SZ);
+ igt_assert(target_bo);
+
+ /* Put some non zero values in the target bo */
+ {
+ uint32_t data=0xffffffff;
+ drm_intel_bo_subdata(target_bo, 0, 4, &data);
+ }
+
+ bb = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ igt_assert(bb);
+ igt_create_delay_bb(fd, bb, ringid, CAL_SEED, target_bo);
+
+ gem_quiescent_gpu(fd);
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ intel_batchbuffer_flush_on_ring(bb, ringid);
+ /* This will not return until the bo has finished executing */
+ drm_intel_bo_wait_rendering(target_bo);
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ drm_intel_bo_get_subdata(target_bo, 0, 4, (void*)buf);
+
+ /* buf[0] in the target buffer should be 0 if the batch buffer completed */
+ igt_assert_f(buf[0] == 0, "buf[0] expected 0x0, got 0x%x\n", buf[0]);
+
+ duration = ((((uint64_t)end.tv_sec - (uint64_t)start.tv_sec) * SEC_TO_NSEC)
+ + (uint64_t)end.tv_nsec) - (uint64_t)start.tv_nsec;
+
+ calibrated = (((uint64_t)(CAL_SEED) * SEC_TO_NSEC) / duration);
+ igt_debug("Uncalibrated run took %" PRIu64 ".%04" PRIu64 "s\n",
+ duration / SEC_TO_NSEC,
+ (duration % SEC_TO_NSEC) / 100000);
+ drm_intel_bo_unreference(target_bo);
+ intel_batchbuffer_free(bb);
+
+ /* Sanity check. If duration < 100ms, something has clearly gone wrong */
+ igt_assert(duration > (SEC_TO_NSEC / 10));
+
+ igt_assert_f(calibrated <= UINT32_MAX, "Calibrated value > UINT32_MAX\n");
+
+ if(intel_execution_engines[ring_index].name != NULL)
+ calibrated_ring_value[ring_index] = (uint32_t)calibrated;
+ return (uint32_t)calibrated;
+}
+
+/**
+ * igt_compare_timestamps:
+ * @ts1: timestamp 1
+ * @ts2: timestamp 2
+ *
+ * This compares two uint32_t timestamps. To handle wrapping it assumes the
+ * difference between the two timestamps is less than 1/4 the max elapsed time
+ * represented by the counters.
+ * It also assumes the timestamps are samples from the same counter.
+ *
+ * Returns:
+ * True if ts2 > ts1, allowing for counter wrapping, false otherwise.
+ */
+
+bool igt_compare_timestamps(uint32_t ts1, uint32_t ts2)
+{
+ if (ts2 > ts1)
+ return true;
+ else if ((ts1 > 0x80000000) && (ts2 < 0x40000000))
+ return true; /* Assuming timestamp counter wrapped */
+ else
+ return false;
+}
diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h
index 869747d..5b66fa3 100644
--- a/lib/intel_batchbuffer.h
+++ b/lib/intel_batchbuffer.h
@@ -323,4 +323,18 @@ typedef void (*igt_media_spinfunc_t)(struct intel_batchbuffer *batch,
igt_media_spinfunc_t igt_get_media_spinfunc(int devid);
+uint32_t igt_batch_used(struct intel_batchbuffer *batch);
+
+void igt_create_delay_bb(int fd, struct intel_batchbuffer *batch,
+ int ringid, uint32_t loops, drm_intel_bo *dest);
+
+void igt_create_timestamp_bb(int fd, struct intel_batchbuffer *batch, int ringid,
+ drm_intel_bo *dest, drm_intel_bo *load, bool write);
+
+void igt_create_noop_bb(struct intel_batchbuffer *batch, int noops);
+
+uint32_t igt_calibrate_delay_bb(int fd, drm_intel_bufmgr *bufmgr, int ringid);
+
+bool igt_compare_timestamps(uint32_t ts1, uint32_t ts2);
+
#endif
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
` (2 preceding siblings ...)
2016-03-02 18:10 ` [PATCH i-g-t v2 3/7] lib/intel_batchbuffer: Add functions to be used in the scheduler test Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 20:15 ` Chris Wilson
2016-03-02 18:10 ` [PATCH i-g-t v2 5/7] igt/gem_ctx_param_basic: Updated to support scheduler priority interface Derek Morton
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
This is intended to test the scheduler behaviour is correct.
The subtests are
<ring>-basic
Tests that batch buffers of the same priority submitted to a ring
execute in the order they are submitted.
<ring>-read
Submits a batch buffer with a read dependency to a buffer object to
a ring which is held in the scheduler queue by a long running batch
buffer. Submit batch buffers to other rings that have a read dependency
to the same buffer object. Ensure they execute before the batch buffer
being held up behind the long running batch buffer.
<ring>-write
Submits a batch buffer with a write dependency to a buffer object to
a ring which is held in the scheduler queue by a long running batch
buffer. Submit batch buffers to other rings that have a write dependency
to the same buffer object. Submit batch buffers with no interdependencies
to all rings. Ensure the batch buffers that have write dependencies are
executed in submission order but the batch buffers without interdependencies
do not get held up.
v2: Addressed review comments from Daniele Ceraolo Spurio
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
tests/Makefile.sources | 1 +
tests/gem_scheduler.c | 451 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 452 insertions(+)
create mode 100644 tests/gem_scheduler.c
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index f8b18b0..c88e045 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -66,6 +66,7 @@ TESTS_progs_M = \
gem_request_retire \
gem_reset_stats \
gem_ringfill \
+ gem_scheduler \
gem_set_tiling_vs_blt \
gem_softpin \
gem_stolen \
diff --git a/tests/gem_scheduler.c b/tests/gem_scheduler.c
new file mode 100644
index 0000000..762b69f
--- /dev/null
+++ b/tests/gem_scheduler.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Derek Morton <derek.j.morton@intel.com>
+ *
+ */
+
+#include "igt.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+IGT_TEST_DESCRIPTION("Check scheduler behaviour. Basic tests ensure independant "
+ "batch buffers of the same priority are executed in "
+ "submission order. Read-read tests ensure "
+ "batch buffers with a read dependency to the same buffer "
+ "object do not block each other. Write-write dependency "
+ "tests ensure batch buffers with a write dependency to a "
+ "buffer object will be executed in submission order but "
+ "will not block execution of other independant batch "
+ "buffers.");
+
+#define SEC_TO_NSEC (1000 * 1000 * 1000)
+
+static struct ring {
+ const char *name;
+ int id;
+ bool exists;
+} rings[] = {
+ { "render", I915_EXEC_RENDER, false },
+ { "bsd1", I915_EXEC_BSD | 1<<13, false },
+ { "bsd2", I915_EXEC_BSD | 2<<13, false },
+ { "blt", I915_EXEC_BLT, false },
+ { "vebox", I915_EXEC_VEBOX, false },
+};
+
+#define NBR_RINGS (sizeof(rings)/sizeof(struct ring))
+
+static void check_rings(int fd) {
+ int loop;
+ for(loop=0; loop < NBR_RINGS; loop++) {
+ if(gem_has_ring(fd, rings[loop].id)) {
+ if(rings[loop].id == (I915_EXEC_BSD | 2<<13))
+ rings[loop].exists = gem_has_bsd2(fd);
+ else
+ rings[loop].exists = true;
+ }
+ }
+}
+
+static drm_intel_bo *create_and_check_bo(drm_intel_bufmgr *bufmgr, const char *desc)
+{
+ drm_intel_bo *bo = drm_intel_bo_alloc(bufmgr, desc, BATCH_SZ, BATCH_SZ);
+ igt_assert_f(bo, "Failed allocating %s\n", desc);
+ return bo;
+}
+
+static struct intel_batchbuffer *create_delay_bb(int fd, drm_intel_bufmgr *bufmgr,
+ int ringid, uint32_t loops,
+ drm_intel_bo *dest)
+{
+ struct intel_batchbuffer *buffer;
+ buffer = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ igt_assert(buffer);
+ igt_create_delay_bb(fd, buffer, ringid, loops, dest);
+ return buffer;
+}
+
+static struct intel_batchbuffer *create_timestamp_bb(int fd, drm_intel_bufmgr *bufmgr,
+ int ringid, drm_intel_bo *dest,
+ drm_intel_bo *load, bool write)
+{
+ struct intel_batchbuffer *buffer;
+ buffer = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ igt_assert(buffer);
+ igt_create_timestamp_bb(fd, buffer, ringid, dest, load, write);
+ return buffer;
+}
+
+static struct intel_batchbuffer *create_noop_bb(int fd, drm_intel_bufmgr *bufmgr,
+ int noops)
+{
+ struct intel_batchbuffer *buffer;
+ buffer = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
+ igt_assert(buffer);
+ igt_create_noop_bb(buffer, noops);
+ return buffer;
+}
+
+static void init_context(int *fd, drm_intel_bufmgr **bufmgr, int ringid)
+{
+ struct intel_batchbuffer *noop_bb;
+ *fd = drm_open_driver(DRIVER_INTEL);
+ igt_assert(*fd >= 0);
+ *bufmgr = drm_intel_bufmgr_gem_init(*fd, BATCH_SZ);
+ igt_assert(*bufmgr);
+ drm_intel_bufmgr_gem_enable_reuse(*bufmgr);
+ /* Send a noop batch buffer to force any deferred initialisation */
+ noop_bb = create_noop_bb(*fd, *bufmgr, 5);
+ intel_batchbuffer_flush_on_ring(noop_bb, ringid);
+ intel_batchbuffer_free(noop_bb);
+}
+
+/* Basic test. Check batch buffers of the same priority and with no dependencies
+ * are executed in the order they are submitted.
+ */
+#define NBR_BASIC_FDs (3)
+static void run_test_basic(int in_flight, int ringid)
+{
+ int fd[NBR_BASIC_FDs];
+ int loop;
+ drm_intel_bufmgr *bufmgr[NBR_BASIC_FDs];
+ uint32_t *delay_buf, *ts1_buf, *ts2_buf;
+ struct intel_batchbuffer *ts1_bb, *ts2_bb;
+ struct intel_batchbuffer **in_flight_bbs;
+ uint32_t calibrated_1s;
+ drm_intel_bo *delay_bo, *ts1_bo, *ts2_bo;
+
+ in_flight_bbs = malloc(in_flight * sizeof(struct intel_batchbuffer *));
+ igt_assert(in_flight_bbs);
+
+ /* Need multiple i915 fd's. Scheduler will not change execution order of
+ * batch buffers from the same context.
+ */
+ for(loop=0; loop < NBR_BASIC_FDs; loop++)
+ init_context(&(fd[loop]), &(bufmgr[loop]), ringid);
+
+
+ /* Create buffer objects */
+ delay_bo = create_and_check_bo(bufmgr[0], "delay bo");
+ ts1_bo = create_and_check_bo(bufmgr[1], "ts1 bo");
+ ts2_bo = create_and_check_bo(bufmgr[2], "ts2 bo");
+
+ /* Put some non zero values in the delay bo */
+ {
+ uint32_t data=0xffffffff;
+ drm_intel_bo_subdata(delay_bo, 0, 4, &data);
+ }
+
+ calibrated_1s = igt_calibrate_delay_bb(fd[0], bufmgr[0], ringid);
+
+ /* Batch buffers to fill the in flight queue */
+ in_flight_bbs[0] = create_delay_bb(fd[0], bufmgr[0], ringid, calibrated_1s, delay_bo);
+ for(loop = 1; loop < in_flight; loop++)
+ in_flight_bbs[loop] = create_noop_bb(fd[0], bufmgr[0], 5);
+
+ /* Extra batch buffers in the scheduler queue */
+ ts1_bb = create_timestamp_bb(fd[1], bufmgr[1], ringid, ts1_bo, NULL, false);
+ ts2_bb = create_timestamp_bb(fd[2], bufmgr[2], ringid, ts2_bo, NULL, false);
+
+ /* Flush batchbuffers */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_flush_on_ring(in_flight_bbs[loop], ringid);
+ intel_batchbuffer_flush_on_ring(ts1_bb, ringid);
+ intel_batchbuffer_flush_on_ring(ts2_bb, ringid);
+
+ /* This will not return until the bo has finished executing */
+ drm_intel_bo_map(delay_bo, 0);
+ drm_intel_bo_map(ts1_bo, 0);
+ drm_intel_bo_map(ts2_bo, 0);
+
+ delay_buf = delay_bo->virtual;
+ ts1_buf = ts1_bo->virtual;
+ ts2_buf = ts2_bo->virtual;
+
+ igt_debug("Delay Timestamp = 0x%08" PRIx32 "\n", delay_buf[2]);
+ igt_debug("TS1 Timestamp = 0x%08" PRIx32 "\n", ts1_buf[0]);
+ igt_debug("TS2 Timestamp = 0x%08" PRIx32 "\n", ts2_buf[0]);
+
+ /* buf[0] in the target buffer should be 0 if the batch buffer completed */
+ igt_assert_f(delay_buf[0] == 0,
+ "delay_buf[0] expected 0x0, got 0x%" PRIx32 "\n", delay_buf[0]);
+
+ igt_assert_f(igt_compare_timestamps(delay_buf[2], ts1_buf[0]),
+ "Delay ts (0x%08" PRIx32 ") > TS1 ts (0x%08" PRIx32 ")\n",
+ delay_buf[2], ts1_buf[0]);
+ igt_assert_f(igt_compare_timestamps(ts1_buf[0], ts2_buf[0]),
+ "TS1 ts (0x%08" PRIx32 ") > TS2 ts (0x%08" PRIx32 ")\n",
+ ts1_buf[0], ts2_buf[0]);
+
+ /* Cleanup */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_free(in_flight_bbs[loop]);
+ intel_batchbuffer_free(ts1_bb);
+ intel_batchbuffer_free(ts2_bb);
+
+ drm_intel_bo_unreference(delay_bo);
+ drm_intel_bo_unreference(ts1_bo);
+ drm_intel_bo_unreference(ts2_bo);
+ for(loop = 0; loop < NBR_BASIC_FDs; loop++) {
+ drm_intel_bufmgr_destroy(bufmgr[loop]);
+ close(fd[loop]);
+ }
+ free(in_flight_bbs);
+}
+
+/* Dependency test.
+ * write=0, Submit batch buffers with read dependencies to all rings. Delay one
+ * with a long executing batch buffer. Check the others are not held up.
+ * write=1, Submit batch buffers with write dependencies to all rings. Delay one
+ * with a long executing batch buffer. Also submit batch buffers with no
+ * dependencies to all rings. Batch buffers with write dependencies should be
+ * executed in submission order. The batch buffers with no dependencies should
+ * not be held up.
+ */
+static void run_test_dependency(int in_flight, int ring, bool write)
+{
+ int fd[NBR_RINGS], fd2[NBR_RINGS];
+ int loop;
+ int prime_fd;
+ uint32_t *delay_buf, *ts_buf[NBR_RINGS], *ts2_buf[NBR_RINGS], *shared_buf;
+ uint32_t calibrated_1s;
+ drm_intel_bufmgr *bufmgr[NBR_RINGS], *bufmgr2[NBR_RINGS];
+ struct intel_batchbuffer *ts_bb[NBR_RINGS], *ts2_bb[NBR_RINGS], **in_flight_bbs;
+ drm_intel_bo *delay_bo, *ts_bo[NBR_RINGS], *ts2_bo[NBR_RINGS], *shared_bo[NBR_RINGS];
+
+ in_flight_bbs = malloc(in_flight * sizeof(struct intel_batchbuffer *));
+ igt_assert(in_flight_bbs);
+
+ /* Need multiple i915 fd's. Scheduler will not change execution order of
+ * batch buffers from the same context.
+ */
+ for(loop=0; loop < NBR_RINGS; loop++) {
+ init_context(&(fd[loop]), &(bufmgr[loop]), rings[loop].id);
+ if(write)
+ init_context(&(fd2[loop]), &(bufmgr2[loop]), rings[loop].id);
+ }
+
+ /* Create buffer objects */
+ delay_bo = create_and_check_bo(bufmgr[ring], "delay bo");
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ ts_bo[loop] = create_and_check_bo(bufmgr[loop], "ts bo");
+ if(write)
+ ts2_bo[loop] = create_and_check_bo(bufmgr2[loop], "ts2 bo");
+ }
+
+ /* Create shared buffer object */
+ shared_bo[0] = create_and_check_bo(bufmgr[0], "shared bo");
+
+ drm_intel_bo_gem_export_to_prime(shared_bo[0], &prime_fd);
+ for(loop = 1; loop < NBR_RINGS; loop++) {
+ shared_bo[loop] = drm_intel_bo_gem_create_from_prime(bufmgr[loop],
+ prime_fd, BATCH_SZ);
+ igt_assert(shared_bo[loop]);
+ }
+ close(prime_fd);
+
+ /* Put some non zero values in the delay and shared bo */
+ drm_intel_bo_map(delay_bo, 1);
+ delay_buf = delay_bo->virtual;
+ delay_buf[0] = 0xff;
+ drm_intel_bo_unmap(delay_bo);
+ drm_intel_bo_map(shared_bo[0], 1);
+ shared_buf = shared_bo[0]->virtual;
+ shared_buf[0] = 0xff00ff00;
+ drm_intel_bo_unmap(shared_bo[0]);
+
+ calibrated_1s = igt_calibrate_delay_bb(fd[ring], bufmgr[ring], rings[ring].id);
+
+ /* Batch buffers to fill the in flight queue */
+ in_flight_bbs[0] = create_delay_bb(fd[ring], bufmgr[ring], rings[ring].id,
+ calibrated_1s, delay_bo);
+ for(loop = 1; loop < in_flight; loop++)
+ in_flight_bbs[loop] = create_noop_bb(fd[ring], bufmgr[ring], 5);
+
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ ts_bb[loop] = create_timestamp_bb(fd[loop], bufmgr[loop],
+ rings[loop].id, ts_bo[loop],
+ shared_bo[loop], write);
+ if(write)
+ ts2_bb[loop] = create_timestamp_bb(fd2[loop], bufmgr2[loop],
+ rings[loop].id, ts2_bo[loop],
+ NULL, false);
+ }
+
+ /* Flush batchbuffers */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_flush_on_ring(in_flight_bbs[loop], rings[ring].id);
+
+ intel_batchbuffer_flush_on_ring(ts_bb[ring], rings[ring].id);
+ for(loop = 0; loop < NBR_RINGS; loop++)
+ if((loop != ring) && rings[loop].exists)
+ intel_batchbuffer_flush_on_ring(ts_bb[loop], rings[loop].id);
+
+ if(write) {
+ intel_batchbuffer_flush_on_ring(ts2_bb[ring], rings[ring].id);
+ for(loop = 0; loop < NBR_RINGS; loop++)
+ if((loop != ring) && rings[loop].exists)
+ intel_batchbuffer_flush_on_ring(ts2_bb[loop], rings[loop].id);
+ }
+
+ /* This will not return until the bo has finished executing */
+ drm_intel_bo_map(delay_bo, 0);
+ delay_buf = delay_bo->virtual;
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ drm_intel_bo_map(ts_bo[loop], 0);
+ ts_buf[loop] = ts_bo[loop]->virtual;
+ if(write) {
+ drm_intel_bo_map(ts2_bo[loop], 0);
+ ts2_buf[loop] = ts2_bo[loop]->virtual;
+ }
+ }
+
+ /* buf[0] in the target buffer should be 0 if the batch buffer completed */
+ igt_assert_f(delay_buf[0] == 0,
+ "delay_buf[0] expected 0x0, got 0x%" PRIx32 "\n",
+ delay_buf[0]);
+
+ igt_debug("%6s delay timestamp = 0x%08" PRIx32 "\n",
+ rings[ring].name, delay_buf[2]);
+ for(loop = 0; loop < NBR_RINGS; loop++)
+ igt_debug("%6s batch timestamp = 0x%08" PRIx32 "\n",
+ rings[loop].name, ts_buf[loop][0]);
+
+ if(write) {
+ igt_debug("Independant batch buffers\n");
+ for(loop = 0; loop < NBR_RINGS; loop++)
+ igt_debug("%6s batch timestamp = 0x%08" PRIx32 "\n",
+ rings[loop].name, ts2_buf[loop][0]);
+ }
+
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ if((loop != ring) && rings[loop].exists) {
+ if(write) {
+ /* Write dependency, delayed ring should run first */
+ igt_assert_f(igt_compare_timestamps(ts_buf[ring][0], ts_buf[loop][0]),
+ "%s ran before %s - 0x%08" PRIx32 " vs 0x%08" PRIx32 "\n",
+ rings[loop].name, rings[ring].name,
+ ts_buf[loop][0], ts_buf[ring][0]);
+ /* Second bb without dependency should run first */
+ igt_assert_f(igt_compare_timestamps(ts2_buf[loop][0], ts_buf[loop][0]),
+ "(%s) independant bb was held up - 0x%08" PRIx32 " vs 0x%08" PRIx32 "\n",
+ rings[loop].name, ts_buf[loop][0], ts2_buf[loop][0]);
+ }
+ else
+ /* Read dependency, delayed ring should run last */
+ igt_assert_f(igt_compare_timestamps(ts_buf[loop][0], ts_buf[ring][0]),
+ "%s ran after %s - 0x%08" PRIx32 " vs 0x%08" PRIx32 "\n",
+ rings[loop].name, rings[ring].name,
+ ts_buf[loop][0], ts_buf[ring][0]);
+ }
+ }
+
+ /* Cleanup */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_free(in_flight_bbs[loop]);
+
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ intel_batchbuffer_free(ts_bb[loop]);
+ drm_intel_bo_unreference(ts_bo[loop]);
+ drm_intel_bo_unreference(shared_bo[loop]);
+ if(write) {
+ intel_batchbuffer_free(ts2_bb[loop]);
+ drm_intel_bo_unreference(ts2_bo[loop]);
+ }
+ }
+
+ drm_intel_bo_unreference(delay_bo);
+
+ for(loop = 0; loop < NBR_RINGS; loop++) {
+ drm_intel_bufmgr_destroy(bufmgr[loop]);
+ close(fd[loop]);
+ if(write) {
+ drm_intel_bufmgr_destroy(bufmgr2[loop]);
+ close(fd2[loop]);
+ }
+ }
+
+ free(in_flight_bbs);
+}
+
+igt_main
+{
+ int loop;
+ int in_flight;
+ int fd;
+
+ igt_fixture {
+ int debug_fd;
+ int l;
+ char buf[6];
+ /* Get nbr of batch buffers that the scheduler will queue in the
+ * HW. If this debugfs file does not exist there is no scheduler
+ * so skip the test.
+ */
+ debug_fd = igt_debugfs_open("i915_scheduler_min_flying", O_RDONLY);
+ igt_skip_on(debug_fd == -1);
+ l = read(debug_fd, buf, sizeof(buf)-1);
+ igt_assert(l > 0);
+ igt_assert(l < sizeof(buf));
+ buf[l] = '\0';
+ /* May be a decimal or hex number depending on scheduler version */
+ if(sscanf(buf, "0x%2x", &in_flight) != 1)
+ igt_assert_f(sscanf(buf, "%2d", &in_flight) == 1,
+ "Error reading from i915_scheduler_min_flying\n");
+ close(debug_fd);
+ igt_debug("in flight = %d\n", in_flight);
+ fd = drm_open_driver(DRIVER_INTEL);
+ igt_assert(fd >= 0);
+ check_rings(fd);
+ }
+
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-basic", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_basic(in_flight, rings[loop].id);
+ }
+
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-read", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_dependency(in_flight, loop, false);
+ }
+
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-write", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_dependency(in_flight, loop, true);
+ }
+
+ igt_fixture {
+ close(fd);
+ }
+}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test
2016-03-02 18:10 ` [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test Derek Morton
@ 2016-03-02 20:15 ` Chris Wilson
2016-03-04 15:19 ` Morton, Derek J
2016-03-07 12:40 ` Dave Gordon
0 siblings, 2 replies; 15+ messages in thread
From: Chris Wilson @ 2016-03-02 20:15 UTC (permalink / raw)
To: Derek Morton; +Cc: daniel.vetter, intel-gfx
> +static struct ring {
> + const char *name;
> + int id;
> + bool exists;
> +} rings[] = {
> + { "render", I915_EXEC_RENDER, false },
> + { "bsd1", I915_EXEC_BSD | 1<<13, false },
> + { "bsd2", I915_EXEC_BSD | 2<<13, false },
This is wrong. The timeline is coupled to the exec_id, which is the same
for "both" BSD engines. To fix that, properly split up the two rings
with separate ids and deprecate HAS_BSD2.
> + { "blt", I915_EXEC_BLT, false },
> + { "vebox", I915_EXEC_VEBOX, false },
> +};
> +
> +#define NBR_RINGS (sizeof(rings)/sizeof(struct ring))
Also see intel_execution_engines to save on duplicating code.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test
2016-03-02 20:15 ` Chris Wilson
@ 2016-03-04 15:19 ` Morton, Derek J
2016-03-07 12:40 ` Dave Gordon
1 sibling, 0 replies; 15+ messages in thread
From: Morton, Derek J @ 2016-03-04 15:19 UTC (permalink / raw)
To: Chris Wilson; +Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org
I don't really understand your statement, can you elaborate please. What do you mean by timeline? Are you saying the driver needs changing? By deprecate HAS_BSD2 did you mean some change that would remove the need for gem_has_bsd2()? Doesn't I915_EXEC_BSD | 1<<13 and I915_EXEC_BSD | 2<<13 constitute separate exec_id's?
//Derek
-----Original Message-----
From: Chris Wilson [mailto:chris@chris-wilson.co.uk]
Sent: Wednesday, March 2, 2016 8:15 PM
To: Morton, Derek J <derek.j.morton@intel.com>
Cc: intel-gfx@lists.freedesktop.org; daniel.vetter@ffwll.ch
Subject: Re: [Intel-gfx] [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test
> +static struct ring {
> + const char *name;
> + int id;
> + bool exists;
> +} rings[] = {
> + { "render", I915_EXEC_RENDER, false },
> + { "bsd1", I915_EXEC_BSD | 1<<13, false },
> + { "bsd2", I915_EXEC_BSD | 2<<13, false },
This is wrong. The timeline is coupled to the exec_id, which is the same for "both" BSD engines. To fix that, properly split up the two rings with separate ids and deprecate HAS_BSD2.
> + { "blt", I915_EXEC_BLT, false },
> + { "vebox", I915_EXEC_VEBOX, false }, };
> +
> +#define NBR_RINGS (sizeof(rings)/sizeof(struct ring))
Also see intel_execution_engines to save on duplicating code.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test
2016-03-02 20:15 ` Chris Wilson
2016-03-04 15:19 ` Morton, Derek J
@ 2016-03-07 12:40 ` Dave Gordon
1 sibling, 0 replies; 15+ messages in thread
From: Dave Gordon @ 2016-03-07 12:40 UTC (permalink / raw)
To: Chris Wilson, Derek Morton, intel-gfx, daniel.vetter
On 02/03/16 20:15, Chris Wilson wrote:
>> +static struct ring {
>> + const char *name;
>> + int id;
>> + bool exists;
>> +} rings[] = {
>> + { "render", I915_EXEC_RENDER, false },
>> + { "bsd1", I915_EXEC_BSD | 1<<13, false },
>> + { "bsd2", I915_EXEC_BSD | 2<<13, false },
>
> This is wrong. The timeline is coupled to the exec_id, which is the same
> for "both" BSD engines. To fix that, properly split up the two rings
> with separate ids and deprecate HAS_BSD2.
>
>> + { "blt", I915_EXEC_BLT, false },
>> + { "vebox", I915_EXEC_VEBOX, false },
>> +};
>> +
>> +#define NBR_RINGS (sizeof(rings)/sizeof(struct ring))
>
> Also see intel_execution_engines to save on duplicating code.
> -Chris
exec_id is indeed the same for both BSD engines, but it is used ONLY in
i915_gem_busy_ioctl(), whose result can tell you that "a" BSD engine is
busy but not which one -- probably callers don't care anyway.
.Dave.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH i-g-t v2 5/7] igt/gem_ctx_param_basic: Updated to support scheduler priority interface
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
` (3 preceding siblings ...)
2016-03-02 18:10 ` [PATCH i-g-t v2 4/7] tests/gem_scheduler: Add gem_scheduler test Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 6/7] tests/gem_scheduler: Add subtests to test batch priority behaviour Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 7/7] gem_scheduler: Added subtests to test priority bumping Derek Morton
6 siblings, 0 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
From: John Harrison <John.C.Harrison@Intel.com>
The GPU scheduler has added an execution priority level to the context
object. There is an IOCTL interface to allow user apps/libraries to
set this priority. This patch updates the context paramter IOCTL test
to include the new interface.
For: VIZ-1587
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
---
lib/ioctl_wrappers.h | 1 +
tests/gem_ctx_param_basic.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index e095c41..9e6337e 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -107,6 +107,7 @@ struct local_i915_gem_context_param {
#define LOCAL_CONTEXT_PARAM_BAN_PERIOD 0x1
#define LOCAL_CONTEXT_PARAM_NO_ZEROMAP 0x2
#define LOCAL_CONTEXT_PARAM_GTT_SIZE 0x3
+#define LOCAL_CONTEXT_PARAM_PRIORITY 0x4
uint64_t value;
};
void gem_context_require_ban_period(int fd);
diff --git a/tests/gem_ctx_param_basic.c b/tests/gem_ctx_param_basic.c
index b75800c..585a1a8 100644
--- a/tests/gem_ctx_param_basic.c
+++ b/tests/gem_ctx_param_basic.c
@@ -147,10 +147,42 @@ igt_main
TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
}
+ ctx_param.param = LOCAL_CONTEXT_PARAM_PRIORITY;
+
+ igt_subtest("priority-root-set") {
+ ctx_param.context = ctx;
+ ctx_param.value = 2048;
+ TEST_FAIL(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM, EINVAL);
+ ctx_param.value = -2048;
+ TEST_FAIL(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM, EINVAL);
+ ctx_param.value = 512;
+ TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
+ ctx_param.value = -512;
+ TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
+ ctx_param.value = 0;
+ TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
+ }
+
+ igt_subtest("priority-non-root-set") {
+ igt_fork(child, 1) {
+ igt_drop_root();
+
+ ctx_param.context = ctx;
+ ctx_param.value = 512;
+ TEST_FAIL(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM, EPERM);
+ ctx_param.value = -512;
+ TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
+ ctx_param.value = 0;
+ TEST_SUCCESS(LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM);
+ }
+
+ igt_waitchildren();
+ }
+
/* NOTE: This testcase intentionally tests for the next free parameter
* to catch ABI extensions. Don't "fix" this testcase without adding all
* the tests for the new param first. */
- ctx_param.param = LOCAL_CONTEXT_PARAM_GTT_SIZE + 1;
+ ctx_param.param = LOCAL_CONTEXT_PARAM_PRIORITY + 1;
igt_subtest("invalid-param-get") {
ctx_param.context = ctx;
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH i-g-t v2 6/7] tests/gem_scheduler: Add subtests to test batch priority behaviour
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
` (4 preceding siblings ...)
2016-03-02 18:10 ` [PATCH i-g-t v2 5/7] igt/gem_ctx_param_basic: Updated to support scheduler priority interface Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
2016-03-02 18:10 ` [PATCH i-g-t v2 7/7] gem_scheduler: Added subtests to test priority bumping Derek Morton
6 siblings, 0 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
Add subtests to test each ring to check batch buffers of a higher
priority will be executed before batch buffers of a lower priority.
v2: Addressed review comments from Daniele Ceraolo Spurio
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
tests/gem_scheduler.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/tests/gem_scheduler.c b/tests/gem_scheduler.c
index 762b69f..171b0a3 100644
--- a/tests/gem_scheduler.c
+++ b/tests/gem_scheduler.c
@@ -39,7 +39,8 @@
IGT_TEST_DESCRIPTION("Check scheduler behaviour. Basic tests ensure independant "
"batch buffers of the same priority are executed in "
- "submission order. Read-read tests ensure "
+ "submission order. Priority tests ensure higher priority "
+ "batch buffers are executed first. Read-read tests ensure "
"batch buffers with a read dependency to the same buffer "
"object do not block each other. Write-write dependency "
"tests ensure batch buffers with a write dependency to a "
@@ -128,11 +129,23 @@ static void init_context(int *fd, drm_intel_bufmgr **bufmgr, int ringid)
intel_batchbuffer_free(noop_bb);
}
-/* Basic test. Check batch buffers of the same priority and with no dependencies
- * are executed in the order they are submitted.
+static void set_priority(int fd, int value)
+{
+ struct local_i915_gem_context_param param;
+ param.context = 0; /* Default context */
+ param.size = 0;
+ param.param = LOCAL_CONTEXT_PARAM_PRIORITY;
+ param.value = (uint64_t)value;
+ gem_context_set_param(fd, ¶m);
+}
+
+/* If 'priority' is 0, check batch buffers of the same priority and with
+ * no dependencies are executed in the order they are submitted.
+ * If 'priority' is set !0, check batch buffers of higher priority are
+ * executed before batch buffers of lower priority.
*/
#define NBR_BASIC_FDs (3)
-static void run_test_basic(int in_flight, int ringid)
+static void run_test_basic(int in_flight, int ringid, int priority)
{
int fd[NBR_BASIC_FDs];
int loop;
@@ -152,6 +165,13 @@ static void run_test_basic(int in_flight, int ringid)
for(loop=0; loop < NBR_BASIC_FDs; loop++)
init_context(&(fd[loop]), &(bufmgr[loop]), ringid);
+ /* For high priority set priority of second context to overtake first
+ * For low priority set priority of first context to be overtaxen by second
+ */
+ if(priority > 0)
+ set_priority(fd[2], priority);
+ else if(priority < 0)
+ set_priority(fd[1], priority);
/* Create buffer objects */
delay_bo = create_and_check_bo(bufmgr[0], "delay bo");
@@ -201,9 +221,14 @@ static void run_test_basic(int in_flight, int ringid)
igt_assert_f(igt_compare_timestamps(delay_buf[2], ts1_buf[0]),
"Delay ts (0x%08" PRIx32 ") > TS1 ts (0x%08" PRIx32 ")\n",
delay_buf[2], ts1_buf[0]);
- igt_assert_f(igt_compare_timestamps(ts1_buf[0], ts2_buf[0]),
- "TS1 ts (0x%08" PRIx32 ") > TS2 ts (0x%08" PRIx32 ")\n",
- ts1_buf[0], ts2_buf[0]);
+ if(priority)
+ igt_assert_f(igt_compare_timestamps(ts2_buf[0], ts1_buf[0]),
+ "TS2 ts (0x%08" PRIx32 ") > TS1 ts (0x%08" PRIx32 ")\n",
+ ts2_buf[0], ts1_buf[0]);
+ else
+ igt_assert_f(igt_compare_timestamps(ts1_buf[0], ts2_buf[0]),
+ "TS1 ts (0x%08" PRIx32 ") > TS2 ts (0x%08" PRIx32 ")\n",
+ ts1_buf[0], ts2_buf[0]);
/* Cleanup */
for(loop = 0; loop < in_flight; loop++)
@@ -430,7 +455,19 @@ igt_main
for (loop=0; loop < NBR_RINGS; loop++)
igt_subtest_f("%s-basic", rings[loop].name) {
gem_require_ring(fd, rings[loop].id);
- run_test_basic(in_flight, rings[loop].id);
+ run_test_basic(in_flight, rings[loop].id, false);
+ }
+
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-priority-high", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_basic(in_flight, rings[loop].id, 1000);
+ }
+
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-priority-low", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_basic(in_flight, rings[loop].id, -1000);
}
for (loop=0; loop < NBR_RINGS; loop++)
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH i-g-t v2 7/7] gem_scheduler: Added subtests to test priority bumping
2016-03-02 18:10 [PATCH i-g-t v2 0/7] Scheduler tests Derek Morton
` (5 preceding siblings ...)
2016-03-02 18:10 ` [PATCH i-g-t v2 6/7] tests/gem_scheduler: Add subtests to test batch priority behaviour Derek Morton
@ 2016-03-02 18:10 ` Derek Morton
6 siblings, 0 replies; 15+ messages in thread
From: Derek Morton @ 2016-03-02 18:10 UTC (permalink / raw)
To: intel-gfx; +Cc: daniel.vetter
When a higher priority batch buffer bumps a lower priority batch
buffer all batch buffers in the scheduler queue get a small priority
increase. Added a subtest to check this behaviour.
Requested by Joonas Lahtinen during scheduler code review
Signed-off-by: Derek Morton <derek.j.morton@intel.com>
---
tests/gem_scheduler.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/tests/gem_scheduler.c b/tests/gem_scheduler.c
index 171b0a3..0e2a4b4 100644
--- a/tests/gem_scheduler.c
+++ b/tests/gem_scheduler.c
@@ -246,6 +246,134 @@ static void run_test_basic(int in_flight, int ringid, int priority)
free(in_flight_bbs);
}
+
+/* Test priority bump behaviour.
+ * When a batch buffer is bumped by a higher priority batch buffer all other
+ * batch buffers in the scheduler queue get their priority increased slightly.
+ * Submit two delay batch buffers then fill the in flight queue. Submit a
+ * slightly reduced priority batch buffer and a normal priority batch buffer.
+ * When the first delay batch buffer completes priority bumping should occur.
+ * Submit another normal priority batch buffer. It should not overtake the
+ * reduced priority batch buffer as its priority has been bumped.
+ */
+#define NBR_PRIO_BUMP_FDs (4)
+static void run_test_priority_bump(int in_flight, int ringid)
+{
+ int fd[NBR_PRIO_BUMP_FDs];
+ int loop;
+ drm_intel_bufmgr *bufmgr[NBR_PRIO_BUMP_FDs];
+ uint32_t *delay_buf, *delay2_buf, *ts1_buf, *ts2_buf, *ts3_buf;
+ struct intel_batchbuffer *ts1_bb, *ts2_bb, *ts3_bb;
+ struct intel_batchbuffer **in_flight_bbs;
+ uint32_t calibrated_1s;
+ drm_intel_bo *delay_bo, *delay2_bo ,*ts1_bo, *ts2_bo, *ts3_bo;
+
+ in_flight_bbs = malloc(in_flight * sizeof(struct intel_batchbuffer *));
+ igt_assert(in_flight_bbs);
+
+ /* Need multiple i915 fd's. Scheduler will not change execution order of
+ * batch buffers from the same context.
+ */
+ for(loop=0; loop < NBR_PRIO_BUMP_FDs; loop++)
+ init_context(&(fd[loop]), &(bufmgr[loop]), ringid);
+
+ /* Lower priority of first timestamp batch buffer
+ * Second timestamp batch buffer should overtake the first
+ * Second should then get bumped so the third does not overtake it
+ */
+ set_priority(fd[1], -1);
+
+ /* Create buffer objects */
+ delay_bo = create_and_check_bo(bufmgr[0], "delay bo");
+ delay2_bo = create_and_check_bo(bufmgr[0], "delay bo2");
+ ts1_bo = create_and_check_bo(bufmgr[1], "ts1 bo");
+ ts2_bo = create_and_check_bo(bufmgr[2], "ts2 bo");
+ ts3_bo = create_and_check_bo(bufmgr[3], "ts23 bo");
+
+ /* Put some non zero values in the delay bo */
+ {
+ uint32_t data=0xffffffff;
+ drm_intel_bo_subdata(delay_bo, 0, 4, &data);
+ drm_intel_bo_subdata(delay2_bo, 0, 4, &data);
+ }
+
+ calibrated_1s = igt_calibrate_delay_bb(fd[0], bufmgr[0], ringid);
+
+ /* Batch buffers to fill the in flight queue */
+ in_flight_bbs[0] = create_delay_bb(fd[0], bufmgr[0], ringid, calibrated_1s, delay_bo);
+ in_flight_bbs[1] = create_delay_bb(fd[0], bufmgr[0], ringid, calibrated_1s, delay2_bo);
+ for(loop = 2; loop < in_flight; loop++)
+ in_flight_bbs[loop] = create_noop_bb(fd[0], bufmgr[0], 5);
+
+ /* Extra batch buffers in the scheduler queue */
+ ts1_bb = create_timestamp_bb(fd[1], bufmgr[1], ringid, ts1_bo, NULL, false);
+ ts2_bb = create_timestamp_bb(fd[2], bufmgr[2], ringid, ts2_bo, NULL, false);
+ ts3_bb = create_timestamp_bb(fd[3], bufmgr[3], ringid, ts3_bo, NULL, false);
+
+ /* Flush batchbuffers */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_flush_on_ring(in_flight_bbs[loop], ringid);
+ intel_batchbuffer_flush_on_ring(ts1_bb, ringid);
+ intel_batchbuffer_flush_on_ring(ts2_bb, ringid);
+
+ /* This will not return until the bo has finished executing */
+ drm_intel_bo_map(delay_bo, 0);
+ /* Once the first delay is complete and any bumping has occured, submit
+ * the final batch buffer
+ */
+ intel_batchbuffer_flush_on_ring(ts3_bb, ringid);
+
+ drm_intel_bo_map(delay2_bo, 0);
+ drm_intel_bo_map(ts1_bo, 0);
+ drm_intel_bo_map(ts2_bo, 0);
+ drm_intel_bo_map(ts3_bo, 0);
+
+ delay_buf = delay_bo->virtual;
+ delay2_buf = delay2_bo->virtual;
+ ts1_buf = ts1_bo->virtual;
+ ts2_buf = ts2_bo->virtual;
+ ts3_buf = ts3_bo->virtual;
+
+ igt_debug("Delay Timestamp = 0x%08" PRIx32 "\n", delay_buf[2]);
+ igt_debug("Delay Timestamp = 0x%08" PRIx32 "\n", delay2_buf[2]);
+ igt_debug("TS1 Timestamp = 0x%08" PRIx32 "\n", ts1_buf[0]);
+ igt_debug("TS2 Timestamp = 0x%08" PRIx32 "\n", ts2_buf[0]);
+ igt_debug("TS3 Timestamp = 0x%08" PRIx32 "\n", ts3_buf[0]);
+
+ /* buf[0] in the target buffer should be 0 if the batch buffer completed */
+ igt_assert_f(delay_buf[0] == 0,
+ "delay_buf[0] expected 0x0, got 0x%" PRIx32 "\n", delay_buf[0]);
+
+ igt_assert_f(igt_compare_timestamps(delay_buf[2], ts1_buf[0]),
+ "Delay ts (0x%08" PRIx32 ") > TS1 ts (0x%08" PRIx32 ")\n",
+ delay_buf[2], ts1_buf[0]);
+
+ igt_assert_f(igt_compare_timestamps(ts2_buf[0], ts1_buf[0]),
+ "TS2 ts (0x%08" PRIx32 ") > TS1 ts (0x%08" PRIx32 ")\n",
+ ts2_buf[0], ts1_buf[0]);
+
+ igt_assert_f(igt_compare_timestamps(ts1_buf[0], ts3_buf[0]),
+ "TS1 ts (0x%08" PRIx32 ") > TS3 ts (0x%08" PRIx32 ")\n",
+ ts1_buf[0], ts3_buf[0]);
+
+ /* Cleanup */
+ for(loop = 0; loop < in_flight; loop++)
+ intel_batchbuffer_free(in_flight_bbs[loop]);
+ intel_batchbuffer_free(ts1_bb);
+ intel_batchbuffer_free(ts2_bb);
+
+ drm_intel_bo_unreference(delay_bo);
+ drm_intel_bo_unreference(delay2_bo);
+ drm_intel_bo_unreference(ts1_bo);
+ drm_intel_bo_unreference(ts2_bo);
+ drm_intel_bo_unreference(ts3_bo);
+ for(loop = 0; loop < NBR_PRIO_BUMP_FDs; loop++) {
+ drm_intel_bufmgr_destroy(bufmgr[loop]);
+ close(fd[loop]);
+ }
+ free(in_flight_bbs);
+}
+
/* Dependency test.
* write=0, Submit batch buffers with read dependencies to all rings. Delay one
* with a long executing batch buffer. Check the others are not held up.
@@ -482,6 +610,12 @@ igt_main
run_test_dependency(in_flight, loop, true);
}
+ for (loop=0; loop < NBR_RINGS; loop++)
+ igt_subtest_f("%s-priority-bump", rings[loop].name) {
+ gem_require_ring(fd, rings[loop].id);
+ run_test_priority_bump(in_flight, rings[loop].id);
+ }
+
igt_fixture {
close(fd);
}
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 15+ messages in thread