aa0e01e17b9f13db4289f7ea79ec868f5b29e0fb
[platform/upstream/intel-gpu-tools.git] / tests / gem_unfence_active_buffers.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Daniel Vetter <daniel.vetter@ffwll.ch>
25  *
26  */
27
28 /** @file gem_unfence_active_buffers.c
29  *
30  * Testcase: Check for use-after free in the fence stealing code
31  *
32  * If we're stealing the fence of a active object where the active list is the
33  * only thing holding a reference, we need to be careful not to access the old
34  * object we're stealing the fence from after that reference has been dropped by
35  * retire_requests.
36  *
37  * Note that this needs slab poisoning enabled in the kernel to reliably hit the
38  * problem - the race window is too small.
39  */
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <fcntl.h>
45 #include <inttypes.h>
46 #include <errno.h>
47 #include <sys/stat.h>
48 #include <sys/time.h>
49 #include <stdbool.h>
50 #include "drm.h"
51 #include "ioctl_wrappers.h"
52 #include "drmtest.h"
53 #include "intel_bufmgr.h"
54 #include "intel_batchbuffer.h"
55 #include "intel_io.h"
56 #include "intel_chipset.h"
57
58 static drm_intel_bufmgr *bufmgr;
59 struct intel_batchbuffer *batch;
60 uint32_t devid;
61
62 #define TEST_SIZE (1024*1024)
63 #define TEST_STRIDE (4*1024)
64
65 uint32_t data[TEST_SIZE/4];
66
67 igt_simple_main
68 {
69         int i, ret, fd, num_fences;
70         drm_intel_bo *busy_bo, *test_bo;
71         uint32_t tiling = I915_TILING_X;
72
73         igt_skip_on_simulation();
74
75         for (i = 0; i < 1024*256; i++)
76                 data[i] = i;
77
78         fd = drm_open_any();
79
80         bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
81         drm_intel_bufmgr_gem_enable_reuse(bufmgr);
82         devid = intel_get_drm_devid(fd);
83         batch = intel_batchbuffer_alloc(bufmgr, devid);
84
85         igt_info("filling ring\n");
86         busy_bo = drm_intel_bo_alloc(bufmgr, "busy bo bo", 16*1024*1024, 4096);
87
88         for (i = 0; i < 250; i++) {
89                 BLIT_COPY_BATCH_START(devid, 0);
90                 OUT_BATCH((3 << 24) | /* 32 bits */
91                           (0xcc << 16) | /* copy ROP */
92                           2*1024*4);
93                 OUT_BATCH(0 << 16 | 1024);
94                 OUT_BATCH((2048) << 16 | (2048));
95                 OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
96                 BLIT_RELOC_UDW(devid);
97                 OUT_BATCH(0 << 16 | 0);
98                 OUT_BATCH(2*1024*4);
99                 OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
100                 BLIT_RELOC_UDW(devid);
101                 ADVANCE_BATCH();
102
103                 if (IS_GEN6(devid) || IS_GEN7(devid)) {
104                         BEGIN_BATCH(3);
105                         OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
106                         OUT_BATCH(0);
107                         OUT_BATCH(0);
108                         ADVANCE_BATCH();
109                 }
110         }
111         intel_batchbuffer_flush(batch);
112
113         num_fences = gem_available_fences(fd);
114         igt_info("creating havoc on %i fences\n", num_fences);
115
116         for (i = 0; i < num_fences*2; i++) {
117                 test_bo = drm_intel_bo_alloc(bufmgr, "test_bo",
118                                              TEST_SIZE, 4096);
119                 ret = drm_intel_bo_set_tiling(test_bo, &tiling, TEST_STRIDE);
120                 igt_assert(ret == 0);
121
122                 drm_intel_bo_disable_reuse(test_bo);
123
124                 BLIT_COPY_BATCH_START(devid, 0);
125                 OUT_BATCH((3 << 24) | /* 32 bits */
126                           (0xcc << 16) | /* copy ROP */
127                           TEST_STRIDE);
128                 OUT_BATCH(0 << 16 | 0);
129                 OUT_BATCH((1) << 16 | (1));
130                 OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
131                 BLIT_RELOC_UDW(devid);
132                 OUT_BATCH(0 << 16 | 0);
133                 OUT_BATCH(TEST_STRIDE);
134                 OUT_RELOC_FENCED(test_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
135                 BLIT_RELOC_UDW(devid);
136                 ADVANCE_BATCH();
137                 intel_batchbuffer_flush(batch);
138                 igt_info("test bo offset: %#lx\n", test_bo->offset);
139
140                 drm_intel_bo_unreference(test_bo);
141         }
142
143         /* launch a few batchs to ensure the damaged slab objects get reused. */
144         for (i = 0; i < 10; i++) {
145                 BLIT_COPY_BATCH_START(devid, 0);
146                 OUT_BATCH((3 << 24) | /* 32 bits */
147                           (0xcc << 16) | /* copy ROP */
148                           2*1024*4);
149                 OUT_BATCH(0 << 16 | 1024);
150                 OUT_BATCH((1) << 16 | (1));
151                 OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
152                 BLIT_RELOC_UDW(devid);
153                 OUT_BATCH(0 << 16 | 0);
154                 OUT_BATCH(2*1024*4);
155                 OUT_RELOC_FENCED(busy_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
156                 BLIT_RELOC_UDW(devid);
157                 ADVANCE_BATCH();
158
159                 if (IS_GEN6(devid) || IS_GEN7(devid)) {
160                         BEGIN_BATCH(3);
161                         OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
162                         OUT_BATCH(0);
163                         OUT_BATCH(0);
164                         ADVANCE_BATCH();
165                 }
166         }
167         intel_batchbuffer_flush(batch);
168 }