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