110be98a7SChris Wilson /* 210be98a7SChris Wilson * SPDX-License-Identifier: MIT 310be98a7SChris Wilson * 410be98a7SChris Wilson * Copyright © 2016 Intel Corporation 510be98a7SChris Wilson */ 610be98a7SChris Wilson 737d63f8fSChris Wilson #include "i915_drv.h" 810be98a7SChris Wilson #include "i915_selftest.h" 910be98a7SChris Wilson 1010be98a7SChris Wilson #include "mock_dmabuf.h" 1110be98a7SChris Wilson #include "selftests/mock_gem_device.h" 1210be98a7SChris Wilson 1310be98a7SChris Wilson static int igt_dmabuf_export(void *arg) 1410be98a7SChris Wilson { 1510be98a7SChris Wilson struct drm_i915_private *i915 = arg; 1610be98a7SChris Wilson struct drm_i915_gem_object *obj; 1710be98a7SChris Wilson struct dma_buf *dmabuf; 1810be98a7SChris Wilson 1910be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 2010be98a7SChris Wilson if (IS_ERR(obj)) 2110be98a7SChris Wilson return PTR_ERR(obj); 2210be98a7SChris Wilson 2310be98a7SChris Wilson dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 2410be98a7SChris Wilson i915_gem_object_put(obj); 2510be98a7SChris Wilson if (IS_ERR(dmabuf)) { 2610be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 2710be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 2810be98a7SChris Wilson return PTR_ERR(dmabuf); 2910be98a7SChris Wilson } 3010be98a7SChris Wilson 3110be98a7SChris Wilson dma_buf_put(dmabuf); 3210be98a7SChris Wilson return 0; 3310be98a7SChris Wilson } 3410be98a7SChris Wilson 3510be98a7SChris Wilson static int igt_dmabuf_import_self(void *arg) 3610be98a7SChris Wilson { 3710be98a7SChris Wilson struct drm_i915_private *i915 = arg; 3810be98a7SChris Wilson struct drm_i915_gem_object *obj; 3910be98a7SChris Wilson struct drm_gem_object *import; 4010be98a7SChris Wilson struct dma_buf *dmabuf; 4110be98a7SChris Wilson int err; 4210be98a7SChris Wilson 4310be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 4410be98a7SChris Wilson if (IS_ERR(obj)) 4510be98a7SChris Wilson return PTR_ERR(obj); 4610be98a7SChris Wilson 4710be98a7SChris Wilson dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 4810be98a7SChris Wilson if (IS_ERR(dmabuf)) { 4910be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 5010be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 5110be98a7SChris Wilson err = PTR_ERR(dmabuf); 5210be98a7SChris Wilson goto out; 5310be98a7SChris Wilson } 5410be98a7SChris Wilson 5510be98a7SChris Wilson import = i915_gem_prime_import(&i915->drm, dmabuf); 5610be98a7SChris Wilson if (IS_ERR(import)) { 5710be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 5810be98a7SChris Wilson (int)PTR_ERR(import)); 5910be98a7SChris Wilson err = PTR_ERR(import); 6010be98a7SChris Wilson goto out_dmabuf; 6110be98a7SChris Wilson } 6210be98a7SChris Wilson 6310be98a7SChris Wilson if (import != &obj->base) { 6410be98a7SChris Wilson pr_err("i915_gem_prime_import created a new object!\n"); 6510be98a7SChris Wilson err = -EINVAL; 6610be98a7SChris Wilson goto out_import; 6710be98a7SChris Wilson } 6810be98a7SChris Wilson 6910be98a7SChris Wilson err = 0; 7010be98a7SChris Wilson out_import: 7110be98a7SChris Wilson i915_gem_object_put(to_intel_bo(import)); 7210be98a7SChris Wilson out_dmabuf: 7310be98a7SChris Wilson dma_buf_put(dmabuf); 7410be98a7SChris Wilson out: 7510be98a7SChris Wilson i915_gem_object_put(obj); 7610be98a7SChris Wilson return err; 7710be98a7SChris Wilson } 7810be98a7SChris Wilson 7910be98a7SChris Wilson static int igt_dmabuf_import(void *arg) 8010be98a7SChris Wilson { 8110be98a7SChris Wilson struct drm_i915_private *i915 = arg; 8210be98a7SChris Wilson struct drm_i915_gem_object *obj; 8310be98a7SChris Wilson struct dma_buf *dmabuf; 8410be98a7SChris Wilson void *obj_map, *dma_map; 8510be98a7SChris Wilson u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff }; 8610be98a7SChris Wilson int err, i; 8710be98a7SChris Wilson 8810be98a7SChris Wilson dmabuf = mock_dmabuf(1); 8910be98a7SChris Wilson if (IS_ERR(dmabuf)) 9010be98a7SChris Wilson return PTR_ERR(dmabuf); 9110be98a7SChris Wilson 9210be98a7SChris Wilson obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 9310be98a7SChris Wilson if (IS_ERR(obj)) { 9410be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 9510be98a7SChris Wilson (int)PTR_ERR(obj)); 9610be98a7SChris Wilson err = PTR_ERR(obj); 9710be98a7SChris Wilson goto out_dmabuf; 9810be98a7SChris Wilson } 9910be98a7SChris Wilson 10010be98a7SChris Wilson if (obj->base.dev != &i915->drm) { 10110be98a7SChris Wilson pr_err("i915_gem_prime_import created a non-i915 object!\n"); 10210be98a7SChris Wilson err = -EINVAL; 10310be98a7SChris Wilson goto out_obj; 10410be98a7SChris Wilson } 10510be98a7SChris Wilson 10610be98a7SChris Wilson if (obj->base.size != PAGE_SIZE) { 10710be98a7SChris Wilson pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n", 10810be98a7SChris Wilson (long long)obj->base.size, PAGE_SIZE); 10910be98a7SChris Wilson err = -EINVAL; 11010be98a7SChris Wilson goto out_obj; 11110be98a7SChris Wilson } 11210be98a7SChris Wilson 11310be98a7SChris Wilson dma_map = dma_buf_vmap(dmabuf); 11410be98a7SChris Wilson if (!dma_map) { 11510be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 11610be98a7SChris Wilson err = -ENOMEM; 11710be98a7SChris Wilson goto out_obj; 11810be98a7SChris Wilson } 11910be98a7SChris Wilson 12010be98a7SChris Wilson if (0) { /* Can not yet map dmabuf */ 12110be98a7SChris Wilson obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB); 12210be98a7SChris Wilson if (IS_ERR(obj_map)) { 12310be98a7SChris Wilson err = PTR_ERR(obj_map); 12410be98a7SChris Wilson pr_err("i915_gem_object_pin_map failed with err=%d\n", err); 12510be98a7SChris Wilson goto out_dma_map; 12610be98a7SChris Wilson } 12710be98a7SChris Wilson 12810be98a7SChris Wilson for (i = 0; i < ARRAY_SIZE(pattern); i++) { 12910be98a7SChris Wilson memset(dma_map, pattern[i], PAGE_SIZE); 13010be98a7SChris Wilson if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) { 13110be98a7SChris Wilson err = -EINVAL; 13210be98a7SChris Wilson pr_err("imported vmap not all set to %x!\n", pattern[i]); 13310be98a7SChris Wilson i915_gem_object_unpin_map(obj); 13410be98a7SChris Wilson goto out_dma_map; 13510be98a7SChris Wilson } 13610be98a7SChris Wilson } 13710be98a7SChris Wilson 13810be98a7SChris Wilson for (i = 0; i < ARRAY_SIZE(pattern); i++) { 13910be98a7SChris Wilson memset(obj_map, pattern[i], PAGE_SIZE); 14010be98a7SChris Wilson if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) { 14110be98a7SChris Wilson err = -EINVAL; 14210be98a7SChris Wilson pr_err("exported vmap not all set to %x!\n", pattern[i]); 14310be98a7SChris Wilson i915_gem_object_unpin_map(obj); 14410be98a7SChris Wilson goto out_dma_map; 14510be98a7SChris Wilson } 14610be98a7SChris Wilson } 14710be98a7SChris Wilson 14810be98a7SChris Wilson i915_gem_object_unpin_map(obj); 14910be98a7SChris Wilson } 15010be98a7SChris Wilson 15110be98a7SChris Wilson err = 0; 15210be98a7SChris Wilson out_dma_map: 15310be98a7SChris Wilson dma_buf_vunmap(dmabuf, dma_map); 15410be98a7SChris Wilson out_obj: 15510be98a7SChris Wilson i915_gem_object_put(obj); 15610be98a7SChris Wilson out_dmabuf: 15710be98a7SChris Wilson dma_buf_put(dmabuf); 15810be98a7SChris Wilson return err; 15910be98a7SChris Wilson } 16010be98a7SChris Wilson 16110be98a7SChris Wilson static int igt_dmabuf_import_ownership(void *arg) 16210be98a7SChris Wilson { 16310be98a7SChris Wilson struct drm_i915_private *i915 = arg; 16410be98a7SChris Wilson struct drm_i915_gem_object *obj; 16510be98a7SChris Wilson struct dma_buf *dmabuf; 16610be98a7SChris Wilson void *ptr; 16710be98a7SChris Wilson int err; 16810be98a7SChris Wilson 16910be98a7SChris Wilson dmabuf = mock_dmabuf(1); 17010be98a7SChris Wilson if (IS_ERR(dmabuf)) 17110be98a7SChris Wilson return PTR_ERR(dmabuf); 17210be98a7SChris Wilson 17310be98a7SChris Wilson ptr = dma_buf_vmap(dmabuf); 17410be98a7SChris Wilson if (!ptr) { 17510be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 17610be98a7SChris Wilson err = -ENOMEM; 17710be98a7SChris Wilson goto err_dmabuf; 17810be98a7SChris Wilson } 17910be98a7SChris Wilson 18010be98a7SChris Wilson memset(ptr, 0xc5, PAGE_SIZE); 18110be98a7SChris Wilson dma_buf_vunmap(dmabuf, ptr); 18210be98a7SChris Wilson 18310be98a7SChris Wilson obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf)); 18410be98a7SChris Wilson if (IS_ERR(obj)) { 18510be98a7SChris Wilson pr_err("i915_gem_prime_import failed with err=%d\n", 18610be98a7SChris Wilson (int)PTR_ERR(obj)); 18710be98a7SChris Wilson err = PTR_ERR(obj); 18810be98a7SChris Wilson goto err_dmabuf; 18910be98a7SChris Wilson } 19010be98a7SChris Wilson 19110be98a7SChris Wilson dma_buf_put(dmabuf); 19210be98a7SChris Wilson 19310be98a7SChris Wilson err = i915_gem_object_pin_pages(obj); 19410be98a7SChris Wilson if (err) { 19510be98a7SChris Wilson pr_err("i915_gem_object_pin_pages failed with err=%d\n", err); 19610be98a7SChris Wilson goto out_obj; 19710be98a7SChris Wilson } 19810be98a7SChris Wilson 19910be98a7SChris Wilson err = 0; 20010be98a7SChris Wilson i915_gem_object_unpin_pages(obj); 20110be98a7SChris Wilson out_obj: 20210be98a7SChris Wilson i915_gem_object_put(obj); 20310be98a7SChris Wilson return err; 20410be98a7SChris Wilson 20510be98a7SChris Wilson err_dmabuf: 20610be98a7SChris Wilson dma_buf_put(dmabuf); 20710be98a7SChris Wilson return err; 20810be98a7SChris Wilson } 20910be98a7SChris Wilson 21010be98a7SChris Wilson static int igt_dmabuf_export_vmap(void *arg) 21110be98a7SChris Wilson { 21210be98a7SChris Wilson struct drm_i915_private *i915 = arg; 21310be98a7SChris Wilson struct drm_i915_gem_object *obj; 21410be98a7SChris Wilson struct dma_buf *dmabuf; 21510be98a7SChris Wilson void *ptr; 21610be98a7SChris Wilson int err; 21710be98a7SChris Wilson 21810be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, PAGE_SIZE); 21910be98a7SChris Wilson if (IS_ERR(obj)) 22010be98a7SChris Wilson return PTR_ERR(obj); 22110be98a7SChris Wilson 22210be98a7SChris Wilson dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 22310be98a7SChris Wilson if (IS_ERR(dmabuf)) { 22410be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", 22510be98a7SChris Wilson (int)PTR_ERR(dmabuf)); 22610be98a7SChris Wilson err = PTR_ERR(dmabuf); 22710be98a7SChris Wilson goto err_obj; 22810be98a7SChris Wilson } 22910be98a7SChris Wilson i915_gem_object_put(obj); 23010be98a7SChris Wilson 23110be98a7SChris Wilson ptr = dma_buf_vmap(dmabuf); 23210be98a7SChris Wilson if (!ptr) { 23310be98a7SChris Wilson pr_err("dma_buf_vmap failed\n"); 23410be98a7SChris Wilson err = -ENOMEM; 23510be98a7SChris Wilson goto out; 23610be98a7SChris Wilson } 23710be98a7SChris Wilson 23810be98a7SChris Wilson if (memchr_inv(ptr, 0, dmabuf->size)) { 23910be98a7SChris Wilson pr_err("Exported object not initialiased to zero!\n"); 24010be98a7SChris Wilson err = -EINVAL; 24110be98a7SChris Wilson goto out; 24210be98a7SChris Wilson } 24310be98a7SChris Wilson 24410be98a7SChris Wilson memset(ptr, 0xc5, dmabuf->size); 24510be98a7SChris Wilson 24610be98a7SChris Wilson err = 0; 24710be98a7SChris Wilson dma_buf_vunmap(dmabuf, ptr); 24810be98a7SChris Wilson out: 24910be98a7SChris Wilson dma_buf_put(dmabuf); 25010be98a7SChris Wilson return err; 25110be98a7SChris Wilson 25210be98a7SChris Wilson err_obj: 25310be98a7SChris Wilson i915_gem_object_put(obj); 25410be98a7SChris Wilson return err; 25510be98a7SChris Wilson } 25610be98a7SChris Wilson 25710be98a7SChris Wilson static int igt_dmabuf_export_kmap(void *arg) 25810be98a7SChris Wilson { 25910be98a7SChris Wilson struct drm_i915_private *i915 = arg; 26010be98a7SChris Wilson struct drm_i915_gem_object *obj; 26110be98a7SChris Wilson struct dma_buf *dmabuf; 26210be98a7SChris Wilson void *ptr; 26310be98a7SChris Wilson int err; 26410be98a7SChris Wilson 26510be98a7SChris Wilson obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE); 26610be98a7SChris Wilson if (IS_ERR(obj)) 26710be98a7SChris Wilson return PTR_ERR(obj); 26810be98a7SChris Wilson 26910be98a7SChris Wilson dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); 27010be98a7SChris Wilson i915_gem_object_put(obj); 27110be98a7SChris Wilson if (IS_ERR(dmabuf)) { 27210be98a7SChris Wilson err = PTR_ERR(dmabuf); 27310be98a7SChris Wilson pr_err("i915_gem_prime_export failed with err=%d\n", err); 27410be98a7SChris Wilson return err; 27510be98a7SChris Wilson } 27610be98a7SChris Wilson 27710be98a7SChris Wilson ptr = dma_buf_kmap(dmabuf, 0); 27810be98a7SChris Wilson if (!ptr) { 27910be98a7SChris Wilson pr_err("dma_buf_kmap failed\n"); 28010be98a7SChris Wilson err = -ENOMEM; 28110be98a7SChris Wilson goto err; 28210be98a7SChris Wilson } 28310be98a7SChris Wilson 28410be98a7SChris Wilson if (memchr_inv(ptr, 0, PAGE_SIZE)) { 28510be98a7SChris Wilson dma_buf_kunmap(dmabuf, 0, ptr); 28610be98a7SChris Wilson pr_err("Exported page[0] not initialiased to zero!\n"); 28710be98a7SChris Wilson err = -EINVAL; 28810be98a7SChris Wilson goto err; 28910be98a7SChris Wilson } 29010be98a7SChris Wilson 29110be98a7SChris Wilson memset(ptr, 0xc5, PAGE_SIZE); 29210be98a7SChris Wilson dma_buf_kunmap(dmabuf, 0, ptr); 29310be98a7SChris Wilson 29410be98a7SChris Wilson ptr = i915_gem_object_pin_map(obj, I915_MAP_WB); 29510be98a7SChris Wilson if (IS_ERR(ptr)) { 29610be98a7SChris Wilson err = PTR_ERR(ptr); 29710be98a7SChris Wilson pr_err("i915_gem_object_pin_map failed with err=%d\n", err); 29810be98a7SChris Wilson goto err; 29910be98a7SChris Wilson } 30010be98a7SChris Wilson memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE); 30110be98a7SChris Wilson i915_gem_object_flush_map(obj); 30210be98a7SChris Wilson i915_gem_object_unpin_map(obj); 30310be98a7SChris Wilson 30410be98a7SChris Wilson ptr = dma_buf_kmap(dmabuf, 1); 30510be98a7SChris Wilson if (!ptr) { 30610be98a7SChris Wilson pr_err("dma_buf_kmap failed\n"); 30710be98a7SChris Wilson err = -ENOMEM; 30810be98a7SChris Wilson goto err; 30910be98a7SChris Wilson } 31010be98a7SChris Wilson 31110be98a7SChris Wilson if (memchr_inv(ptr, 0xaa, PAGE_SIZE)) { 31210be98a7SChris Wilson dma_buf_kunmap(dmabuf, 1, ptr); 31310be98a7SChris Wilson pr_err("Exported page[1] not set to 0xaa!\n"); 31410be98a7SChris Wilson err = -EINVAL; 31510be98a7SChris Wilson goto err; 31610be98a7SChris Wilson } 31710be98a7SChris Wilson 31810be98a7SChris Wilson memset(ptr, 0xc5, PAGE_SIZE); 31910be98a7SChris Wilson dma_buf_kunmap(dmabuf, 1, ptr); 32010be98a7SChris Wilson 32110be98a7SChris Wilson ptr = dma_buf_kmap(dmabuf, 0); 32210be98a7SChris Wilson if (!ptr) { 32310be98a7SChris Wilson pr_err("dma_buf_kmap failed\n"); 32410be98a7SChris Wilson err = -ENOMEM; 32510be98a7SChris Wilson goto err; 32610be98a7SChris Wilson } 32710be98a7SChris Wilson if (memchr_inv(ptr, 0xc5, PAGE_SIZE)) { 32810be98a7SChris Wilson dma_buf_kunmap(dmabuf, 0, ptr); 32910be98a7SChris Wilson pr_err("Exported page[0] did not retain 0xc5!\n"); 33010be98a7SChris Wilson err = -EINVAL; 33110be98a7SChris Wilson goto err; 33210be98a7SChris Wilson } 33310be98a7SChris Wilson dma_buf_kunmap(dmabuf, 0, ptr); 33410be98a7SChris Wilson 33510be98a7SChris Wilson ptr = dma_buf_kmap(dmabuf, 2); 33610be98a7SChris Wilson if (ptr) { 33710be98a7SChris Wilson pr_err("Erroneously kmapped beyond the end of the object!\n"); 33810be98a7SChris Wilson dma_buf_kunmap(dmabuf, 2, ptr); 33910be98a7SChris Wilson err = -EINVAL; 34010be98a7SChris Wilson goto err; 34110be98a7SChris Wilson } 34210be98a7SChris Wilson 34310be98a7SChris Wilson ptr = dma_buf_kmap(dmabuf, -1); 34410be98a7SChris Wilson if (ptr) { 34510be98a7SChris Wilson pr_err("Erroneously kmapped before the start of the object!\n"); 34610be98a7SChris Wilson dma_buf_kunmap(dmabuf, -1, ptr); 34710be98a7SChris Wilson err = -EINVAL; 34810be98a7SChris Wilson goto err; 34910be98a7SChris Wilson } 35010be98a7SChris Wilson 35110be98a7SChris Wilson err = 0; 35210be98a7SChris Wilson err: 35310be98a7SChris Wilson dma_buf_put(dmabuf); 35410be98a7SChris Wilson return err; 35510be98a7SChris Wilson } 35610be98a7SChris Wilson 35710be98a7SChris Wilson int i915_gem_dmabuf_mock_selftests(void) 35810be98a7SChris Wilson { 35910be98a7SChris Wilson static const struct i915_subtest tests[] = { 36010be98a7SChris Wilson SUBTEST(igt_dmabuf_export), 36110be98a7SChris Wilson SUBTEST(igt_dmabuf_import_self), 36210be98a7SChris Wilson SUBTEST(igt_dmabuf_import), 36310be98a7SChris Wilson SUBTEST(igt_dmabuf_import_ownership), 36410be98a7SChris Wilson SUBTEST(igt_dmabuf_export_vmap), 36510be98a7SChris Wilson SUBTEST(igt_dmabuf_export_kmap), 36610be98a7SChris Wilson }; 36710be98a7SChris Wilson struct drm_i915_private *i915; 36810be98a7SChris Wilson int err; 36910be98a7SChris Wilson 37010be98a7SChris Wilson i915 = mock_gem_device(); 37110be98a7SChris Wilson if (!i915) 37210be98a7SChris Wilson return -ENOMEM; 37310be98a7SChris Wilson 37410be98a7SChris Wilson err = i915_subtests(tests, i915); 37510be98a7SChris Wilson 37610be98a7SChris Wilson drm_dev_put(&i915->drm); 37710be98a7SChris Wilson return err; 37810be98a7SChris Wilson } 37910be98a7SChris Wilson 38010be98a7SChris Wilson int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915) 38110be98a7SChris Wilson { 38210be98a7SChris Wilson static const struct i915_subtest tests[] = { 38310be98a7SChris Wilson SUBTEST(igt_dmabuf_export), 38410be98a7SChris Wilson }; 38510be98a7SChris Wilson 38610be98a7SChris Wilson return i915_subtests(tests, i915); 38710be98a7SChris Wilson } 388