1/*
2 * Copyright 2014 Advanced Micro Devices, Inc.
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22*/
23
24#include <stdio.h>
25
26#include "CUnit/Basic.h"
27
28#include "amdgpu_test.h"
29#include "amdgpu_drm.h"
30#include "amdgpu_internal.h"
31
32#define BUFFER_SIZE (4*1024)
33#define BUFFER_ALIGN (4*1024)
34
35static amdgpu_device_handle device_handle;
36static uint32_t major_version;
37static uint32_t minor_version;
38
39static amdgpu_bo_handle buffer_handle;
40static uint64_t virtual_mc_base_address;
41static amdgpu_va_handle va_handle;
42
43static void amdgpu_bo_export_import(void);
44static void amdgpu_bo_metadata(void);
45static void amdgpu_bo_map_unmap(void);
46static void amdgpu_memory_alloc(void);
47static void amdgpu_mem_fail_alloc(void);
48static void amdgpu_bo_find_by_cpu_mapping(void);
49
50CU_TestInfo bo_tests[] = {
51	{ "Export/Import",  amdgpu_bo_export_import },
52	{ "Metadata",  amdgpu_bo_metadata },
53	{ "CPU map/unmap",  amdgpu_bo_map_unmap },
54	{ "Memory alloc Test",  amdgpu_memory_alloc },
55	{ "Memory fail alloc Test",  amdgpu_mem_fail_alloc },
56	{ "Find bo by CPU mapping",  amdgpu_bo_find_by_cpu_mapping },
57	CU_TEST_INFO_NULL,
58};
59
60int suite_bo_tests_init(void)
61{
62	struct amdgpu_bo_alloc_request req = {0};
63	amdgpu_bo_handle buf_handle;
64	uint64_t va;
65	int r;
66
67	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
68				  &minor_version, &device_handle);
69	if (r) {
70		if ((r == -EACCES) && (errno == EACCES))
71			printf("\n\nError:%s. "
72				"Hint:Try to run this test program as root.",
73				strerror(errno));
74
75		return CUE_SINIT_FAILED;
76	}
77
78	req.alloc_size = BUFFER_SIZE;
79	req.phys_alignment = BUFFER_ALIGN;
80	req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
81
82	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
83	if (r)
84		return CUE_SINIT_FAILED;
85
86	r = amdgpu_va_range_alloc(device_handle,
87				  amdgpu_gpu_va_range_general,
88				  BUFFER_SIZE, BUFFER_ALIGN, 0,
89				  &va, &va_handle, 0);
90	if (r)
91		goto error_va_alloc;
92
93	r = amdgpu_bo_va_op(buf_handle, 0, BUFFER_SIZE, va, 0, AMDGPU_VA_OP_MAP);
94	if (r)
95		goto error_va_map;
96
97	buffer_handle = buf_handle;
98	virtual_mc_base_address = va;
99
100	return CUE_SUCCESS;
101
102error_va_map:
103	amdgpu_va_range_free(va_handle);
104
105error_va_alloc:
106	amdgpu_bo_free(buf_handle);
107	return CUE_SINIT_FAILED;
108}
109
110int suite_bo_tests_clean(void)
111{
112	int r;
113
114	r = amdgpu_bo_va_op(buffer_handle, 0, BUFFER_SIZE,
115			    virtual_mc_base_address, 0,
116			    AMDGPU_VA_OP_UNMAP);
117	if (r)
118		return CUE_SCLEAN_FAILED;
119
120	r = amdgpu_va_range_free(va_handle);
121	if (r)
122		return CUE_SCLEAN_FAILED;
123
124	r = amdgpu_bo_free(buffer_handle);
125	if (r)
126		return CUE_SCLEAN_FAILED;
127
128	r = amdgpu_device_deinitialize(device_handle);
129	if (r)
130		return CUE_SCLEAN_FAILED;
131
132	return CUE_SUCCESS;
133}
134
135static void amdgpu_bo_export_import_do_type(enum amdgpu_bo_handle_type type)
136{
137	struct amdgpu_bo_import_result res = {0};
138	uint32_t shared_handle;
139	int r;
140
141	r = amdgpu_bo_export(buffer_handle, type, &shared_handle);
142	CU_ASSERT_EQUAL(r, 0);
143
144	r = amdgpu_bo_import(device_handle, type, shared_handle, &res);
145	CU_ASSERT_EQUAL(r, 0);
146
147	CU_ASSERT_EQUAL(res.buf_handle, buffer_handle);
148	CU_ASSERT_EQUAL(res.alloc_size, BUFFER_SIZE);
149
150	r = amdgpu_bo_free(res.buf_handle);
151	CU_ASSERT_EQUAL(r, 0);
152}
153
154static void amdgpu_bo_export_import(void)
155{
156	if (open_render_node) {
157		printf("(DRM render node is used. Skip export/Import test) ");
158		return;
159	}
160
161	amdgpu_bo_export_import_do_type(amdgpu_bo_handle_type_gem_flink_name);
162	amdgpu_bo_export_import_do_type(amdgpu_bo_handle_type_dma_buf_fd);
163}
164
165static void amdgpu_bo_metadata(void)
166{
167	struct amdgpu_bo_metadata meta = {0};
168	struct amdgpu_bo_info info = {0};
169	int r;
170
171	meta.size_metadata = 4;
172	meta.umd_metadata[0] = 0xdeadbeef;
173
174	r = amdgpu_bo_set_metadata(buffer_handle, &meta);
175	CU_ASSERT_EQUAL(r, 0);
176
177	r = amdgpu_bo_query_info(buffer_handle, &info);
178	CU_ASSERT_EQUAL(r, 0);
179
180	CU_ASSERT_EQUAL(info.metadata.size_metadata, 4);
181	CU_ASSERT_EQUAL(info.metadata.umd_metadata[0], 0xdeadbeef);
182}
183
184static void amdgpu_bo_map_unmap(void)
185{
186	uint32_t *ptr;
187	int i, r;
188
189	r = amdgpu_bo_cpu_map(buffer_handle, (void **)&ptr);
190	CU_ASSERT_EQUAL(r, 0);
191	CU_ASSERT_NOT_EQUAL(ptr, NULL);
192
193	for (i = 0; i < (BUFFER_SIZE / 4); ++i)
194		ptr[i] = 0xdeadbeef;
195
196	r = amdgpu_bo_cpu_unmap(buffer_handle);
197	CU_ASSERT_EQUAL(r, 0);
198}
199
200static void amdgpu_memory_alloc(void)
201{
202	amdgpu_bo_handle bo;
203	amdgpu_va_handle va_handle;
204	uint64_t bo_mc;
205	int r;
206
207	/* Test visible VRAM */
208	bo = gpu_mem_alloc(device_handle,
209			4096, 4096,
210			AMDGPU_GEM_DOMAIN_VRAM,
211			AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
212			&bo_mc, &va_handle);
213
214	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
215	CU_ASSERT_EQUAL(r, 0);
216
217	/* Test invisible VRAM */
218	bo = gpu_mem_alloc(device_handle,
219			4096, 4096,
220			AMDGPU_GEM_DOMAIN_VRAM,
221			AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
222			&bo_mc, &va_handle);
223
224	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
225	CU_ASSERT_EQUAL(r, 0);
226
227	/* Test GART Cacheable */
228	bo = gpu_mem_alloc(device_handle,
229			4096, 4096,
230			AMDGPU_GEM_DOMAIN_GTT,
231			0, &bo_mc, &va_handle);
232
233	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
234	CU_ASSERT_EQUAL(r, 0);
235
236	/* Test GART USWC */
237	bo = gpu_mem_alloc(device_handle,
238			4096, 4096,
239			AMDGPU_GEM_DOMAIN_GTT,
240			AMDGPU_GEM_CREATE_CPU_GTT_USWC,
241			&bo_mc, &va_handle);
242
243	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
244	CU_ASSERT_EQUAL(r, 0);
245
246	/* Test GDS */
247	bo = gpu_mem_alloc(device_handle, 1024, 0,
248			AMDGPU_GEM_DOMAIN_GDS, 0,
249			NULL, NULL);
250	r = gpu_mem_free(bo, NULL, 0, 4096);
251	CU_ASSERT_EQUAL(r, 0);
252
253	/* Test GWS */
254	bo = gpu_mem_alloc(device_handle, 1, 0,
255			AMDGPU_GEM_DOMAIN_GWS, 0,
256			NULL, NULL);
257	r = gpu_mem_free(bo, NULL, 0, 4096);
258	CU_ASSERT_EQUAL(r, 0);
259
260	/* Test OA */
261	bo = gpu_mem_alloc(device_handle, 1, 0,
262			AMDGPU_GEM_DOMAIN_OA, 0,
263			NULL, NULL);
264	r = gpu_mem_free(bo, NULL, 0, 4096);
265	CU_ASSERT_EQUAL(r, 0);
266}
267
268static void amdgpu_mem_fail_alloc(void)
269{
270	int r;
271	struct amdgpu_bo_alloc_request req = {0};
272	amdgpu_bo_handle buf_handle;
273
274	/* Test impossible mem allocation, 1TB */
275	req.alloc_size = 0xE8D4A51000;
276	req.phys_alignment = 4096;
277	req.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM;
278	req.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
279
280	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
281	CU_ASSERT_EQUAL(r, -ENOMEM);
282
283	if (!r) {
284		r = amdgpu_bo_free(buf_handle);
285		CU_ASSERT_EQUAL(r, 0);
286	}
287}
288
289static void amdgpu_bo_find_by_cpu_mapping(void)
290{
291	amdgpu_bo_handle bo_handle, find_bo_handle;
292	amdgpu_va_handle va_handle;
293	void *bo_cpu;
294	uint64_t bo_mc_address;
295	uint64_t offset;
296	int r;
297
298	r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,
299				    AMDGPU_GEM_DOMAIN_GTT, 0,
300				    &bo_handle, &bo_cpu,
301				    &bo_mc_address, &va_handle);
302	CU_ASSERT_EQUAL(r, 0);
303
304	r = amdgpu_find_bo_by_cpu_mapping(device_handle,
305					  bo_cpu,
306					  4096,
307					  &find_bo_handle,
308					  &offset);
309	CU_ASSERT_EQUAL(r, 0);
310	CU_ASSERT_EQUAL(offset, 0);
311	CU_ASSERT_EQUAL(bo_handle->handle, find_bo_handle->handle);
312
313	atomic_dec(&find_bo_handle->refcount, 1);
314	r = amdgpu_bo_unmap_and_free(bo_handle, va_handle,
315				     bo_mc_address, 4096);
316	CU_ASSERT_EQUAL(r, 0);
317}
318