Prepare for 64bit relocation addresses
[platform/upstream/intel-gpu-tools.git] / tests / gem_tiled_partial_pwrite_pread.c
1 /*
2  * Copyright © 2011 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 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <inttypes.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36
37 #include <drm.h>
38
39 #include "ioctl_wrappers.h"
40 #include "drmtest.h"
41 #include "intel_chipset.h"
42 #include "intel_io.h"
43 #include "igt_aux.h"
44
45 /*
46  * Testcase: pwrite/pread consistency when touching partial cachelines
47  *
48  * Some fancy new pwrite/pread optimizations clflush in-line while
49  * reading/writing. Check whether all required clflushes happen.
50  *
51  * Unfortunately really old mesa used unaligned pread/pwrite for s/w fallback
52  * rendering, so we need to check whether this works on tiled buffers, too.
53  *
54  */
55
56 static drm_intel_bufmgr *bufmgr;
57 struct intel_batchbuffer *batch;
58
59 drm_intel_bo *scratch_bo;
60 drm_intel_bo *staging_bo;
61 drm_intel_bo *tiled_staging_bo;
62 unsigned long scratch_pitch;
63 #define BO_SIZE (32*4096)
64 uint32_t devid;
65 uint64_t mappable_gtt_limit;
66 int fd;
67
68 static void
69 copy_bo(drm_intel_bo *src, int src_tiled,
70         drm_intel_bo *dst, int dst_tiled)
71 {
72         unsigned long dst_pitch = scratch_pitch;
73         unsigned long src_pitch = scratch_pitch;
74         uint32_t cmd_bits = 0;
75
76         /* dst is tiled ... */
77         if (intel_gen(devid) >= 4 && dst_tiled) {
78                 dst_pitch /= 4;
79                 cmd_bits |= XY_SRC_COPY_BLT_DST_TILED;
80         }
81
82         if (intel_gen(devid) >= 4 && dst_tiled) {
83                 src_pitch /= 4;
84                 cmd_bits |= XY_SRC_COPY_BLT_SRC_TILED;
85         }
86
87         BLIT_COPY_BATCH_START(devid, cmd_bits);
88         OUT_BATCH((3 << 24) | /* 32 bits */
89                   (0xcc << 16) | /* copy ROP */
90                   dst_pitch);
91         OUT_BATCH(0 << 16 | 0);
92         OUT_BATCH(BO_SIZE/scratch_pitch << 16 | 1024);
93         OUT_RELOC_FENCED(dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
94         OUT_BATCH(0 << 16 | 0);
95         OUT_BATCH(src_pitch);
96         OUT_RELOC_FENCED(src, I915_GEM_DOMAIN_RENDER, 0, 0);
97         ADVANCE_BATCH();
98
99         intel_batchbuffer_flush(batch);
100 }
101
102 static void
103 blt_bo_fill(drm_intel_bo *tmp_bo, drm_intel_bo *bo, int val)
104 {
105         uint8_t *gtt_ptr;
106         int i;
107
108         drm_intel_gem_bo_map_gtt(tmp_bo);
109         gtt_ptr = tmp_bo->virtual;
110
111         for (i = 0; i < BO_SIZE; i++)
112                 gtt_ptr[i] = val;
113
114         drm_intel_gem_bo_unmap_gtt(tmp_bo);
115
116         if (bo->offset < mappable_gtt_limit &&
117             (IS_G33(devid) || intel_gen(devid) >= 4))
118                 igt_trash_aperture();
119
120         copy_bo(tmp_bo, 0, bo, 1);
121 }
122
123 #define MAX_BLT_SIZE 128
124 #define ROUNDS 200
125 uint8_t tmp[BO_SIZE];
126 uint8_t compare_tmp[BO_SIZE];
127
128 static void test_partial_reads(void)
129 {
130         int i, j;
131
132         for (i = 0; i < ROUNDS; i++) {
133                 int start, len;
134                 int val = i % 256;
135
136                 blt_bo_fill(staging_bo, scratch_bo, i);
137
138                 start = random() % BO_SIZE;
139                 len = random() % (BO_SIZE-start) + 1;
140
141                 drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
142                 for (j = 0; j < len; j++) {
143                         igt_assert_f(tmp[j] == val,
144                                      "mismatch at %i, got: %i, expected: %i\n",
145                                      start + j, tmp[j], val);
146                 }
147
148                 igt_progress("partial reads test: ", i, ROUNDS);
149         }
150 }
151
152 static void test_partial_writes(void)
153 {
154         int i, j;
155
156         for (i = 0; i < ROUNDS; i++) {
157                 int start, len;
158                 int val = i % 256;
159
160                 blt_bo_fill(staging_bo, scratch_bo, i);
161
162                 start = random() % BO_SIZE;
163                 len = random() % (BO_SIZE-start) + 1;
164
165                 memset(tmp, i + 63, BO_SIZE);
166
167                 drm_intel_bo_subdata(scratch_bo, start, len, tmp);
168
169                 copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
170                 drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
171                                          compare_tmp);
172
173                 for (j = 0; j < start; j++) {
174                         igt_assert_f(compare_tmp[j] == val,
175                                      "mismatch at %i, got: %i, expected: %i\n",
176                                      j, tmp[j], val);
177                 }
178                 for (; j < start + len; j++) {
179                         igt_assert_f(compare_tmp[j] == tmp[0],
180                                      "mismatch at %i, got: %i, expected: %i\n",
181                                      j, tmp[j], i);
182                 }
183                 for (; j < BO_SIZE; j++) {
184                         igt_assert_f(compare_tmp[j] == val,
185                                      "mismatch at %i, got: %i, expected: %i\n",
186                                      j, tmp[j], val);
187                 }
188                 drm_intel_gem_bo_unmap_gtt(staging_bo);
189
190                 igt_progress("partial writes test: ", i, ROUNDS);
191         }
192 }
193
194 static void test_partial_read_writes(void)
195 {
196         int i, j;
197
198         for (i = 0; i < ROUNDS; i++) {
199                 int start, len;
200                 int val = i % 256;
201
202                 blt_bo_fill(staging_bo, scratch_bo, i);
203
204                 /* partial read */
205                 start = random() % BO_SIZE;
206                 len = random() % (BO_SIZE-start) + 1;
207
208                 drm_intel_bo_get_subdata(scratch_bo, start, len, tmp);
209                 for (j = 0; j < len; j++) {
210                         igt_assert_f(tmp[j] == val,
211                                      "mismatch in read at %i, got: %i, expected: %i\n",
212                                      start + j, tmp[j], val);
213                 }
214
215                 /* Change contents through gtt to make the pread cachelines
216                  * stale. */
217                 val = (i + 17) % 256;
218                 blt_bo_fill(staging_bo, scratch_bo, val);
219
220                 /* partial write */
221                 start = random() % BO_SIZE;
222                 len = random() % (BO_SIZE-start) + 1;
223
224                 memset(tmp, i + 63, BO_SIZE);
225
226                 drm_intel_bo_subdata(scratch_bo, start, len, tmp);
227
228                 copy_bo(scratch_bo, 1, tiled_staging_bo, 1);
229                 drm_intel_bo_get_subdata(tiled_staging_bo, 0, BO_SIZE,
230                                          compare_tmp);
231
232                 for (j = 0; j < start; j++) {
233                         igt_assert_f(compare_tmp[j] == val,
234                                      "mismatch at %i, got: %i, expected: %i\n",
235                                      j, tmp[j], val);
236                 }
237                 for (; j < start + len; j++) {
238                         igt_assert_f(compare_tmp[j] == tmp[0],
239                                      "mismatch at %i, got: %i, expected: %i\n",
240                                      j, tmp[j], tmp[0]);
241                 }
242                 for (; j < BO_SIZE; j++) {
243                         igt_assert_f(compare_tmp[j] == val,
244                                      "mismatch at %i, got: %i, expected: %i\n",
245                                      j, tmp[j], val);
246                 }
247                 drm_intel_gem_bo_unmap_gtt(staging_bo);
248
249                 igt_progress("partial read/writes test: ", i, ROUNDS);
250         }
251 }
252
253 igt_main
254 {
255         uint32_t tiling_mode = I915_TILING_X;
256
257         igt_skip_on_simulation();
258
259         srandom(0xdeadbeef);
260
261         igt_fixture {
262                 fd = drm_open_any();
263
264                 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
265                 //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
266                 devid = intel_get_drm_devid(fd);
267                 batch = intel_batchbuffer_alloc(bufmgr, devid);
268
269                 /* overallocate the buffers we're actually using because */
270                 scratch_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
271                                                       BO_SIZE/4096, 4,
272                                                       &tiling_mode, &scratch_pitch, 0);
273                 igt_assert(tiling_mode == I915_TILING_X);
274                 igt_assert(scratch_pitch == 4096);
275                 staging_bo = drm_intel_bo_alloc(bufmgr, "staging bo", BO_SIZE, 4096);
276                 tiled_staging_bo = drm_intel_bo_alloc_tiled(bufmgr, "scratch bo", 1024,
277                                                             BO_SIZE/4096, 4,
278                                                             &tiling_mode,
279                                                             &scratch_pitch, 0);
280
281                 igt_init_aperture_trashers(bufmgr);
282                 mappable_gtt_limit = gem_mappable_aperture_size();
283         }
284
285         igt_subtest("reads")
286                 test_partial_reads();
287
288         igt_subtest("writes")
289                 test_partial_writes();
290
291         igt_subtest("writes-after-reads")
292                 test_partial_read_writes();
293
294         igt_fixture {
295                 igt_cleanup_aperture_trashers();
296                 drm_intel_bufmgr_destroy(bufmgr);
297
298                 close(fd);
299         }
300 }