1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2007, 2011, 2013, 2014, 2019 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker *
23*d83cc019SAndroid Build Coastguard Worker */
24*d83cc019SAndroid Build Coastguard Worker
25*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
26*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
27*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
28*d83cc019SAndroid Build Coastguard Worker
29*d83cc019SAndroid Build Coastguard Worker #include "igt_core.h"
30*d83cc019SAndroid Build Coastguard Worker #include "ioctl_wrappers.h"
31*d83cc019SAndroid Build Coastguard Worker
32*d83cc019SAndroid Build Coastguard Worker #include "gem_mman.h"
33*d83cc019SAndroid Build Coastguard Worker
34*d83cc019SAndroid Build Coastguard Worker #ifdef HAVE_VALGRIND
35*d83cc019SAndroid Build Coastguard Worker #include <valgrind/valgrind.h>
36*d83cc019SAndroid Build Coastguard Worker #include <valgrind/memcheck.h>
37*d83cc019SAndroid Build Coastguard Worker
38*d83cc019SAndroid Build Coastguard Worker #define VG(x) x
39*d83cc019SAndroid Build Coastguard Worker #else
40*d83cc019SAndroid Build Coastguard Worker #define VG(x) do {} while (0)
41*d83cc019SAndroid Build Coastguard Worker #endif
42*d83cc019SAndroid Build Coastguard Worker
43*d83cc019SAndroid Build Coastguard Worker /**
44*d83cc019SAndroid Build Coastguard Worker * __gem_mmap__gtt:
45*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
46*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
47*d83cc019SAndroid Build Coastguard Worker * @size: size of the gem buffer
48*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
49*d83cc019SAndroid Build Coastguard Worker *
50*d83cc019SAndroid Build Coastguard Worker * This functions wraps up procedure to establish a memory mapping through the
51*d83cc019SAndroid Build Coastguard Worker * GTT.
52*d83cc019SAndroid Build Coastguard Worker *
53*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping, NULL on failure.
54*d83cc019SAndroid Build Coastguard Worker */
__gem_mmap__gtt(int fd,uint32_t handle,uint64_t size,unsigned prot)55*d83cc019SAndroid Build Coastguard Worker void *__gem_mmap__gtt(int fd, uint32_t handle, uint64_t size, unsigned prot)
56*d83cc019SAndroid Build Coastguard Worker {
57*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_mmap_gtt mmap_arg;
58*d83cc019SAndroid Build Coastguard Worker void *ptr;
59*d83cc019SAndroid Build Coastguard Worker
60*d83cc019SAndroid Build Coastguard Worker memset(&mmap_arg, 0, sizeof(mmap_arg));
61*d83cc019SAndroid Build Coastguard Worker mmap_arg.handle = handle;
62*d83cc019SAndroid Build Coastguard Worker if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg))
63*d83cc019SAndroid Build Coastguard Worker return NULL;
64*d83cc019SAndroid Build Coastguard Worker
65*d83cc019SAndroid Build Coastguard Worker ptr = mmap64(0, size, prot, MAP_SHARED, fd, mmap_arg.offset);
66*d83cc019SAndroid Build Coastguard Worker if (ptr == MAP_FAILED)
67*d83cc019SAndroid Build Coastguard Worker ptr = NULL;
68*d83cc019SAndroid Build Coastguard Worker else
69*d83cc019SAndroid Build Coastguard Worker errno = 0;
70*d83cc019SAndroid Build Coastguard Worker
71*d83cc019SAndroid Build Coastguard Worker VG(VALGRIND_MAKE_MEM_DEFINED(ptr, size));
72*d83cc019SAndroid Build Coastguard Worker
73*d83cc019SAndroid Build Coastguard Worker return ptr;
74*d83cc019SAndroid Build Coastguard Worker }
75*d83cc019SAndroid Build Coastguard Worker
76*d83cc019SAndroid Build Coastguard Worker /**
77*d83cc019SAndroid Build Coastguard Worker * gem_mmap__gtt:
78*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
79*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
80*d83cc019SAndroid Build Coastguard Worker * @size: size of the gem buffer
81*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
82*d83cc019SAndroid Build Coastguard Worker *
83*d83cc019SAndroid Build Coastguard Worker * Like __gem_mmap__gtt() except we assert on failure.
84*d83cc019SAndroid Build Coastguard Worker *
85*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping
86*d83cc019SAndroid Build Coastguard Worker */
gem_mmap__gtt(int fd,uint32_t handle,uint64_t size,unsigned prot)87*d83cc019SAndroid Build Coastguard Worker void *gem_mmap__gtt(int fd, uint32_t handle, uint64_t size, unsigned prot)
88*d83cc019SAndroid Build Coastguard Worker {
89*d83cc019SAndroid Build Coastguard Worker void *ptr = __gem_mmap__gtt(fd, handle, size, prot);
90*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr);
91*d83cc019SAndroid Build Coastguard Worker return ptr;
92*d83cc019SAndroid Build Coastguard Worker }
93*d83cc019SAndroid Build Coastguard Worker
gem_munmap(void * ptr,uint64_t size)94*d83cc019SAndroid Build Coastguard Worker int gem_munmap(void *ptr, uint64_t size)
95*d83cc019SAndroid Build Coastguard Worker {
96*d83cc019SAndroid Build Coastguard Worker int ret = munmap(ptr, size);
97*d83cc019SAndroid Build Coastguard Worker
98*d83cc019SAndroid Build Coastguard Worker if (ret == 0)
99*d83cc019SAndroid Build Coastguard Worker VG(VALGRIND_MAKE_MEM_NOACCESS(ptr, size));
100*d83cc019SAndroid Build Coastguard Worker
101*d83cc019SAndroid Build Coastguard Worker return ret;
102*d83cc019SAndroid Build Coastguard Worker }
103*d83cc019SAndroid Build Coastguard Worker
gem_mmap__has_wc(int fd)104*d83cc019SAndroid Build Coastguard Worker bool gem_mmap__has_wc(int fd)
105*d83cc019SAndroid Build Coastguard Worker {
106*d83cc019SAndroid Build Coastguard Worker static int has_wc = -1;
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker if (has_wc == -1) {
109*d83cc019SAndroid Build Coastguard Worker struct drm_i915_getparam gp;
110*d83cc019SAndroid Build Coastguard Worker int mmap_version = -1;
111*d83cc019SAndroid Build Coastguard Worker int gtt_version = -1;
112*d83cc019SAndroid Build Coastguard Worker
113*d83cc019SAndroid Build Coastguard Worker has_wc = 0;
114*d83cc019SAndroid Build Coastguard Worker
115*d83cc019SAndroid Build Coastguard Worker memset(&gp, 0, sizeof(gp));
116*d83cc019SAndroid Build Coastguard Worker gp.param = I915_PARAM_MMAP_GTT_VERSION;
117*d83cc019SAndroid Build Coastguard Worker gp.value = >t_version;
118*d83cc019SAndroid Build Coastguard Worker ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
119*d83cc019SAndroid Build Coastguard Worker
120*d83cc019SAndroid Build Coastguard Worker memset(&gp, 0, sizeof(gp));
121*d83cc019SAndroid Build Coastguard Worker gp.param = I915_PARAM_MMAP_VERSION;
122*d83cc019SAndroid Build Coastguard Worker gp.value = &mmap_version;
123*d83cc019SAndroid Build Coastguard Worker ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
124*d83cc019SAndroid Build Coastguard Worker
125*d83cc019SAndroid Build Coastguard Worker /* Do we have the new mmap_ioctl with DOMAIN_WC? */
126*d83cc019SAndroid Build Coastguard Worker if (mmap_version >= 1 && gtt_version >= 2) {
127*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_mmap arg;
128*d83cc019SAndroid Build Coastguard Worker
129*d83cc019SAndroid Build Coastguard Worker /* Does this device support wc-mmaps ? */
130*d83cc019SAndroid Build Coastguard Worker memset(&arg, 0, sizeof(arg));
131*d83cc019SAndroid Build Coastguard Worker arg.handle = gem_create(fd, 4096);
132*d83cc019SAndroid Build Coastguard Worker arg.offset = 0;
133*d83cc019SAndroid Build Coastguard Worker arg.size = 4096;
134*d83cc019SAndroid Build Coastguard Worker arg.flags = I915_MMAP_WC;
135*d83cc019SAndroid Build Coastguard Worker has_wc = igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg) == 0;
136*d83cc019SAndroid Build Coastguard Worker gem_close(fd, arg.handle);
137*d83cc019SAndroid Build Coastguard Worker }
138*d83cc019SAndroid Build Coastguard Worker errno = 0;
139*d83cc019SAndroid Build Coastguard Worker }
140*d83cc019SAndroid Build Coastguard Worker
141*d83cc019SAndroid Build Coastguard Worker return has_wc > 0;
142*d83cc019SAndroid Build Coastguard Worker }
143*d83cc019SAndroid Build Coastguard Worker
144*d83cc019SAndroid Build Coastguard Worker /**
145*d83cc019SAndroid Build Coastguard Worker * __gem_mmap:
146*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
147*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
148*d83cc019SAndroid Build Coastguard Worker * @offset: offset in the gem buffer of the mmap arena
149*d83cc019SAndroid Build Coastguard Worker * @size: size of the mmap arena
150*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
151*d83cc019SAndroid Build Coastguard Worker * @flags: flags used to determine caching
152*d83cc019SAndroid Build Coastguard Worker *
153*d83cc019SAndroid Build Coastguard Worker * This functions wraps up procedure to establish a memory mapping through
154*d83cc019SAndroid Build Coastguard Worker * direct cpu access, bypassing the gpu (valid for wc == false). For wc == true
155*d83cc019SAndroid Build Coastguard Worker * it also bypass cpu caches completely and GTT system agent (i.e. there is no
156*d83cc019SAndroid Build Coastguard Worker * automatic tiling of the mmapping through the fence registers).
157*d83cc019SAndroid Build Coastguard Worker *
158*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping, NULL on failure.
159*d83cc019SAndroid Build Coastguard Worker */
160*d83cc019SAndroid Build Coastguard Worker static void
__gem_mmap(int fd,uint32_t handle,uint64_t offset,uint64_t size,unsigned int prot,uint64_t flags)161*d83cc019SAndroid Build Coastguard Worker *__gem_mmap(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned int prot, uint64_t flags)
162*d83cc019SAndroid Build Coastguard Worker {
163*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_mmap arg;
164*d83cc019SAndroid Build Coastguard Worker
165*d83cc019SAndroid Build Coastguard Worker memset(&arg, 0, sizeof(arg));
166*d83cc019SAndroid Build Coastguard Worker arg.handle = handle;
167*d83cc019SAndroid Build Coastguard Worker arg.offset = offset;
168*d83cc019SAndroid Build Coastguard Worker arg.size = size;
169*d83cc019SAndroid Build Coastguard Worker arg.flags = flags;
170*d83cc019SAndroid Build Coastguard Worker
171*d83cc019SAndroid Build Coastguard Worker if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &arg))
172*d83cc019SAndroid Build Coastguard Worker return NULL;
173*d83cc019SAndroid Build Coastguard Worker
174*d83cc019SAndroid Build Coastguard Worker VG(VALGRIND_MAKE_MEM_DEFINED(from_user_pointer(arg.addr_ptr), arg.size));
175*d83cc019SAndroid Build Coastguard Worker
176*d83cc019SAndroid Build Coastguard Worker errno = 0;
177*d83cc019SAndroid Build Coastguard Worker return from_user_pointer(arg.addr_ptr);
178*d83cc019SAndroid Build Coastguard Worker }
179*d83cc019SAndroid Build Coastguard Worker
180*d83cc019SAndroid Build Coastguard Worker /**
181*d83cc019SAndroid Build Coastguard Worker * __gem_mmap__wc:
182*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
183*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
184*d83cc019SAndroid Build Coastguard Worker * @offset: offset in the gem buffer of the mmap arena
185*d83cc019SAndroid Build Coastguard Worker * @size: size of the mmap arena
186*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
187*d83cc019SAndroid Build Coastguard Worker *
188*d83cc019SAndroid Build Coastguard Worker * This functions wraps up procedure to establish a memory mapping through
189*d83cc019SAndroid Build Coastguard Worker * direct cpu access, bypassing the gpu and cpu caches completely and also
190*d83cc019SAndroid Build Coastguard Worker * bypassing the GTT system agent (i.e. there is no automatic tiling of
191*d83cc019SAndroid Build Coastguard Worker * the mmapping through the fence registers).
192*d83cc019SAndroid Build Coastguard Worker *
193*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping, NULL on failure.
194*d83cc019SAndroid Build Coastguard Worker */
__gem_mmap__wc(int fd,uint32_t handle,uint64_t offset,uint64_t size,unsigned prot)195*d83cc019SAndroid Build Coastguard Worker void *__gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
196*d83cc019SAndroid Build Coastguard Worker {
197*d83cc019SAndroid Build Coastguard Worker return __gem_mmap(fd, handle, offset, size, prot, I915_MMAP_WC);
198*d83cc019SAndroid Build Coastguard Worker }
199*d83cc019SAndroid Build Coastguard Worker
200*d83cc019SAndroid Build Coastguard Worker /**
201*d83cc019SAndroid Build Coastguard Worker * gem_mmap__wc:
202*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
203*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
204*d83cc019SAndroid Build Coastguard Worker * @offset: offset in the gem buffer of the mmap arena
205*d83cc019SAndroid Build Coastguard Worker * @size: size of the mmap arena
206*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
207*d83cc019SAndroid Build Coastguard Worker *
208*d83cc019SAndroid Build Coastguard Worker * Like __gem_mmap__wc() except we assert on failure.
209*d83cc019SAndroid Build Coastguard Worker *
210*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping
211*d83cc019SAndroid Build Coastguard Worker */
gem_mmap__wc(int fd,uint32_t handle,uint64_t offset,uint64_t size,unsigned prot)212*d83cc019SAndroid Build Coastguard Worker void *gem_mmap__wc(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
213*d83cc019SAndroid Build Coastguard Worker {
214*d83cc019SAndroid Build Coastguard Worker void *ptr = __gem_mmap__wc(fd, handle, offset, size, prot);
215*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr);
216*d83cc019SAndroid Build Coastguard Worker return ptr;
217*d83cc019SAndroid Build Coastguard Worker }
218*d83cc019SAndroid Build Coastguard Worker
219*d83cc019SAndroid Build Coastguard Worker /**
220*d83cc019SAndroid Build Coastguard Worker * __gem_mmap__cpu:
221*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
222*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
223*d83cc019SAndroid Build Coastguard Worker * @offset: offset in the gem buffer of the mmap arena
224*d83cc019SAndroid Build Coastguard Worker * @size: size of the mmap arena
225*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
226*d83cc019SAndroid Build Coastguard Worker *
227*d83cc019SAndroid Build Coastguard Worker * This functions wraps up procedure to establish a memory mapping through
228*d83cc019SAndroid Build Coastguard Worker * direct cpu access, bypassing the gpu completely.
229*d83cc019SAndroid Build Coastguard Worker *
230*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping, NULL on failure.
231*d83cc019SAndroid Build Coastguard Worker */
__gem_mmap__cpu(int fd,uint32_t handle,uint64_t offset,uint64_t size,unsigned prot)232*d83cc019SAndroid Build Coastguard Worker void *__gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
233*d83cc019SAndroid Build Coastguard Worker {
234*d83cc019SAndroid Build Coastguard Worker return __gem_mmap(fd, handle, offset, size, prot, 0);
235*d83cc019SAndroid Build Coastguard Worker }
236*d83cc019SAndroid Build Coastguard Worker
237*d83cc019SAndroid Build Coastguard Worker /**
238*d83cc019SAndroid Build Coastguard Worker * gem_mmap__cpu:
239*d83cc019SAndroid Build Coastguard Worker * @fd: open i915 drm file descriptor
240*d83cc019SAndroid Build Coastguard Worker * @handle: gem buffer object handle
241*d83cc019SAndroid Build Coastguard Worker * @offset: offset in the gem buffer of the mmap arena
242*d83cc019SAndroid Build Coastguard Worker * @size: size of the mmap arena
243*d83cc019SAndroid Build Coastguard Worker * @prot: memory protection bits as used by mmap()
244*d83cc019SAndroid Build Coastguard Worker *
245*d83cc019SAndroid Build Coastguard Worker * Like __gem_mmap__cpu() except we assert on failure.
246*d83cc019SAndroid Build Coastguard Worker *
247*d83cc019SAndroid Build Coastguard Worker * Returns: A pointer to the created memory mapping
248*d83cc019SAndroid Build Coastguard Worker */
gem_mmap__cpu(int fd,uint32_t handle,uint64_t offset,uint64_t size,unsigned prot)249*d83cc019SAndroid Build Coastguard Worker void *gem_mmap__cpu(int fd, uint32_t handle, uint64_t offset, uint64_t size, unsigned prot)
250*d83cc019SAndroid Build Coastguard Worker {
251*d83cc019SAndroid Build Coastguard Worker void *ptr = __gem_mmap__cpu(fd, handle, offset, size, prot);
252*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr);
253*d83cc019SAndroid Build Coastguard Worker return ptr;
254*d83cc019SAndroid Build Coastguard Worker }
255