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