1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2016 Intel Corporation 5 */ 6 7 #include "i915_drv.h" 8 #include "i915_selftest.h" 9 10 #include "mock_dmabuf.h" 11 #include "selftests/mock_gem_device.h" 12 13 static int igt_dmabuf_export(void *arg) 14 { 15 struct drm_i915_private *i915 = arg; 16 struct drm_i915_gem_object *obj; 17 struct dma_buf *dmabuf; 18 19 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 20 if (IS_ERR(obj)) 21 return PTR_ERR(obj); 22 23 dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 24 i915_gem_object_put(obj); 25 if (IS_ERR(dmabuf)) { 26 pr_err("i915_gem_prime_export failed with err=%d\n", 27 (int)PTR_ERR(dmabuf)); 28 return PTR_ERR(dmabuf); 29 } 30 31 dma_buf_put(dmabuf); 32 return 0; 33 } 34 35 static int igt_dmabuf_import_self(void *arg) 36 { 37 struct drm_i915_private *i915 = arg; 38 struct drm_i915_gem_object *obj; 39 struct drm_gem_object *import; 40 struct dma_buf *dmabuf; 41 int err; 42 43 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 44 if (IS_ERR(obj)) 45 return PTR_ERR(obj); 46 47 dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 48 if (IS_ERR(dmabuf)) { 49 pr_err("i915_gem_prime_export failed with err=%d\n", 50 (int)PTR_ERR(dmabuf)); 51 err = PTR_ERR(dmabuf); 52 goto out; 53 } 54 55 import = i915_gem_prime_import(&i915->drm, dmabuf); 56 if (IS_ERR(import)) { 57 pr_err("i915_gem_prime_import failed with err=%d\n", 58 (int)PTR_ERR(import)); 59 err = PTR_ERR(import); 60 goto out_dmabuf; 61 } 62 63 if (import != &obj->base) { 64 pr_err("i915_gem_prime_import created a new object!\n"); 65 err = -EINVAL; 66 goto out_import; 67 } 68 69 err = 0; 70 out_import: 71 i915_gem_object_put(to_intel_bo(import)); 72 out_dmabuf: 73 dma_buf_put(dmabuf); 74 out: 75 i915_gem_object_put(obj); 76 return err; 77 } 78 79 static int igt_dmabuf_import(void *arg) 80 { 81 struct drm_i915_private *i915 = arg; 82 struct drm_i915_gem_object *obj; 83 struct dma_buf *dmabuf; 84 void *obj_map, *dma_map; 85 u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; 86 int err, i; 87 88 dmabuf = mock_dmabuf(1); 89 if (IS_ERR(dmabuf)) 90 return PTR_ERR(dmabuf); 91 92 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 93 if (IS_ERR(obj)) { 94 pr_err("i915_gem_prime_import failed with err=%d\n", 95 (int)PTR_ERR(obj)); 96 err = PTR_ERR(obj); 97 goto out_dmabuf; 98 } 99 100 if (obj->base.dev != &i915->drm) { 101 pr_err("i915_gem_prime_import created a non-i915 object!\n"); 102 err = -EINVAL; 103 goto out_obj; 104 } 105 106 if (obj->base.size != PAGE_SIZE) { 107 pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", 108 (long long)obj->base.size, PAGE_SIZE); 109 err = -EINVAL; 110 goto out_obj; 111 } 112 113 dma_map = dma_buf_vmap(dmabuf); 114 if (!dma_map) { 115 pr_err("dma_buf_vmap failed\n"); 116 err = -ENOMEM; 117 goto out_obj; 118 } 119 120 if (0) { /* Can not yet map dmabuf */ 121 obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); 122 if (IS_ERR(obj_map)) { 123 err = PTR_ERR(obj_map); 124 pr_err("i915_gem_object_pin_map failed with err=%d\n", err); 125 goto out_dma_map; 126 } 127 128 for (i = 0; i < ARRAY_SIZE(pattern); i++) { 129 memset(dma_map, pattern[i], PAGE_SIZE); 130 if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { 131 err = -EINVAL; 132 pr_err("imported vmap not all set to %x!\n", pattern[i]); 133 i915_gem_object_unpin_map(obj); 134 goto out_dma_map; 135 } 136 } 137 138 for (i = 0; i < ARRAY_SIZE(pattern); i++) { 139 memset(obj_map, pattern[i], PAGE_SIZE); 140 if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { 141 err = -EINVAL; 142 pr_err("exported vmap not all set to %x!\n", pattern[i]); 143 i915_gem_object_unpin_map(obj); 144 goto out_dma_map; 145 } 146 } 147 148 i915_gem_object_unpin_map(obj); 149 } 150 151 err = 0; 152 out_dma_map: 153 dma_buf_vunmap(dmabuf, dma_map); 154 out_obj: 155 i915_gem_object_put(obj); 156 out_dmabuf: 157 dma_buf_put(dmabuf); 158 return err; 159 } 160 161 static int igt_dmabuf_import_ownership(void *arg) 162 { 163 struct drm_i915_private *i915 = arg; 164 struct drm_i915_gem_object *obj; 165 struct dma_buf *dmabuf; 166 void *ptr; 167 int err; 168 169 dmabuf = mock_dmabuf(1); 170 if (IS_ERR(dmabuf)) 171 return PTR_ERR(dmabuf); 172 173 ptr = dma_buf_vmap(dmabuf); 174 if (!ptr) { 175 pr_err("dma_buf_vmap failed\n"); 176 err = -ENOMEM; 177 goto err_dmabuf; 178 } 179 180 memset(ptr, 0xc5, PAGE_SIZE); 181 dma_buf_vunmap(dmabuf, ptr); 182 183 obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 184 if (IS_ERR(obj)) { 185 pr_err("i915_gem_prime_import failed with err=%d\n", 186 (int)PTR_ERR(obj)); 187 err = PTR_ERR(obj); 188 goto err_dmabuf; 189 } 190 191 dma_buf_put(dmabuf); 192 193 err = i915_gem_object_pin_pages(obj); 194 if (err) { 195 pr_err("i915_gem_object_pin_pages failed with err=%d\n", err); 196 goto out_obj; 197 } 198 199 err = 0; 200 i915_gem_object_unpin_pages(obj); 201 out_obj: 202 i915_gem_object_put(obj); 203 return err; 204 205 err_dmabuf: 206 dma_buf_put(dmabuf); 207 return err; 208 } 209 210 static int igt_dmabuf_export_vmap(void *arg) 211 { 212 struct drm_i915_private *i915 = arg; 213 struct drm_i915_gem_object *obj; 214 struct dma_buf *dmabuf; 215 void *ptr; 216 int err; 217 218 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 219 if (IS_ERR(obj)) 220 return PTR_ERR(obj); 221 222 dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 223 if (IS_ERR(dmabuf)) { 224 pr_err("i915_gem_prime_export failed with err=%d\n", 225 (int)PTR_ERR(dmabuf)); 226 err = PTR_ERR(dmabuf); 227 goto err_obj; 228 } 229 i915_gem_object_put(obj); 230 231 ptr = dma_buf_vmap(dmabuf); 232 if (!ptr) { 233 pr_err("dma_buf_vmap failed\n"); 234 err = -ENOMEM; 235 goto out; 236 } 237 238 if (memchr_inv(ptr, 0, dmabuf->size)) { 239 pr_err("Exported object not initialiased to zero!\n"); 240 err = -EINVAL; 241 goto out; 242 } 243 244 memset(ptr, 0xc5, dmabuf->size); 245 246 err = 0; 247 dma_buf_vunmap(dmabuf, ptr); 248 out: 249 dma_buf_put(dmabuf); 250 return err; 251 252 err_obj: 253 i915_gem_object_put(obj); 254 return err; 255 } 256 257 static int igt_dmabuf_export_kmap(void *arg) 258 { 259 struct drm_i915_private *i915 = arg; 260 struct drm_i915_gem_object *obj; 261 struct dma_buf *dmabuf; 262 void *ptr; 263 int err; 264 265 obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE); 266 if (IS_ERR(obj)) 267 return PTR_ERR(obj); 268 269 dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 270 i915_gem_object_put(obj); 271 if (IS_ERR(dmabuf)) { 272 err = PTR_ERR(dmabuf); 273 pr_err("i915_gem_prime_export failed with err=%d\n", err); 274 return err; 275 } 276 277 ptr = dma_buf_kmap(dmabuf, 0); 278 if (!ptr) { 279 pr_err("dma_buf_kmap failed\n"); 280 err = -ENOMEM; 281 goto err; 282 } 283 284 if (memchr_inv(ptr, 0, PAGE_SIZE)) { 285 dma_buf_kunmap(dmabuf, 0, ptr); 286 pr_err("Exported page[0] not initialiased to zero!\n"); 287 err = -EINVAL; 288 goto err; 289 } 290 291 memset(ptr, 0xc5, PAGE_SIZE); 292 dma_buf_kunmap(dmabuf, 0, ptr); 293 294 ptr = i915_gem_object_pin_map(obj, I915_MAP_WB); 295 if (IS_ERR(ptr)) { 296 err = PTR_ERR(ptr); 297 pr_err("i915_gem_object_pin_map failed with err=%d\n", err); 298 goto err; 299 } 300 memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE); 301 i915_gem_object_flush_map(obj); 302 i915_gem_object_unpin_map(obj); 303 304 ptr = dma_buf_kmap(dmabuf, 1); 305 if (!ptr) { 306 pr_err("dma_buf_kmap failed\n"); 307 err = -ENOMEM; 308 goto err; 309 } 310 311 if (memchr_inv(ptr, 0xaa, PAGE_SIZE)) { 312 dma_buf_kunmap(dmabuf, 1, ptr); 313 pr_err("Exported page[1] not set to 0xaa!\n"); 314 err = -EINVAL; 315 goto err; 316 } 317 318 memset(ptr, 0xc5, PAGE_SIZE); 319 dma_buf_kunmap(dmabuf, 1, ptr); 320 321 ptr = dma_buf_kmap(dmabuf, 0); 322 if (!ptr) { 323 pr_err("dma_buf_kmap failed\n"); 324 err = -ENOMEM; 325 goto err; 326 } 327 if (memchr_inv(ptr, 0xc5, PAGE_SIZE)) { 328 dma_buf_kunmap(dmabuf, 0, ptr); 329 pr_err("Exported page[0] did not retain 0xc5!\n"); 330 err = -EINVAL; 331 goto err; 332 } 333 dma_buf_kunmap(dmabuf, 0, ptr); 334 335 ptr = dma_buf_kmap(dmabuf, 2); 336 if (ptr) { 337 pr_err("Erroneously kmapped beyond the end of the object!\n"); 338 dma_buf_kunmap(dmabuf, 2, ptr); 339 err = -EINVAL; 340 goto err; 341 } 342 343 ptr = dma_buf_kmap(dmabuf, -1); 344 if (ptr) { 345 pr_err("Erroneously kmapped before the start of the object!\n"); 346 dma_buf_kunmap(dmabuf, -1, ptr); 347 err = -EINVAL; 348 goto err; 349 } 350 351 err = 0; 352 err: 353 dma_buf_put(dmabuf); 354 return err; 355 } 356 357 int i915_gem_dmabuf_mock_selftests(void) 358 { 359 static const struct i915_subtest tests[] = { 360 SUBTEST(igt_dmabuf_export), 361 SUBTEST(igt_dmabuf_import_self), 362 SUBTEST(igt_dmabuf_import), 363 SUBTEST(igt_dmabuf_import_ownership), 364 SUBTEST(igt_dmabuf_export_vmap), 365 SUBTEST(igt_dmabuf_export_kmap), 366 }; 367 struct drm_i915_private *i915; 368 int err; 369 370 i915 = mock_gem_device(); 371 if (!i915) 372 return -ENOMEM; 373 374 err = i915_subtests(tests, i915); 375 376 drm_dev_put(&i915->drm); 377 return err; 378 } 379 380 int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915) 381 { 382 static const struct i915_subtest tests[] = { 383 SUBTEST(igt_dmabuf_export), 384 }; 385 386 return i915_subtests(tests, i915); 387 } 388