1 /*******************************************************************************
2     Copyright (c) 2021-2023 NVIDIA Corporation
3 
4     Permission is hereby granted, free of charge, to any person obtaining a copy
5     of this software and associated documentation files (the "Software"), to
6     deal in the Software without restriction, including without limitation the
7     rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8     sell copies of the Software, and to permit persons to whom the Software is
9     furnished to do so, subject to the following conditions:
10 
11         The above copyright notice and this permission notice shall be
12         included in 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20     DEALINGS IN THE SOFTWARE.
21 
22 *******************************************************************************/
23 
24 #include <uvm_common.h>
25 #include <uvm_gpu.h>
26 #include <uvm_mem.h>
27 #include <uvm_push.h>
28 #include <uvm_hal.h>
29 #include <uvm_test.h>
30 #include <uvm_va_space.h>
31 #include <uvm_kvmalloc.h>
32 #include <linux/string.h>
33 #include "nv_uvm_interface.h"
34 
35 typedef struct test_sem_mem_t {
36     void *cpu_va;
37     NvU64 gpu_va;
38 
39     union {
40         uvm_mem_t *uvm_mem;
41         uvm_rm_mem_t *rm_mem;
42     };
43 } test_sem_mem;
44 
45 static NV_STATUS test_semaphore_alloc_uvm_rm_mem(uvm_gpu_t *gpu, const size_t size, test_sem_mem *mem_out)
46 {
47     NV_STATUS status;
48     uvm_rm_mem_t *mem = NULL;
49     NvU64 gpu_va;
50 
51     status = uvm_rm_mem_alloc_and_map_cpu(gpu, UVM_RM_MEM_TYPE_SYS, size, 0, &mem);
52     TEST_NV_CHECK_RET(status);
53 
54     gpu_va = uvm_rm_mem_get_gpu_uvm_va(mem, gpu);
55     TEST_CHECK_GOTO(gpu_va < gpu->parent->max_host_va, error);
56 
57     mem_out->cpu_va = uvm_rm_mem_get_cpu_va(mem);
58     mem_out->gpu_va = gpu_va;
59     mem_out->rm_mem = mem;
60 
61     return NV_OK;
62 
63 error:
64     uvm_rm_mem_free(mem);
65     return status;
66 }
67 
68 static NV_STATUS test_semaphore_alloc_sem(uvm_gpu_t *gpu, const size_t size, test_sem_mem *mem_out)
69 {
70     NV_STATUS status = NV_OK;
71     uvm_mem_t *mem = NULL;
72     NvU64 gpu_va;
73 
74     TEST_NV_CHECK_RET(uvm_mem_alloc_sysmem_dma(size, gpu, current->mm, &mem));
75 
76     TEST_NV_CHECK_GOTO(uvm_mem_map_gpu_kernel(mem, gpu), error);
77     gpu_va = uvm_mem_get_gpu_va_kernel(mem, gpu);
78 
79     // Use an RM allocation when SEC2 cannot address the semaphore.
80     // SEC2 VA width is similar to Host's.
81     if (gpu_va >= gpu->parent->max_host_va) {
82         uvm_mem_free(mem);
83         return test_semaphore_alloc_uvm_rm_mem(gpu, size, mem_out);
84     }
85 
86     // This semaphore resides in the uvm_mem region, i.e., it has the GPU VA
87     // MSbit set. The intent is to validate semaphore operations when the
88     // semaphore's VA is in the high-end of the GPU effective virtual address
89     // space spectrum, i.e., its VA upper-bit is set.
90     TEST_CHECK_GOTO(gpu_va & (1ULL << (gpu->address_space_tree.hal->num_va_bits() - 1)), error);
91 
92     TEST_NV_CHECK_GOTO(uvm_mem_map_cpu_kernel(mem), error);
93 
94     mem_out->cpu_va = uvm_mem_get_cpu_addr_kernel(mem);
95     mem_out->gpu_va = gpu_va;
96     mem_out->uvm_mem = mem;
97 
98     return NV_OK;
99 
100 error:
101     uvm_mem_free(mem);
102     return status;
103 }
104 
105 static void test_semaphore_free_sem(uvm_gpu_t *gpu, test_sem_mem *mem)
106 {
107     if (mem->gpu_va >= gpu->parent->uvm_mem_va_base)
108         uvm_mem_free(mem->uvm_mem);
109     else
110         uvm_rm_mem_free(mem->rm_mem);
111 }
112 
113 // This test is similar to the test_semaphore_release() test in
114 // uvm_host_test.c, except that this one uses sec2_hal->semaphore_release();
115 static NV_STATUS test_semaphore_release(uvm_gpu_t *gpu)
116 {
117     NV_STATUS status;
118     test_sem_mem mem = { 0 };
119     uvm_push_t push;
120     NvU32 value;
121     NvU32 payload = 0xA5A55A5A;
122     NvU32 *cpu_ptr;
123 
124     // Semaphore release needs 1 word (4 bytes).
125     const size_t size = sizeof(NvU32);
126 
127     status = test_semaphore_alloc_sem(gpu, size, &mem);
128     TEST_NV_CHECK_RET(status);
129 
130     // Initialize the payload.
131     cpu_ptr = (NvU32 *)mem.cpu_va;
132     *cpu_ptr = 0;
133 
134     status = uvm_push_begin(gpu->channel_manager, UVM_CHANNEL_TYPE_SEC2, &push, "semaphore_release test");
135     TEST_NV_CHECK_GOTO(status, done);
136 
137     gpu->parent->sec2_hal->semaphore_release(&push, mem.gpu_va, payload);
138 
139     status = uvm_push_end_and_wait(&push);
140     TEST_NV_CHECK_GOTO(status, done);
141 
142     value = *cpu_ptr;
143     if (value != payload) {
144         UVM_TEST_PRINT("Semaphore payload = %u instead of %u, GPU %s\n", value, payload, uvm_gpu_name(gpu));
145         status = NV_ERR_INVALID_STATE;
146         goto done;
147     }
148 
149 done:
150     test_semaphore_free_sem(gpu, &mem);
151 
152     return status;
153 }
154 
155 // This test is similiar to the test_semaphore_timestamp() test in
156 // uvm_ce_test.c, except that this one uses sec2_hal->semaphore_timestamp();
157 static NV_STATUS test_semaphore_timestamp(uvm_gpu_t *gpu)
158 {
159     NV_STATUS status;
160     test_sem_mem mem = { 0 };
161     uvm_push_t push;
162     NvU32 i;
163     NvU64 *timestamp;
164     NvU64 last_timestamp = 0;
165 
166     // 2 iterations:
167     //   1: compare retrieved timestamp with 0;
168     //   2: compare retrieved timestamp with previous timestamp (obtained in 1).
169     const NvU32 iterations = 2;
170 
171     // The semaphore is 4 words long (16 bytes).
172     const size_t size = 16;
173 
174     // TODO: Bug 3804752: SEC2 semaphore timestamp is not implemented for
175     // Hopper
176     if (uvm_conf_computing_mode_is_hcc(gpu))
177         return NV_OK;
178 
179     status = test_semaphore_alloc_sem(gpu, size, &mem);
180     TEST_NV_CHECK_RET(status);
181 
182     timestamp = (NvU64 *)mem.cpu_va;
183     TEST_CHECK_GOTO(timestamp != NULL, done);
184     memset(timestamp, 0, size);
185 
186     // Shift the timestamp pointer to where the semaphore timestamp info is.
187     timestamp += 1;
188 
189     for (i = 0; i < iterations; i++) {
190         status = uvm_push_begin(gpu->channel_manager,
191                                 UVM_CHANNEL_TYPE_SEC2,
192                                 &push,
193                                 "semaphore_timestamp test, iter: %u",
194                                 i);
195         TEST_NV_CHECK_GOTO(status, done);
196 
197         gpu->parent->sec2_hal->semaphore_timestamp(&push, mem.gpu_va);
198 
199         status = uvm_push_end_and_wait(&push);
200         TEST_NV_CHECK_GOTO(status, done);
201 
202         TEST_CHECK_GOTO(*timestamp != 0, done);
203         TEST_CHECK_GOTO(*timestamp >= last_timestamp, done);
204         last_timestamp = *timestamp;
205     }
206 
207 done:
208     test_semaphore_free_sem(gpu, &mem);
209 
210     return status;
211 }
212 
213 typedef enum
214 {
215     MEM_ALLOC_TYPE_SYSMEM_DMA,
216     MEM_ALLOC_TYPE_VIDMEM_PROTECTED
217 } mem_alloc_type_t;
218 
219 static bool mem_match(uvm_mem_t *mem1, uvm_mem_t *mem2)
220 {
221     void *mem1_addr;
222     void *mem2_addr;
223 
224     UVM_ASSERT(uvm_mem_is_sysmem(mem1));
225     UVM_ASSERT(uvm_mem_is_sysmem(mem2));
226     UVM_ASSERT(mem1->size == mem2->size);
227 
228     mem1_addr = uvm_mem_get_cpu_addr_kernel(mem1);
229     mem2_addr = uvm_mem_get_cpu_addr_kernel(mem2);
230 
231     return !memcmp(mem1_addr, mem2_addr, mem1->size);
232 }
233 
234 static NV_STATUS ce_memset_gpu(uvm_gpu_t *gpu, uvm_mem_t *mem, size_t size, NvU32 val)
235 {
236     uvm_push_t push;
237 
238     TEST_NV_CHECK_RET(uvm_push_begin(gpu->channel_manager,
239                                      UVM_CHANNEL_TYPE_GPU_INTERNAL,
240                                      &push,
241                                      "VPR memset"));
242 
243     gpu->parent->ce_hal->memset_4(&push, uvm_mem_gpu_address_virtual_kernel(mem, gpu), val, size);
244 
245     TEST_NV_CHECK_RET(uvm_push_end_and_wait(&push));
246 
247     return NV_OK;
248 }
249 
250 static void write_range_cpu(uvm_mem_t *mem, size_t size, NvU64 base_val)
251 {
252     char *start, *end;
253 
254     UVM_ASSERT(uvm_mem_is_sysmem(mem));
255 
256     start = uvm_mem_get_cpu_addr_kernel(mem);
257     end = start + size;
258 
259     for (; start < end; start += sizeof(NvU64))
260         *(NvU64 *) start = base_val++;
261 }
262 
263 static NV_STATUS alloc_and_init_mem(uvm_gpu_t *gpu, uvm_mem_t **mem, size_t size, mem_alloc_type_t type)
264 {
265     NV_STATUS status = NV_OK;
266 
267     UVM_ASSERT(mem);
268 
269     *mem = NULL;
270 
271     if (type == MEM_ALLOC_TYPE_VIDMEM_PROTECTED) {
272         TEST_NV_CHECK_RET(uvm_mem_alloc_vidmem_protected(size, gpu, mem));
273         TEST_NV_CHECK_GOTO(uvm_mem_map_gpu_kernel(*mem, gpu), err);
274         TEST_NV_CHECK_GOTO(ce_memset_gpu(gpu, *mem, size, 0xdead), err);
275     }
276     else {
277         TEST_NV_CHECK_RET(uvm_mem_alloc_sysmem_dma(size, gpu, NULL, mem));
278         TEST_NV_CHECK_GOTO(uvm_mem_map_cpu_kernel(*mem), err);
279         TEST_NV_CHECK_GOTO(uvm_mem_map_gpu_kernel(*mem, gpu), err);
280         write_range_cpu(*mem, size, 0xdeaddead);
281     }
282 
283     return NV_OK;
284 
285 err:
286     uvm_mem_free(*mem);
287     return status;
288 }
289 
290 static void cpu_encrypt(uvm_channel_t *channel,
291                         uvm_mem_t *dst_mem,
292                         uvm_mem_t *src_mem,
293                         uvm_mem_t *auth_tag_mem,
294                         size_t size,
295                         size_t copy_size)
296 {
297     size_t i;
298     void *src_plain = uvm_mem_get_cpu_addr_kernel(src_mem);
299     void *dst_cipher = uvm_mem_get_cpu_addr_kernel(dst_mem);
300     void *auth_tag_buffer = uvm_mem_get_cpu_addr_kernel(auth_tag_mem);
301 
302     UVM_ASSERT(IS_ALIGNED(size, copy_size));
303 
304     for (i = 0; i < size / copy_size; i++) {
305         uvm_conf_computing_cpu_encrypt(channel, dst_cipher, src_plain, NULL, copy_size, auth_tag_buffer);
306 
307         src_plain = (char *) src_plain + copy_size;
308         dst_cipher = (char *) dst_cipher + copy_size;
309         auth_tag_buffer = (char *) auth_tag_buffer + UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
310     }
311 }
312 
313 static NV_STATUS cpu_decrypt(uvm_channel_t *channel,
314                              uvm_mem_t *dst_mem,
315                              uvm_mem_t *src_mem,
316                              UvmCslIv *decrypt_iv,
317                              uvm_mem_t *auth_tag_mem,
318                              size_t size,
319                              size_t copy_size)
320 {
321     size_t i;
322     void *src_cipher = uvm_mem_get_cpu_addr_kernel(src_mem);
323     void *dst_plain = uvm_mem_get_cpu_addr_kernel(dst_mem);
324     void *auth_tag_buffer = uvm_mem_get_cpu_addr_kernel(auth_tag_mem);
325 
326     UVM_ASSERT(IS_ALIGNED(size, copy_size));
327 
328     for (i = 0; i < size / copy_size; i++) {
329         TEST_NV_CHECK_RET(uvm_conf_computing_cpu_decrypt(channel,
330                                                          dst_plain,
331                                                          src_cipher,
332                                                          &decrypt_iv[i],
333                                                          copy_size,
334                                                          auth_tag_buffer));
335 
336         dst_plain = (char *) dst_plain + copy_size;
337         src_cipher = (char *) src_cipher + copy_size;
338         auth_tag_buffer = (char *) auth_tag_buffer + UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
339     }
340 
341     return NV_OK;
342 }
343 
344 // gpu_encrypt uses a secure CE for encryption (instead of SEC2). SEC2 does not
345 // support encryption. The following function is copied from uvm_ce_test.c and
346 // adapted to SEC2 tests.
347 static void gpu_encrypt(uvm_push_t *push,
348                         uvm_mem_t *dst_mem,
349                         uvm_mem_t *src_mem,
350                         UvmCslIv *decrypt_iv,
351                         uvm_mem_t *auth_tag_mem,
352                         size_t size,
353                         size_t copy_size)
354 {
355     size_t i;
356     size_t num_iterations = size / copy_size;
357     uvm_gpu_t *gpu = uvm_push_get_gpu(push);
358     uvm_gpu_address_t dst_cipher_address = uvm_mem_gpu_address_virtual_kernel(dst_mem, gpu);
359     uvm_gpu_address_t src_plain_address = uvm_mem_gpu_address_virtual_kernel(src_mem, gpu);
360     uvm_gpu_address_t auth_tag_address = uvm_mem_gpu_address_virtual_kernel(auth_tag_mem, gpu);
361 
362     for (i = 0; i < num_iterations; i++) {
363         uvm_conf_computing_log_gpu_encryption(push->channel, decrypt_iv);
364 
365         if (i > 0)
366             uvm_push_set_flag(push, UVM_PUSH_FLAG_CE_NEXT_PIPELINED);
367 
368         uvm_push_set_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_NONE);
369 
370         gpu->parent->ce_hal->encrypt(push, dst_cipher_address, src_plain_address, copy_size, auth_tag_address);
371         dst_cipher_address.address += copy_size;
372         src_plain_address.address += copy_size;
373         auth_tag_address.address += UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
374         decrypt_iv++;
375     }
376 }
377 
378 static void gpu_decrypt(uvm_push_t *push,
379                         uvm_mem_t *dst_mem,
380                         uvm_mem_t *src_mem,
381                         uvm_mem_t *auth_tag_mem,
382                         size_t size,
383                         size_t copy_size)
384 {
385     size_t i;
386     size_t num_iterations = size / copy_size;
387     uvm_gpu_t *gpu = uvm_push_get_gpu(push);
388     uvm_gpu_address_t src_cipher_address = uvm_mem_gpu_address_virtual_kernel(src_mem, gpu);
389     uvm_gpu_address_t dst_plain_address = uvm_mem_gpu_address_virtual_kernel(dst_mem, gpu);
390     uvm_gpu_address_t auth_tag_gpu_address = uvm_mem_gpu_address_virtual_kernel(auth_tag_mem, gpu);
391 
392     UVM_ASSERT(IS_ALIGNED(size, copy_size));
393 
394     for (i = 0; i < num_iterations; i++) {
395         uvm_push_set_flag(push, UVM_PUSH_FLAG_NEXT_MEMBAR_NONE);
396         gpu->parent->sec2_hal->decrypt(push,
397                                        dst_plain_address.address,
398                                        src_cipher_address.address,
399                                        copy_size,
400                                        auth_tag_gpu_address.address);
401 
402         dst_plain_address.address += copy_size;
403         src_cipher_address.address += copy_size;
404         auth_tag_gpu_address.address += UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
405     }
406 }
407 
408 // This test only uses sysmem so that we can use the CPU for encryption and SEC2
409 // for decryption, i.e., the test doesn't depend on any other GPU engine for
410 // the encryption operation (refer to test_cpu_to_gpu_roundtrip()). This is not
411 // how SEC2 is used in the driver. The intended SEC2 usage is to decrypt from
412 // unprotected sysmem to protected vidmem, which is tested in
413 // test_cpu_to_gpu_roundtrip().
414 static NV_STATUS test_cpu_to_gpu_sysmem(uvm_gpu_t *gpu, size_t copy_size, size_t size)
415 {
416     NV_STATUS status = NV_OK;
417     uvm_mem_t *src_plain = NULL;
418     uvm_mem_t *cipher = NULL;
419     uvm_mem_t *dst_plain = NULL;
420     uvm_mem_t *auth_tag_mem = NULL;
421     size_t auth_tag_buffer_size = (size / copy_size) * UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
422     uvm_push_t push;
423 
424     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &src_plain, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
425     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &dst_plain, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
426     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &cipher, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
427     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &auth_tag_mem, auth_tag_buffer_size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
428 
429     write_range_cpu(src_plain, size, uvm_get_stale_thread_id());
430     write_range_cpu(dst_plain, size, 0xA5A5A5A5);
431 
432     TEST_NV_CHECK_GOTO(uvm_push_begin(gpu->channel_manager, UVM_CHANNEL_TYPE_SEC2, &push, "enc(cpu)_dec(gpu)"), out);
433 
434     cpu_encrypt(push.channel, cipher, src_plain, auth_tag_mem, size, copy_size);
435     gpu_decrypt(&push, dst_plain, cipher, auth_tag_mem, size, copy_size);
436 
437     uvm_push_end_and_wait(&push);
438 
439     TEST_CHECK_GOTO(mem_match(src_plain, dst_plain), out);
440 
441 out:
442     uvm_mem_free(auth_tag_mem);
443     uvm_mem_free(cipher);
444     uvm_mem_free(dst_plain);
445     uvm_mem_free(src_plain);
446 
447     return status;
448 }
449 
450 // This test depends on the CE for the encryption, so we assume tests from
451 // uvm_ce_test.c have successfully passed.
452 static NV_STATUS test_cpu_to_gpu_roundtrip(uvm_gpu_t *gpu, size_t copy_size, size_t size)
453 {
454     NV_STATUS status = NV_OK;
455     uvm_mem_t *src_plain = NULL;
456     uvm_mem_t *src_cipher = NULL;
457     uvm_mem_t *dst_cipher = NULL;
458     uvm_mem_t *dst_plain = NULL;
459     uvm_mem_t *dst_plain_cpu = NULL;
460     uvm_mem_t *auth_tag_mem = NULL;
461     size_t auth_tag_buffer_size = (size / copy_size) * UVM_CONF_COMPUTING_AUTH_TAG_SIZE;
462     uvm_push_t push;
463     UvmCslIv *decrypt_iv;
464     uvm_tracker_t tracker;
465 
466     decrypt_iv = uvm_kvmalloc_zero((size / copy_size) * sizeof(UvmCslIv));
467     if (!decrypt_iv)
468         return NV_ERR_NO_MEMORY;
469 
470     uvm_tracker_init(&tracker);
471 
472     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &src_plain, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
473     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &src_cipher, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
474     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &dst_cipher, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
475     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &dst_plain, size, MEM_ALLOC_TYPE_VIDMEM_PROTECTED), out);
476     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &dst_plain_cpu, size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
477     TEST_NV_CHECK_GOTO(alloc_and_init_mem(gpu, &auth_tag_mem, auth_tag_buffer_size, MEM_ALLOC_TYPE_SYSMEM_DMA), out);
478 
479     write_range_cpu(src_plain, size, uvm_get_stale_thread_id());
480 
481     TEST_NV_CHECK_GOTO(uvm_push_begin(gpu->channel_manager, UVM_CHANNEL_TYPE_SEC2, &push, "enc(cpu)_dec(gpu)"), out);
482 
483     cpu_encrypt(push.channel, src_cipher, src_plain, auth_tag_mem, size, copy_size);
484     gpu_decrypt(&push, dst_plain, src_cipher, auth_tag_mem, size, copy_size);
485 
486     uvm_push_end(&push);
487     TEST_NV_CHECK_GOTO(uvm_tracker_add_push(&tracker, &push), out);
488 
489     TEST_NV_CHECK_GOTO(uvm_push_begin_acquire(gpu->channel_manager,
490                                               UVM_CHANNEL_TYPE_GPU_TO_CPU,
491                                               &tracker,
492                                               &push,
493                                               "enc(gpu)_dec(cpu)"),
494                        out);
495 
496     gpu_encrypt(&push, dst_cipher, dst_plain, decrypt_iv, auth_tag_mem, size, copy_size);
497 
498     TEST_NV_CHECK_GOTO(uvm_push_end_and_wait(&push), out);
499 
500     TEST_CHECK_GOTO(!mem_match(src_plain, src_cipher), out);
501     TEST_CHECK_GOTO(!mem_match(dst_cipher, src_plain), out);
502 
503     TEST_NV_CHECK_GOTO(cpu_decrypt(push.channel,
504                                    dst_plain_cpu,
505                                    dst_cipher,
506                                    decrypt_iv,
507                                    auth_tag_mem,
508                                    size,
509                                    copy_size),
510                        out);
511 
512     TEST_CHECK_GOTO(mem_match(src_plain, dst_plain_cpu), out);
513 
514 out:
515     uvm_mem_free(auth_tag_mem);
516     uvm_mem_free(dst_plain_cpu);
517     uvm_mem_free(dst_plain);
518     uvm_mem_free(dst_cipher);
519     uvm_mem_free(src_cipher);
520     uvm_mem_free(src_plain);
521 
522     uvm_kvfree(decrypt_iv);
523 
524     uvm_tracker_deinit(&tracker);
525 
526     return status;
527 }
528 
529 static NV_STATUS test_encryption_decryption(uvm_gpu_t *gpu)
530 {
531     size_t copy_sizes[] = { 4, 16, 512, 2 * UVM_SIZE_1KB, 4 * UVM_SIZE_1KB, 64 * UVM_SIZE_1KB, 2 * UVM_SIZE_1MB };
532     int i;
533 
534     for (i = 0; i < ARRAY_SIZE(copy_sizes); i++) {
535         // Limit the number of methods in the gpu_encrypt()/gpu_decrypt() work
536         // submission.
537         size_t size = min(UVM_VA_BLOCK_SIZE, 256ull * copy_sizes[i]);
538 
539         // gpu_encrypt() and gpu_decrypt() iterate over a 'size' buffer. If
540         // copy_sizes[i] < 16 (SEC2 src and dst alignment requirement is
541         // 16-byte), SEC2 and our HAL implementation assert/fail. When
542         // copy_sizes[i] < 16, we only perform a single copy_sizes[i] copy.
543         if (copy_sizes[i] < 16)
544             size = copy_sizes[i];
545 
546         UVM_ASSERT(size % copy_sizes[i] == 0);
547 
548         TEST_NV_CHECK_RET(test_cpu_to_gpu_sysmem(gpu, copy_sizes[i], size));
549         TEST_NV_CHECK_RET(test_cpu_to_gpu_roundtrip(gpu, copy_sizes[i], size));
550     }
551 
552     return NV_OK;
553 }
554 
555 static NV_STATUS test_sec2(uvm_va_space_t *va_space)
556 {
557     uvm_gpu_t *gpu;
558 
559     for_each_va_space_gpu(gpu, va_space) {
560         TEST_CHECK_RET(uvm_conf_computing_mode_enabled(gpu));
561 
562         TEST_NV_CHECK_RET(test_semaphore_release(gpu));
563         TEST_NV_CHECK_RET(test_semaphore_timestamp(gpu));
564         TEST_NV_CHECK_RET(test_encryption_decryption(gpu));
565     }
566 
567     return NV_OK;
568 }
569 
570 NV_STATUS uvm_test_sec2_sanity(UVM_TEST_SEC2_SANITY_PARAMS *params, struct file *filp)
571 {
572     NV_STATUS status;
573     uvm_va_space_t *va_space = uvm_va_space_get(filp);
574 
575     uvm_va_space_down_read_rm(va_space);
576 
577     status = test_sec2(va_space);
578     if (status != NV_OK)
579         goto done;
580 
581 done:
582     uvm_va_space_up_read_rm(va_space);
583 
584     return status;
585 }
586 
587 NV_STATUS uvm_test_sec2_cpu_gpu_roundtrip(UVM_TEST_SEC2_CPU_GPU_ROUNDTRIP_PARAMS *params, struct file *filp)
588 {
589     NV_STATUS status = NV_OK;
590     uvm_va_space_t *va_space = uvm_va_space_get(filp);
591     uvm_gpu_t *gpu;
592 
593     uvm_va_space_down_read(va_space);
594 
595     for_each_va_space_gpu(gpu, va_space) {
596         TEST_CHECK_RET(uvm_conf_computing_mode_enabled(gpu));
597 
598         // To exercise certain SEC2 context save/restore races, do a looped
599         // decrypt with smaller copy sizes instead of larger copy sizes since we
600         // need SEC2 to context switch with pending work in different channels
601         // and smaller copies decrypt increases the probability of exercising
602         // SEC2 context switching. A single push of the entire size may not be
603         // enough to re-create this scenario since SEC2 doesn't preempt in the
604         // middle of the decrypt.
605         status = test_cpu_to_gpu_roundtrip(gpu, UVM_PAGE_SIZE_4K, UVM_VA_BLOCK_SIZE);
606         if (status != NV_OK)
607             goto done;
608     }
609 
610 done:
611     uvm_va_space_up_read(va_space);
612 
613     return status;
614 }
615