• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 "CUnit/Basic.h"
25 
26 #include "amdgpu_test.h"
27 #include "amdgpu_drm.h"
28 #include "amdgpu_internal.h"
29 
30 #include <string.h>
31 #include <unistd.h>
32 #ifdef __FreeBSD__
33 #include <sys/endian.h>
34 #else
35 #include <endian.h>
36 #endif
37 #include <strings.h>
38 #include <xf86drm.h>
39 
40 static amdgpu_device_handle device_handle;
41 static uint32_t major_version;
42 static uint32_t minor_version;
43 
44 static struct drm_amdgpu_info_hw_ip  sdma_info;
45 
46 #ifndef ARRAY_SIZE
47 #define ARRAY_SIZE(_Arr)  (sizeof(_Arr)/sizeof((_Arr)[0]))
48 #endif
49 
50 
51 /* --------------------- Secure bounce test ------------------------ *
52  *
53  * The secure bounce test tests that we can evict a TMZ buffer,
54  * and page it back in, via a bounce buffer, as it encryption/decryption
55  * depends on its physical address, and have the same data, i.e. data
56  * integrity is preserved.
57  *
58  * The steps are as follows (from Christian K.):
59  *
60  * Buffer A which is TMZ protected and filled by the CPU with a
61  * certain pattern. That the GPU is reading only random nonsense from
62  * that pattern is irrelevant for the test.
63  *
64  * This buffer A is then secure copied into buffer B which is also
65  * TMZ protected.
66  *
67  * Buffer B is moved around, from VRAM to GTT, GTT to SYSTEM,
68  * etc.
69  *
70  * Then, we use another secure copy of buffer B back to buffer A.
71  *
72  * And lastly we check with the CPU the pattern.
73  *
74  * Assuming that we don't have memory contention and buffer A stayed
75  * at the same place, we should still see the same pattern when read
76  * by the CPU.
77  *
78  * If we don't see the same pattern then something in the buffer
79  * migration code is not working as expected.
80  */
81 
82 #define SECURE_BOUNCE_TEST_STR    "secure bounce"
83 #define SECURE_BOUNCE_FAILED_STR  SECURE_BOUNCE_TEST_STR " failed"
84 
85 #define PRINT_ERROR(_Res)   fprintf(stderr, "%s:%d: %s (%d)\n",	\
86 				    __func__, __LINE__, strerror(-(_Res)), _Res)
87 
88 #define PACKET_LCOPY_SIZE         7
89 #define PACKET_NOP_SIZE          12
90 
91 struct sec_amdgpu_bo {
92 	struct amdgpu_bo *bo;
93 	struct amdgpu_va *va;
94 };
95 
96 struct command_ctx {
97 	struct amdgpu_device    *dev;
98 	struct amdgpu_cs_ib_info cs_ibinfo;
99 	struct amdgpu_cs_request cs_req;
100 	struct amdgpu_context   *context;
101 	int ring_id;
102 };
103 
104 /**
105  * amdgpu_bo_alloc_map -- Allocate and map a buffer object (BO)
106  * @dev: The AMDGPU device this BO belongs to.
107  * @size: The size of the BO.
108  * @alignment: Alignment of the BO.
109  * @gem_domain: One of AMDGPU_GEM_DOMAIN_xyz.
110  * @alloc_flags: One of AMDGPU_GEM_CREATE_xyz.
111  * @sbo: the result
112  *
113  * Allocate a buffer object (BO) with the desired attributes
114  * as specified by the argument list and write out the result
115  * into @sbo.
116  *
117  * Return 0 on success and @sbo->bo and @sbo->va are set,
118  * or -errno on error.
119  */
amdgpu_bo_alloc_map(struct amdgpu_device * dev,unsigned size,unsigned alignment,unsigned gem_domain,uint64_t alloc_flags,struct sec_amdgpu_bo * sbo)120 static int amdgpu_bo_alloc_map(struct amdgpu_device *dev,
121 			       unsigned size,
122 			       unsigned alignment,
123 			       unsigned gem_domain,
124 			       uint64_t alloc_flags,
125 			       struct sec_amdgpu_bo *sbo)
126 {
127 	void *cpu;
128 	uint64_t mc_addr;
129 
130 	return amdgpu_bo_alloc_and_map_raw(dev,
131 					   size,
132 					   alignment,
133 					   gem_domain,
134 					   alloc_flags,
135 					   0,
136 					   &sbo->bo,
137 					   &cpu, &mc_addr,
138 					   &sbo->va);
139 }
140 
amdgpu_bo_unmap_free(struct sec_amdgpu_bo * sbo,const uint64_t size)141 static void amdgpu_bo_unmap_free(struct sec_amdgpu_bo *sbo,
142 				 const uint64_t size)
143 {
144 	(void) amdgpu_bo_unmap_and_free(sbo->bo,
145 					sbo->va,
146 					sbo->va->address,
147 					size);
148 	sbo->bo = NULL;
149 	sbo->va = NULL;
150 }
151 
amdgpu_sdma_lcopy(uint32_t * packet,const uint64_t dst,const uint64_t src,const uint32_t size,const int secure)152 static void amdgpu_sdma_lcopy(uint32_t *packet,
153 			      const uint64_t dst,
154 			      const uint64_t src,
155 			      const uint32_t size,
156 			      const int secure)
157 {
158 	/* Set the packet to Linear copy with TMZ set.
159 	 */
160 	packet[0] = htole32(secure << 18 | 1);
161 	packet[1] = htole32(size-1);
162 	packet[2] = htole32(0);
163 	packet[3] = htole32((uint32_t)(src & 0xFFFFFFFFU));
164 	packet[4] = htole32((uint32_t)(src >> 32));
165 	packet[5] = htole32((uint32_t)(dst & 0xFFFFFFFFU));
166 	packet[6] = htole32((uint32_t)(dst >> 32));
167 }
168 
amdgpu_sdma_nop(uint32_t * packet,uint32_t nop_count)169 static void amdgpu_sdma_nop(uint32_t *packet, uint32_t nop_count)
170 {
171 	/* A packet of the desired number of NOPs.
172 	 */
173 	packet[0] = htole32(nop_count << 16);
174 	for ( ; nop_count > 0; nop_count--)
175 		packet[nop_count-1] = 0;
176 }
177 
178 /**
179  * amdgpu_bo_lcopy -- linear copy with TMZ set, using sDMA
180  * @dev: AMDGPU device to which both buffer objects belong to
181  * @dst: destination buffer object
182  * @src: source buffer object
183  * @size: size of memory to move, in bytes.
184  * @secure: Set to 1 to perform secure copy, 0 for clear
185  *
186  * Issues and waits for completion of a Linear Copy with TMZ
187  * set, to the sDMA engine. @size should be a multiple of
188  * at least 16 bytes.
189  */
amdgpu_bo_lcopy(struct command_ctx * ctx,struct sec_amdgpu_bo * dst,struct sec_amdgpu_bo * src,const uint32_t size,int secure)190 static void amdgpu_bo_lcopy(struct command_ctx *ctx,
191 			    struct sec_amdgpu_bo *dst,
192 			    struct sec_amdgpu_bo *src,
193 			    const uint32_t size,
194 			    int secure)
195 {
196 	struct amdgpu_bo *bos[] = { dst->bo, src->bo };
197 	uint32_t packet[PACKET_LCOPY_SIZE];
198 
199 	amdgpu_sdma_lcopy(packet,
200 			  dst->va->address,
201 			  src->va->address,
202 			  size, secure);
203 	amdgpu_test_exec_cs_helper_raw(ctx->dev, ctx->context,
204 				       AMDGPU_HW_IP_DMA, ctx->ring_id,
205 				       ARRAY_SIZE(packet), packet,
206 				       ARRAY_SIZE(bos), bos,
207 				       &ctx->cs_ibinfo, &ctx->cs_req,
208 				       secure == 1);
209 }
210 
211 /**
212  * amdgpu_bo_move -- Evoke a move of the buffer object (BO)
213  * @dev: device to which this buffer object belongs to
214  * @bo: the buffer object to be moved
215  * @whereto: one of AMDGPU_GEM_DOMAIN_xyz
216  * @secure: set to 1 to submit secure IBs
217  *
218  * Evokes a move of the buffer object @bo to the GEM domain
219  * descibed by @whereto.
220  *
221  * Returns 0 on sucess; -errno on error.
222  */
amdgpu_bo_move(struct command_ctx * ctx,struct amdgpu_bo * bo,uint64_t whereto,int secure)223 static int amdgpu_bo_move(struct command_ctx *ctx,
224 			  struct amdgpu_bo *bo,
225 			  uint64_t whereto,
226 			  int secure)
227 {
228 	struct amdgpu_bo *bos[] = { bo };
229 	struct drm_amdgpu_gem_op gop = {
230 		.handle  = bo->handle,
231 		.op      = AMDGPU_GEM_OP_SET_PLACEMENT,
232 		.value   = whereto,
233 	};
234 	uint32_t packet[PACKET_NOP_SIZE];
235 	int res;
236 
237 	/* Change the buffer's placement.
238 	 */
239 	res = drmIoctl(ctx->dev->fd, DRM_IOCTL_AMDGPU_GEM_OP, &gop);
240 	if (res)
241 		return -errno;
242 
243 	/* Now issue a NOP to actually evoke the MM to move
244 	 * it to the desired location.
245 	 */
246 	amdgpu_sdma_nop(packet, PACKET_NOP_SIZE);
247 	amdgpu_test_exec_cs_helper_raw(ctx->dev, ctx->context,
248 				       AMDGPU_HW_IP_DMA, ctx->ring_id,
249 				       ARRAY_SIZE(packet), packet,
250 				       ARRAY_SIZE(bos), bos,
251 				       &ctx->cs_ibinfo, &ctx->cs_req,
252 				       secure == 1);
253 	return 0;
254 }
255 
256 /* Safe, O Sec!
257  */
258 static const uint8_t secure_pattern[] = { 0x5A, 0xFE, 0x05, 0xEC };
259 
260 #define SECURE_BUFFER_SIZE       (4 * 1024 * sizeof(secure_pattern))
261 
amdgpu_secure_bounce(void)262 static void amdgpu_secure_bounce(void)
263 {
264 	struct sec_amdgpu_bo alice, bob;
265 	struct command_ctx   sb_ctx;
266 	long page_size;
267 	uint8_t *pp;
268 	int res;
269 
270 	page_size = sysconf(_SC_PAGESIZE);
271 
272 	memset(&sb_ctx, 0, sizeof(sb_ctx));
273 	sb_ctx.dev = device_handle;
274 	res = amdgpu_cs_ctx_create(sb_ctx.dev, &sb_ctx.context);
275 	if (res) {
276 		PRINT_ERROR(res);
277 		CU_FAIL(SECURE_BOUNCE_FAILED_STR);
278 		return;
279 	}
280 
281 	/* Use the first present ring.
282 	 */
283 	res = ffs(sdma_info.available_rings) - 1;
284 	if (res == -1) {
285 		PRINT_ERROR(-ENOENT);
286 		CU_FAIL(SECURE_BOUNCE_FAILED_STR);
287 		goto Out_free_ctx;
288 	}
289 	sb_ctx.ring_id = res;
290 
291 	/* Allocate a buffer named Alice in VRAM.
292 	 */
293 	res = amdgpu_bo_alloc_map(device_handle,
294 				  SECURE_BUFFER_SIZE,
295 				  page_size,
296 				  AMDGPU_GEM_DOMAIN_VRAM,
297 				  AMDGPU_GEM_CREATE_ENCRYPTED,
298 				  &alice);
299 	if (res) {
300 		PRINT_ERROR(res);
301 		CU_FAIL(SECURE_BOUNCE_FAILED_STR);
302 		return;
303 	}
304 
305 	/* Fill Alice with a pattern.
306 	 */
307 	for (pp = alice.bo->cpu_ptr;
308 	     pp < (typeof(pp)) alice.bo->cpu_ptr + SECURE_BUFFER_SIZE;
309 	     pp += sizeof(secure_pattern))
310 		memcpy(pp, secure_pattern, sizeof(secure_pattern));
311 
312 	/* Allocate a buffer named Bob in VRAM.
313 	 */
314 	res = amdgpu_bo_alloc_map(device_handle,
315 				  SECURE_BUFFER_SIZE,
316 				  page_size,
317 				  AMDGPU_GEM_DOMAIN_VRAM,
318 				  0 /* AMDGPU_GEM_CREATE_ENCRYPTED */,
319 				  &bob);
320 	if (res) {
321 		PRINT_ERROR(res);
322 		CU_FAIL(SECURE_BOUNCE_FAILED_STR);
323 		goto Out_free_Alice;
324 	}
325 
326 	/* sDMA clear copy from Alice to Bob.
327 	 */
328 	amdgpu_bo_lcopy(&sb_ctx, &bob, &alice, SECURE_BUFFER_SIZE, 0);
329 
330 	/* Move Bob to the GTT domain.
331 	 */
332 	res = amdgpu_bo_move(&sb_ctx, bob.bo, AMDGPU_GEM_DOMAIN_GTT, 0);
333 	if (res) {
334 		PRINT_ERROR(res);
335 		CU_FAIL(SECURE_BOUNCE_FAILED_STR);
336 		goto Out_free_all;
337 	}
338 
339 	/* sDMA clear copy from Bob to Alice.
340 	 */
341 	amdgpu_bo_lcopy(&sb_ctx, &alice, &bob, SECURE_BUFFER_SIZE, 0);
342 
343 	/* Verify the contents of Alice.
344 	 */
345 	for (pp = alice.bo->cpu_ptr;
346 	     pp < (typeof(pp)) alice.bo->cpu_ptr + SECURE_BUFFER_SIZE;
347 	     pp += sizeof(secure_pattern)) {
348 		res = memcmp(pp, secure_pattern, sizeof(secure_pattern));
349 		if (res) {
350 			fprintf(stderr, SECURE_BOUNCE_FAILED_STR);
351 			CU_FAIL(SECURE_BOUNCE_FAILED_STR);
352 			break;
353 		}
354 	}
355 
356 Out_free_all:
357 	amdgpu_bo_unmap_free(&bob, SECURE_BUFFER_SIZE);
358 Out_free_Alice:
359 	amdgpu_bo_unmap_free(&alice, SECURE_BUFFER_SIZE);
360 Out_free_ctx:
361 	res = amdgpu_cs_ctx_free(sb_ctx.context);
362 	CU_ASSERT_EQUAL(res, 0);
363 }
364 
365 /* ----------------------------------------------------------------- */
366 
amdgpu_security_alloc_buf_test(void)367 static void amdgpu_security_alloc_buf_test(void)
368 {
369 	amdgpu_bo_handle bo;
370 	amdgpu_va_handle va_handle;
371 	uint64_t bo_mc;
372 	int r;
373 
374 	/* Test secure buffer allocation in VRAM */
375 	bo = gpu_mem_alloc(device_handle, 4096, 4096,
376 			   AMDGPU_GEM_DOMAIN_VRAM,
377 			   AMDGPU_GEM_CREATE_ENCRYPTED,
378 			   &bo_mc, &va_handle);
379 
380 	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
381 	CU_ASSERT_EQUAL(r, 0);
382 
383 	/* Test secure buffer allocation in system memory */
384 	bo = gpu_mem_alloc(device_handle, 4096, 4096,
385 			   AMDGPU_GEM_DOMAIN_GTT,
386 			   AMDGPU_GEM_CREATE_ENCRYPTED,
387 			   &bo_mc, &va_handle);
388 
389 	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
390 	CU_ASSERT_EQUAL(r, 0);
391 
392 	/* Test secure buffer allocation in invisible VRAM */
393 	bo = gpu_mem_alloc(device_handle, 4096, 4096,
394 			   AMDGPU_GEM_DOMAIN_GTT,
395 			   AMDGPU_GEM_CREATE_ENCRYPTED |
396 			   AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
397 			   &bo_mc, &va_handle);
398 
399 	r = gpu_mem_free(bo, va_handle, bo_mc, 4096);
400 	CU_ASSERT_EQUAL(r, 0);
401 }
402 
amdgpu_security_gfx_submission_test(void)403 static void amdgpu_security_gfx_submission_test(void)
404 {
405 	amdgpu_command_submission_write_linear_helper_with_secure(device_handle,
406 								  AMDGPU_HW_IP_GFX,
407 								  true);
408 }
409 
amdgpu_security_sdma_submission_test(void)410 static void amdgpu_security_sdma_submission_test(void)
411 {
412 	amdgpu_command_submission_write_linear_helper_with_secure(device_handle,
413 								  AMDGPU_HW_IP_DMA,
414 								  true);
415 }
416 
417 /* ----------------------------------------------------------------- */
418 
419 CU_TestInfo security_tests[] = {
420 	{ "allocate secure buffer test",        amdgpu_security_alloc_buf_test },
421 	{ "graphics secure command submission", amdgpu_security_gfx_submission_test },
422 	{ "sDMA secure command submission",     amdgpu_security_sdma_submission_test },
423 	{ SECURE_BOUNCE_TEST_STR,               amdgpu_secure_bounce },
424 	CU_TEST_INFO_NULL,
425 };
426 
suite_security_tests_enable(void)427 CU_BOOL suite_security_tests_enable(void)
428 {
429 	CU_BOOL enable = CU_TRUE;
430 
431 	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
432 				     &minor_version, &device_handle))
433 		return CU_FALSE;
434 
435 	if (device_handle->info.family_id != AMDGPU_FAMILY_RV) {
436 		printf("\n\nDon't support TMZ (trust memory zone), security suite disabled\n");
437 		enable = CU_FALSE;
438 	}
439 
440 	if ((major_version < 3) ||
441 		((major_version == 3) && (minor_version < 37))) {
442 		printf("\n\nDon't support TMZ (trust memory zone), kernel DRM version (%d.%d)\n",
443 			major_version, minor_version);
444 		printf("is older, security suite disabled\n");
445 		enable = CU_FALSE;
446 	}
447 
448 	if (amdgpu_device_deinitialize(device_handle))
449 		return CU_FALSE;
450 
451 	return enable;
452 }
453 
suite_security_tests_init(void)454 int suite_security_tests_init(void)
455 {
456 	int res;
457 
458 	res = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
459 				       &minor_version, &device_handle);
460 	if (res) {
461 		PRINT_ERROR(res);
462 		return CUE_SINIT_FAILED;
463 	}
464 
465 	res = amdgpu_query_hw_ip_info(device_handle,
466 				      AMDGPU_HW_IP_DMA,
467 				      0, &sdma_info);
468 	if (res) {
469 		PRINT_ERROR(res);
470 		return CUE_SINIT_FAILED;
471 	}
472 
473 	return CUE_SUCCESS;
474 }
475 
suite_security_tests_clean(void)476 int suite_security_tests_clean(void)
477 {
478 	int res;
479 
480 	res = amdgpu_device_deinitialize(device_handle);
481 	if (res)
482 		return CUE_SCLEAN_FAILED;
483 
484 	return CUE_SUCCESS;
485 }
486