1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// SPDX-License-Identifier: MIT
/*
* Copyright © 2022 Intel Corporation
*/
#include "igt.h"
#include "igt_kmod.h"
#include "i915/gem_create.h"
#include "i915/gem.h"
/**
* TEST: gem lmem evict
* Description: Force tiny lmem size for easily testing eviction scenarios.
* Category: Core
* Mega feature: General Core features
* Sub-category: Memory management tests
* Functionality: local memory eviction
* Feature: local_memory
* Test category: GEM_Legacy
*
* SUBTEST: dontneed-evict-race
* Description: Regression test to verify that madvise will sync against busy dma-resv object for lmem
*/
IGT_TEST_DESCRIPTION("Force tiny lmem size for easily testing eviction scenarios.");
#define PAGE_SIZE 4096
static uint32_t batch_create_size(int fd, uint64_t size)
{
const uint32_t bbe = MI_BATCH_BUFFER_END;
uint32_t handle;
handle = gem_create(fd, size);
gem_write(fd, handle, 0, &bbe, sizeof(bbe));
return handle;
}
static int upload(int fd, uint32_t handle)
{
struct drm_i915_gem_exec_object2 exec[2] = {};
struct drm_i915_gem_execbuffer2 execbuf = {
.buffers_ptr = to_user_pointer(&exec),
.buffer_count = 2,
};
exec[0].handle = handle;
exec[0].flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
exec[1].handle = batch_create_size(fd, PAGE_SIZE);
exec[1].flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
gem_execbuf(fd, &execbuf);
return 0;
}
static void test_dontneed_evict_race(int fd,
struct gem_memory_region *region)
{
const uint64_t size = region->size >> 1;
uint64_t ahnd = get_reloc_ahnd(fd, 0);
uint32_t handle1;
igt_spin_t *spin;
handle1 = gem_create_in_memory_region_list(fd, size, 0,
®ion->ci, 1);
spin = igt_spin_new(fd,
.ahnd = ahnd,
.dependency = handle1);
igt_fork(child, 1) {
uint32_t handle2;
fd = drm_reopen_driver(fd);
handle2 = gem_create_in_memory_region_list(fd,
size, 0,
®ion->ci, 1);
/*
* The actual move when evicting will be pipelined
* behind the spinner, so can't fire until the spinner
* is killed.
*/
upload(fd, handle2);
gem_close(fd, handle2);
}
sleep(2); /* Give eviction time to find handle1 */
igt_spin_end(spin);
gem_madvise(fd, handle1, I915_MADV_DONTNEED);
igt_waitchildren();
igt_spin_free(fd, spin);
gem_close(fd, handle1);
}
igt_main
{
struct drm_i915_query_memory_regions *regions;
int i915 = -1;
igt_fixture {
char *tmp;
if (igt_kmod_is_loaded("i915")) {
i915 = __drm_open_driver(DRIVER_INTEL);
igt_require_fd(i915);
igt_require_gem(i915);
igt_require(gem_has_lmem(i915));
drm_close_driver(i915);
}
igt_i915_driver_unload();
/*
* To avoid running of ring space and stalling during evicting
* (while holding the dma-resv lock), we need to use a smaller
* lmem size, such we can easliy trigger eviction without
* needing to wait for more ring space. The point of the test is
* to mark the object as DONTNEED which has an in-progress
* pipilined unbind/move, which also requires grabbing the
* dma-resv lock.
*/
igt_assert_eq(igt_i915_driver_load("lmem_size=128"), 0);
i915 = __drm_open_driver(DRIVER_INTEL);
igt_require_fd(i915);
igt_require_gem(i915);
igt_require(gem_has_lmem(i915));
tmp = __igt_params_get(i915, "lmem_size");
igt_skip_on(!tmp);
free(tmp);
regions = gem_get_query_memory_regions(i915);
igt_require(regions);
}
igt_describe("Regression test to verify that madvise will sync against busy dma-resv object for lmem");
igt_subtest("dontneed-evict-race") {
for_each_memory_region(r, i915) {
if (r->ci.memory_class == I915_MEMORY_CLASS_DEVICE) {
test_dontneed_evict_race(i915, r);
break;
}
}
}
igt_fixture {
drm_close_driver(i915);
igt_i915_driver_unload();
}
}
|