1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1999-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 25 26 //***************************** Module Header ********************************** 27 // 28 // This code is linked into the resource manager proper. It receives the 29 // ioctl from the resource manager's customer, unbundles the args and 30 // calls the correct resman routines. 31 // 32 //****************************************************************************** 33 34 #include <core/prelude.h> 35 #include <core/locks.h> 36 #include <nv.h> 37 #include <nv_escape.h> 38 #include <osapi.h> 39 #include <rmapi/exports.h> 40 #include <nv-unix-nvos-params-wrappers.h> 41 42 #include <nvos.h> 43 #include <class/cl0000.h> // NV01_ROOT 44 #include <class/cl0001.h> // NV01_ROOT_NON_PRIV 45 #include <class/cl0005.h> // NV01_EVENT 46 #include <class/cl003e.h> // NV01_MEMORY_SYSTEM 47 #include <class/cl0071.h> // NV01_MEMORY_SYSTEM_OS_DESCRIPTOR 48 49 #include "rmapi/client_resource.h" 50 #include "nvlog/nvlog.h" 51 #include <nv-ioctl-nvlog.h> 52 53 #include <ctrl/ctrl00fd.h> 54 55 #define NV_CTL_DEVICE_ONLY(nv) \ 56 { \ 57 if (((nv)->flags & NV_FLAG_CONTROL) == 0) \ 58 { \ 59 rmStatus = NV_ERR_INVALID_ARGUMENT; \ 60 goto done; \ 61 } \ 62 } 63 64 #define NV_ACTUAL_DEVICE_ONLY(nv) \ 65 { \ 66 if (((nv)->flags & NV_FLAG_CONTROL) != 0) \ 67 { \ 68 rmStatus = NV_ERR_INVALID_ARGUMENT; \ 69 goto done; \ 70 } \ 71 } 72 73 static NvBool RmIsDeviceRefNeeded(NVOS54_PARAMETERS *pApi) 74 { 75 switch(pApi->cmd) 76 { 77 case NV00FD_CTRL_CMD_ATTACH_GPU: 78 return NV_TRUE; 79 default: 80 return NV_FALSE; 81 } 82 } 83 84 static NV_STATUS RmGetDeviceFd(NVOS54_PARAMETERS *pApi, NvS32 *pFd) 85 { 86 RMAPI_PARAM_COPY paramCopy; 87 void *pKernelParams; 88 NvU32 paramSize; 89 NV_STATUS status; 90 91 *pFd = -1; 92 93 switch(pApi->cmd) 94 { 95 case NV00FD_CTRL_CMD_ATTACH_GPU: 96 paramSize = sizeof(NV00FD_CTRL_ATTACH_GPU_PARAMS); 97 break; 98 default: 99 return NV_ERR_INVALID_ARGUMENT; 100 } 101 102 RMAPI_PARAM_COPY_INIT(paramCopy, pKernelParams, pApi->params, paramSize, 1); 103 104 status = rmapiParamsAcquire(¶mCopy, NV_TRUE); 105 if (status != NV_OK) 106 return status; 107 108 switch(pApi->cmd) 109 { 110 case NV00FD_CTRL_CMD_ATTACH_GPU: 111 *pFd = (NvS32)((NV00FD_CTRL_ATTACH_GPU_PARAMS *)pKernelParams)->devDescriptor; 112 break; 113 default: 114 NV_ASSERT(0); 115 break; 116 } 117 118 NV_ASSERT(rmapiParamsRelease(¶mCopy) == NV_OK); 119 120 return status; 121 } 122 123 // Only return errors through pApi->status 124 static void RmCreateOsDescriptor(NVOS32_PARAMETERS *pApi, API_SECURITY_INFO secInfo) 125 { 126 NV_STATUS rmStatus; 127 NvBool writable; 128 NvU32 flags = 0; 129 NvU64 allocSize, pageCount, *pPteArray = NULL; 130 void *pDescriptor, *pPageArray = NULL; 131 132 pDescriptor = NvP64_VALUE(pApi->data.AllocOsDesc.descriptor); 133 if (((NvUPtr)pDescriptor & ~os_page_mask) != 0) 134 { 135 rmStatus = NV_ERR_NOT_SUPPORTED; 136 goto done; 137 } 138 139 // Check to prevent an NvU64 overflow 140 if ((pApi->data.AllocOsDesc.limit + 1) == 0) 141 { 142 rmStatus = NV_ERR_INVALID_LIMIT; 143 goto done; 144 } 145 146 allocSize = (pApi->data.AllocOsDesc.limit + 1); 147 pageCount = (1 + ((allocSize - 1) / os_page_size)); 148 149 writable = FLD_TEST_DRF(OS32, _ATTR2, _PROTECTION_USER, _READ_WRITE, pApi->data.AllocOsDesc.attr2); 150 151 flags = FLD_SET_DRF_NUM(_LOCK_USER_PAGES, _FLAGS, _WRITE, writable, flags); 152 rmStatus = os_lock_user_pages(pDescriptor, pageCount, &pPageArray, flags); 153 if (rmStatus == NV_OK) 154 { 155 pApi->data.AllocOsDesc.descriptor = (NvP64)(NvUPtr)pPageArray; 156 pApi->data.AllocOsDesc.descriptorType = NVOS32_DESCRIPTOR_TYPE_OS_PAGE_ARRAY; 157 } 158 else if (rmStatus == NV_ERR_INVALID_ADDRESS) 159 { 160 rmStatus = os_lookup_user_io_memory(pDescriptor, pageCount, 161 &pPteArray, &pPageArray); 162 if (rmStatus == NV_OK) 163 { 164 if (pPageArray != NULL) 165 { 166 pApi->data.AllocOsDesc.descriptor = (NvP64)(NvUPtr)pPageArray; 167 pApi->data.AllocOsDesc.descriptorType = NVOS32_DESCRIPTOR_TYPE_OS_PAGE_ARRAY; 168 } 169 else if (pPteArray != NULL) 170 { 171 pApi->data.AllocOsDesc.descriptor = (NvP64)(NvUPtr)pPteArray; 172 pApi->data.AllocOsDesc.descriptorType = NVOS32_DESCRIPTOR_TYPE_OS_IO_MEMORY; 173 } 174 else 175 { 176 NV_ASSERT_FAILED("unknown memory import type"); 177 rmStatus = NV_ERR_NOT_SUPPORTED; 178 } 179 } 180 } 181 if (rmStatus != NV_OK) 182 goto done; 183 184 Nv04VidHeapControlWithSecInfo(pApi, secInfo); 185 186 if (pApi->status != NV_OK) 187 { 188 switch (pApi->data.AllocOsDesc.descriptorType) 189 { 190 default: 191 break; 192 case NVOS32_DESCRIPTOR_TYPE_OS_PAGE_ARRAY: 193 os_unlock_user_pages(pageCount, pPageArray); 194 break; 195 } 196 } 197 198 done: 199 if (rmStatus != NV_OK) 200 pApi->status = rmStatus; 201 } 202 203 // Only return errors through pApi->status 204 static void RmAllocOsDescriptor(NVOS02_PARAMETERS *pApi, API_SECURITY_INFO secInfo) 205 { 206 NV_STATUS rmStatus = NV_OK; 207 NvU32 flags, attr, attr2; 208 NVOS32_PARAMETERS *pVidHeapParams; 209 210 if (!FLD_TEST_DRF(OS02, _FLAGS, _LOCATION, _PCI, pApi->flags) || 211 !FLD_TEST_DRF(OS02, _FLAGS, _MAPPING, _NO_MAP, pApi->flags)) 212 { 213 rmStatus = NV_ERR_INVALID_FLAGS; 214 goto done; 215 } 216 217 attr = DRF_DEF(OS32, _ATTR, _LOCATION, _PCI); 218 219 if (FLD_TEST_DRF(OS02, _FLAGS, _COHERENCY, _CACHED, pApi->flags) || 220 FLD_TEST_DRF(OS02, _FLAGS, _COHERENCY, _WRITE_BACK, pApi->flags)) 221 { 222 attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _WRITE_BACK, attr); 223 } 224 else if (FLD_TEST_DRF(OS02, _FLAGS, _COHERENCY, _UNCACHED, pApi->flags)) 225 attr = FLD_SET_DRF(OS32, _ATTR, _COHERENCY, _UNCACHED, attr); 226 else { 227 rmStatus = NV_ERR_INVALID_FLAGS; 228 goto done; 229 } 230 231 if (FLD_TEST_DRF(OS02, _FLAGS, _PHYSICALITY, _CONTIGUOUS, pApi->flags)) 232 attr = FLD_SET_DRF(OS32, _ATTR, _PHYSICALITY, _CONTIGUOUS, attr); 233 else 234 attr = FLD_SET_DRF(OS32, _ATTR, _PHYSICALITY, _NONCONTIGUOUS, attr); 235 236 if (FLD_TEST_DRF(OS02, _FLAGS, _GPU_CACHEABLE, _YES, pApi->flags)) 237 attr2 = DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _YES); 238 else 239 attr2 = DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _NO); 240 241 pVidHeapParams = portMemAllocNonPaged(sizeof(NVOS32_PARAMETERS)); 242 if (pVidHeapParams == NULL) 243 { 244 rmStatus = NV_ERR_NO_MEMORY; 245 goto done; 246 } 247 portMemSet(pVidHeapParams, 0, sizeof(NVOS32_PARAMETERS)); 248 249 pVidHeapParams->hRoot = pApi->hRoot; 250 pVidHeapParams->hObjectParent = pApi->hObjectParent; 251 pVidHeapParams->function = NVOS32_FUNCTION_ALLOC_OS_DESCRIPTOR; 252 253 flags = (NVOS32_ALLOC_FLAGS_MEMORY_HANDLE_PROVIDED | 254 NVOS32_ALLOC_FLAGS_MAP_NOT_REQUIRED); 255 256 if (DRF_VAL(OS02, _FLAGS, _ALLOC_USER_READ_ONLY, pApi->flags)) 257 attr2 = FLD_SET_DRF(OS32, _ATTR2, _PROTECTION_USER, _READ_ONLY, attr2); 258 259 // Currently CPU-RO memory implies GPU-RO as well 260 if (DRF_VAL(OS02, _FLAGS, _ALLOC_DEVICE_READ_ONLY, pApi->flags) || 261 DRF_VAL(OS02, _FLAGS, _ALLOC_USER_READ_ONLY, pApi->flags)) 262 attr2 = FLD_SET_DRF(OS32, _ATTR2, _PROTECTION_DEVICE, _READ_ONLY, attr2); 263 264 pVidHeapParams->data.AllocOsDesc.hMemory = pApi->hObjectNew; 265 pVidHeapParams->data.AllocOsDesc.flags = flags; 266 pVidHeapParams->data.AllocOsDesc.attr = attr; 267 pVidHeapParams->data.AllocOsDesc.attr2 = attr2; 268 pVidHeapParams->data.AllocOsDesc.descriptor = pApi->pMemory; 269 pVidHeapParams->data.AllocOsDesc.limit = pApi->limit; 270 pVidHeapParams->data.AllocOsDesc.descriptorType = NVOS32_DESCRIPTOR_TYPE_VIRTUAL_ADDRESS; 271 272 RmCreateOsDescriptor(pVidHeapParams, secInfo); 273 274 pApi->status = pVidHeapParams->status; 275 276 portMemFree(pVidHeapParams); 277 278 done: 279 if (rmStatus != NV_OK) 280 pApi->status = rmStatus; 281 } 282 283 ct_assert(NV_OFFSETOF(NVOS21_PARAMETERS, hRoot) == NV_OFFSETOF(NVOS64_PARAMETERS, hRoot)); 284 ct_assert(NV_OFFSETOF(NVOS21_PARAMETERS, hObjectParent) == NV_OFFSETOF(NVOS64_PARAMETERS, hObjectParent)); 285 ct_assert(NV_OFFSETOF(NVOS21_PARAMETERS, hObjectNew) == NV_OFFSETOF(NVOS64_PARAMETERS, hObjectNew)); 286 ct_assert(NV_OFFSETOF(NVOS21_PARAMETERS, hClass) == NV_OFFSETOF(NVOS64_PARAMETERS, hClass)); 287 ct_assert(NV_OFFSETOF(NVOS21_PARAMETERS, pAllocParms) == NV_OFFSETOF(NVOS64_PARAMETERS, pAllocParms)); 288 289 NV_STATUS RmIoctl( 290 nv_state_t *nv, 291 nv_file_private_t *nvfp, 292 NvU32 cmd, 293 void *data, 294 NvU32 dataSize 295 ) 296 { 297 NV_STATUS rmStatus = NV_ERR_GENERIC; 298 API_SECURITY_INFO secInfo = { }; 299 300 secInfo.privLevel = osIsAdministrator() ? RS_PRIV_LEVEL_USER_ROOT : RS_PRIV_LEVEL_USER; 301 secInfo.paramLocation = PARAM_LOCATION_USER; 302 secInfo.pProcessToken = NULL; 303 secInfo.gpuOsInfo = NULL; 304 secInfo.clientOSInfo = nvfp->ctl_nvfp; 305 if (secInfo.clientOSInfo == NULL) 306 secInfo.clientOSInfo = nvfp; 307 308 switch (cmd) 309 { 310 case NV_ESC_RM_ALLOC_MEMORY: 311 { 312 nv_ioctl_nvos02_parameters_with_fd *pApi; 313 NVOS02_PARAMETERS *pParms; 314 315 pApi = data; 316 pParms = &pApi->params; 317 318 NV_ACTUAL_DEVICE_ONLY(nv); 319 320 if (dataSize != sizeof(nv_ioctl_nvos02_parameters_with_fd)) 321 { 322 rmStatus = NV_ERR_INVALID_ARGUMENT; 323 goto done; 324 } 325 326 if (pParms->hClass == NV01_MEMORY_SYSTEM_OS_DESCRIPTOR) 327 RmAllocOsDescriptor(pParms, secInfo); 328 else 329 { 330 NvU32 flags = pParms->flags; 331 332 Nv01AllocMemoryWithSecInfo(pParms, secInfo); 333 334 // 335 // If the system memory is going to be mapped immediately, 336 // create the mmap context for it now. 337 // 338 if ((pParms->hClass == NV01_MEMORY_SYSTEM) && 339 (!FLD_TEST_DRF(OS02, _FLAGS, _ALLOC, _NONE, flags)) && 340 (!FLD_TEST_DRF(OS02, _FLAGS, _MAPPING, _NO_MAP, flags)) && 341 (pParms->status == NV_OK)) 342 { 343 if (rm_create_mmap_context(pParms->hRoot, 344 pParms->hObjectParent, pParms->hObjectNew, 345 pParms->pMemory, pParms->limit + 1, 0, 346 NV_MEMORY_DEFAULT, 347 pApi->fd) != NV_OK) 348 { 349 NV_PRINTF(LEVEL_WARNING, 350 "could not create mmap context for %p\n", 351 NvP64_VALUE(pParms->pMemory)); 352 rmStatus = NV_ERR_INVALID_ARGUMENT; 353 goto done; 354 } 355 } 356 } 357 358 break; 359 } 360 361 case NV_ESC_RM_ALLOC_OBJECT: 362 { 363 NVOS05_PARAMETERS *pApi = data; 364 365 NV_CTL_DEVICE_ONLY(nv); 366 367 if (dataSize != sizeof(NVOS05_PARAMETERS)) 368 { 369 rmStatus = NV_ERR_INVALID_ARGUMENT; 370 goto done; 371 } 372 373 Nv01AllocObjectWithSecInfo(pApi, secInfo); 374 break; 375 } 376 377 case NV_ESC_RM_ALLOC: 378 { 379 NVOS21_PARAMETERS *pApi = data; 380 NVOS64_PARAMETERS *pApiAccess = data; 381 NvBool bAccessApi = (dataSize == sizeof(NVOS64_PARAMETERS)); 382 383 if ((dataSize != sizeof(NVOS21_PARAMETERS)) && 384 (dataSize != sizeof(NVOS64_PARAMETERS))) 385 { 386 rmStatus = NV_ERR_INVALID_ARGUMENT; 387 goto done; 388 } 389 390 switch (pApi->hClass) 391 { 392 case NV01_ROOT: 393 case NV01_ROOT_CLIENT: 394 case NV01_ROOT_NON_PRIV: 395 { 396 NV_CTL_DEVICE_ONLY(nv); 397 398 // Force userspace client allocations to be the _CLIENT class. 399 pApi->hClass = NV01_ROOT_CLIENT; 400 break; 401 } 402 case NV01_EVENT: 403 case NV01_EVENT_OS_EVENT: 404 case NV01_EVENT_KERNEL_CALLBACK: 405 case NV01_EVENT_KERNEL_CALLBACK_EX: 406 { 407 break; 408 } 409 default: 410 { 411 NV_CTL_DEVICE_ONLY(nv); 412 break; 413 } 414 } 415 416 if (!bAccessApi) 417 { 418 Nv04AllocWithSecInfo(pApi, secInfo); 419 } 420 else 421 { 422 Nv04AllocWithAccessSecInfo(pApiAccess, secInfo); 423 } 424 425 break; 426 } 427 428 case NV_ESC_RM_FREE: 429 { 430 NVOS00_PARAMETERS *pApi = data; 431 432 NV_CTL_DEVICE_ONLY(nv); 433 434 if (dataSize != sizeof(NVOS00_PARAMETERS)) 435 { 436 rmStatus = NV_ERR_INVALID_ARGUMENT; 437 goto done; 438 } 439 440 Nv01FreeWithSecInfo(pApi, secInfo); 441 442 if (pApi->status == NV_OK && 443 pApi->hObjectOld == pApi->hRoot) 444 { 445 rm_client_free_os_events(pApi->hRoot); 446 } 447 448 break; 449 } 450 451 case NV_ESC_RM_VID_HEAP_CONTROL: 452 { 453 NVOS32_PARAMETERS *pApi = data; 454 455 NV_CTL_DEVICE_ONLY(nv); 456 457 if (dataSize != sizeof(NVOS32_PARAMETERS)) 458 { 459 rmStatus = NV_ERR_INVALID_ARGUMENT; 460 goto done; 461 } 462 463 if (pApi->function == NVOS32_FUNCTION_ALLOC_OS_DESCRIPTOR) 464 RmCreateOsDescriptor(pApi, secInfo); 465 else 466 Nv04VidHeapControlWithSecInfo(pApi, secInfo); 467 468 break; 469 } 470 471 case NV_ESC_RM_I2C_ACCESS: 472 { 473 NVOS_I2C_ACCESS_PARAMS *pApi = data; 474 475 NV_ACTUAL_DEVICE_ONLY(nv); 476 477 if (dataSize != sizeof(NVOS_I2C_ACCESS_PARAMS)) 478 { 479 rmStatus = NV_ERR_INVALID_ARGUMENT; 480 goto done; 481 } 482 483 Nv04I2CAccessWithSecInfo(pApi, secInfo); 484 break; 485 } 486 487 case NV_ESC_RM_IDLE_CHANNELS: 488 { 489 NVOS30_PARAMETERS *pApi = data; 490 491 NV_CTL_DEVICE_ONLY(nv); 492 493 if (dataSize != sizeof(NVOS30_PARAMETERS)) 494 { 495 rmStatus = NV_ERR_INVALID_ARGUMENT; 496 goto done; 497 } 498 499 Nv04IdleChannelsWithSecInfo(pApi, secInfo); 500 break; 501 } 502 503 case NV_ESC_RM_MAP_MEMORY: 504 { 505 nv_ioctl_nvos33_parameters_with_fd *pApi; 506 NVOS33_PARAMETERS *pParms; 507 508 pApi = data; 509 pParms = &pApi->params; 510 511 NV_CTL_DEVICE_ONLY(nv); 512 513 if (dataSize != sizeof(nv_ioctl_nvos33_parameters_with_fd)) 514 { 515 rmStatus = NV_ERR_INVALID_ARGUMENT; 516 goto done; 517 } 518 519 // Don't allow userspace to override the caching type 520 pParms->flags = FLD_SET_DRF(OS33, _FLAGS, _CACHING_TYPE, _DEFAULT, pParms->flags); 521 Nv04MapMemoryWithSecInfo(pParms, secInfo); 522 523 if (pParms->status == NV_OK) 524 { 525 pParms->status = rm_create_mmap_context(pParms->hClient, 526 pParms->hDevice, pParms->hMemory, 527 pParms->pLinearAddress, pParms->length, 528 pParms->offset, 529 DRF_VAL(OS33, _FLAGS, _CACHING_TYPE, pParms->flags), 530 pApi->fd); 531 if (pParms->status != NV_OK) 532 { 533 NVOS34_PARAMETERS params; 534 portMemSet(¶ms, 0, sizeof(NVOS34_PARAMETERS)); 535 params.hClient = pParms->hClient; 536 params.hDevice = pParms->hDevice; 537 params.hMemory = pParms->hMemory; 538 params.pLinearAddress = pParms->pLinearAddress; 539 params.flags = pParms->flags; 540 Nv04UnmapMemoryWithSecInfo(¶ms, secInfo); 541 } 542 } 543 break; 544 } 545 546 case NV_ESC_RM_UNMAP_MEMORY: 547 { 548 NVOS34_PARAMETERS *pApi = data; 549 550 NV_CTL_DEVICE_ONLY(nv); 551 552 if (dataSize != sizeof(NVOS34_PARAMETERS)) 553 { 554 rmStatus = NV_ERR_INVALID_ARGUMENT; 555 goto done; 556 } 557 558 Nv04UnmapMemoryWithSecInfo(pApi, secInfo); 559 break; 560 } 561 562 case NV_ESC_RM_ACCESS_REGISTRY: 563 { 564 NVOS38_PARAMETERS *pApi = data; 565 566 NV_CTL_DEVICE_ONLY(nv); 567 568 if (dataSize != sizeof(NVOS38_PARAMETERS)) 569 { 570 rmStatus = NV_ERR_INVALID_ARGUMENT; 571 goto done; 572 } 573 574 pApi->status = rm_access_registry(pApi->hClient, 575 pApi->hObject, 576 pApi->AccessType, 577 pApi->pDevNode, 578 pApi->DevNodeLength, 579 pApi->pParmStr, 580 pApi->ParmStrLength, 581 pApi->pBinaryData, 582 &pApi->BinaryDataLength, 583 &pApi->Data, 584 &pApi->Entry); 585 break; 586 } 587 588 case NV_ESC_RM_ALLOC_CONTEXT_DMA2: 589 { 590 NVOS39_PARAMETERS *pApi = data; 591 592 NV_CTL_DEVICE_ONLY(nv); 593 594 if (dataSize != sizeof(NVOS39_PARAMETERS)) 595 { 596 rmStatus = NV_ERR_INVALID_ARGUMENT; 597 goto done; 598 } 599 600 Nv04AllocContextDmaWithSecInfo(pApi, secInfo); 601 break; 602 } 603 604 case NV_ESC_RM_BIND_CONTEXT_DMA: 605 { 606 NVOS49_PARAMETERS *pApi = data; 607 608 NV_CTL_DEVICE_ONLY(nv); 609 610 if (dataSize != sizeof(NVOS49_PARAMETERS)) 611 { 612 rmStatus = NV_ERR_INVALID_ARGUMENT; 613 goto done; 614 } 615 616 Nv04BindContextDmaWithSecInfo(pApi, secInfo); 617 break; 618 } 619 620 case NV_ESC_RM_MAP_MEMORY_DMA: 621 { 622 NVOS46_PARAMETERS *pApi = data; 623 624 NV_CTL_DEVICE_ONLY(nv); 625 626 if (dataSize != sizeof(NVOS46_PARAMETERS)) 627 { 628 rmStatus = NV_ERR_INVALID_ARGUMENT; 629 goto done; 630 } 631 632 Nv04MapMemoryDmaWithSecInfo(pApi, secInfo); 633 break; 634 } 635 636 case NV_ESC_RM_UNMAP_MEMORY_DMA: 637 { 638 NVOS47_PARAMETERS *pApi = data; 639 640 NV_CTL_DEVICE_ONLY(nv); 641 642 if (dataSize != sizeof(NVOS47_PARAMETERS)) 643 { 644 rmStatus = NV_ERR_INVALID_ARGUMENT; 645 goto done; 646 } 647 648 Nv04UnmapMemoryDmaWithSecInfo(pApi, secInfo); 649 break; 650 } 651 652 case NV_ESC_RM_DUP_OBJECT: 653 { 654 NVOS55_PARAMETERS *pApi = data; 655 656 NV_CTL_DEVICE_ONLY(nv); 657 658 if (dataSize != sizeof(NVOS55_PARAMETERS)) 659 { 660 rmStatus = NV_ERR_INVALID_ARGUMENT; 661 goto done; 662 } 663 664 Nv04DupObjectWithSecInfo(pApi, secInfo); 665 break; 666 } 667 668 case NV_ESC_RM_SHARE: 669 { 670 NVOS57_PARAMETERS *pApi = data; 671 672 NV_CTL_DEVICE_ONLY(nv); 673 674 if (dataSize != sizeof(NVOS57_PARAMETERS)) 675 { 676 rmStatus = NV_ERR_INVALID_ARGUMENT; 677 goto done; 678 } 679 680 Nv04ShareWithSecInfo(pApi, secInfo); 681 break; 682 } 683 684 case NV_ESC_ALLOC_OS_EVENT: 685 { 686 nv_ioctl_alloc_os_event_t *pApi = data; 687 688 if (dataSize != sizeof(nv_ioctl_alloc_os_event_t)) 689 { 690 rmStatus = NV_ERR_INVALID_ARGUMENT; 691 goto done; 692 } 693 694 pApi->Status = rm_alloc_os_event(pApi->hClient, 695 nvfp, 696 pApi->fd); 697 break; 698 } 699 700 case NV_ESC_FREE_OS_EVENT: 701 { 702 nv_ioctl_free_os_event_t *pApi = data; 703 704 if (dataSize != sizeof(nv_ioctl_free_os_event_t)) 705 { 706 rmStatus = NV_ERR_INVALID_ARGUMENT; 707 goto done; 708 } 709 710 pApi->Status = rm_free_os_event(pApi->hClient, pApi->fd); 711 break; 712 } 713 714 case NV_ESC_RM_GET_EVENT_DATA: 715 { 716 NVOS41_PARAMETERS *pApi = data; 717 718 if (dataSize != sizeof(NVOS41_PARAMETERS)) 719 { 720 rmStatus = NV_ERR_INVALID_ARGUMENT; 721 goto done; 722 } 723 724 pApi->status = rm_get_event_data(nvfp, 725 pApi->pEvent, 726 &pApi->MoreEvents); 727 break; 728 } 729 730 case NV_ESC_STATUS_CODE: 731 { 732 nv_state_t *pNv; 733 nv_ioctl_status_code_t *pApi = data; 734 735 NV_CTL_DEVICE_ONLY(nv); 736 737 if (dataSize != sizeof(nv_ioctl_status_code_t)) 738 { 739 rmStatus = NV_ERR_INVALID_ARGUMENT; 740 goto done; 741 } 742 743 pNv = nv_get_adapter_state(pApi->domain, pApi->bus, pApi->slot); 744 if (pNv == NULL) 745 { 746 rmStatus = NV_ERR_INVALID_ARGUMENT; 747 goto done; 748 } 749 750 rmStatus = rm_get_adapter_status(pNv, &pApi->status); 751 752 if (rmStatus != NV_OK) 753 goto done; 754 755 break; 756 } 757 758 case NV_ESC_RM_CONTROL: 759 { 760 NVOS54_PARAMETERS *pApi = data; 761 void *priv = NULL; 762 nv_file_private_t *dev_nvfp = NULL; 763 NvS32 fd; 764 765 NV_CTL_DEVICE_ONLY(nv); 766 767 if (dataSize != sizeof(NVOS54_PARAMETERS)) 768 { 769 rmStatus = NV_ERR_INVALID_ARGUMENT; 770 goto done; 771 } 772 773 if (RmIsDeviceRefNeeded(pApi)) 774 { 775 rmStatus = RmGetDeviceFd(pApi, &fd); 776 if (rmStatus != NV_OK) 777 { 778 goto done; 779 } 780 781 dev_nvfp = nv_get_file_private(fd, NV_FALSE, &priv); 782 if (dev_nvfp == NULL) 783 { 784 rmStatus = NV_ERR_INVALID_DEVICE; 785 goto done; 786 } 787 788 // Check to avoid cyclic dependency with NV_ESC_REGISTER_FD 789 if (!portAtomicCompareAndSwapU32(&dev_nvfp->register_or_refcount, 790 NVFP_TYPE_REFCOUNTED, 791 NVFP_TYPE_NONE)) 792 { 793 // Is this already refcounted... 794 if (dev_nvfp->register_or_refcount != NVFP_TYPE_REFCOUNTED) 795 { 796 nv_put_file_private(priv); 797 rmStatus = NV_ERR_IN_USE; 798 goto done; 799 } 800 } 801 802 secInfo.gpuOsInfo = priv; 803 } 804 805 Nv04ControlWithSecInfo(pApi, secInfo); 806 807 if ((pApi->status != NV_OK) && (priv != NULL)) 808 { 809 // 810 // No need to reset `register_or_refcount` as it might be set 811 // for previous successful calls. We let it clear with FD close. 812 // 813 nv_put_file_private(priv); 814 815 secInfo.gpuOsInfo = NULL; 816 } 817 818 break; 819 } 820 821 case NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO: 822 { 823 NVOS56_PARAMETERS *pApi = data; 824 void *pOldCpuAddress; 825 void *pNewCpuAddress; 826 827 NV_CTL_DEVICE_ONLY(nv); 828 829 if (dataSize != sizeof(NVOS56_PARAMETERS)) 830 { 831 rmStatus = NV_ERR_INVALID_ARGUMENT; 832 goto done; 833 } 834 835 pOldCpuAddress = NvP64_VALUE(pApi->pOldCpuAddress); 836 pNewCpuAddress = NvP64_VALUE(pApi->pNewCpuAddress); 837 838 pApi->status = rm_update_device_mapping_info(pApi->hClient, 839 pApi->hDevice, 840 pApi->hMemory, 841 pOldCpuAddress, 842 pNewCpuAddress); 843 break; 844 } 845 846 case NV_ESC_RM_NVLOG_CTRL: 847 { 848 NV_NVLOG_CTRL_PARAMS *pParams = data; 849 850 NV_CTL_DEVICE_ONLY(nv); 851 852 if (!osIsAdministrator()) 853 { 854 rmStatus = NV_ERR_INSUFFICIENT_PERMISSIONS; 855 pParams->status = rmStatus; 856 goto done; 857 } 858 859 switch (pParams->ctrl) 860 { 861 // Do not use NVOC _DISPATCH here as it dereferences NULL RmClientResource* 862 case NV0000_CTRL_CMD_NVD_GET_NVLOG_INFO: 863 rmStatus = cliresCtrlCmdNvdGetNvlogInfo_IMPL(NULL, &pParams->params.getNvlogInfo); 864 break; 865 case NV0000_CTRL_CMD_NVD_GET_NVLOG_BUFFER_INFO: 866 rmStatus = cliresCtrlCmdNvdGetNvlogBufferInfo_IMPL(NULL, &pParams->params.getNvlogBufferInfo); 867 break; 868 case NV0000_CTRL_CMD_NVD_GET_NVLOG: 869 rmStatus = cliresCtrlCmdNvdGetNvlog_IMPL(NULL, &pParams->params.getNvlog); 870 break; 871 default: 872 rmStatus = NV_ERR_NOT_SUPPORTED; 873 break; 874 } 875 876 pParams->status = rmStatus; 877 goto done; 878 } 879 880 case NV_ESC_REGISTER_FD: 881 { 882 nv_ioctl_register_fd_t *params = data; 883 void *priv = NULL; 884 nv_file_private_t *ctl_nvfp; 885 886 if (dataSize != sizeof(nv_ioctl_register_fd_t)) 887 { 888 rmStatus = NV_ERR_INVALID_ARGUMENT; 889 goto done; 890 } 891 892 // LOCK: acquire API lock 893 rmStatus = rmapiLockAcquire(API_LOCK_FLAGS_NONE, RM_LOCK_MODULES_OSAPI); 894 if (rmStatus != NV_OK) 895 goto done; 896 897 // If there is already a ctl fd registered on this nvfp, fail. 898 if (nvfp->ctl_nvfp != NULL) 899 { 900 // UNLOCK: release API lock 901 rmapiLockRelease(); 902 rmStatus = NV_ERR_INVALID_STATE; 903 goto done; 904 } 905 906 // 907 // Note that this call is valid for both "actual" devices and ctrl 908 // devices. In particular, NV_ESC_ALLOC_OS_EVENT can be used with 909 // both types of devices. 910 // But, the ctl_fd passed in should always correspond to a control FD. 911 // 912 ctl_nvfp = nv_get_file_private(params->ctl_fd, 913 NV_TRUE, /* require ctl fd */ 914 &priv); 915 if (ctl_nvfp == NULL) 916 { 917 // UNLOCK: release API lock 918 rmapiLockRelease(); 919 rmStatus = NV_ERR_INVALID_ARGUMENT; 920 goto done; 921 } 922 923 // Disallow self-referential links, and disallow links to FDs that 924 // themselves have a link. 925 if ((ctl_nvfp == nvfp) || (ctl_nvfp->ctl_nvfp != NULL)) 926 { 927 nv_put_file_private(priv); 928 // UNLOCK: release API lock 929 rmapiLockRelease(); 930 rmStatus = NV_ERR_INVALID_ARGUMENT; 931 goto done; 932 } 933 934 // Check to avoid cyclic dependency with device refcounting 935 if (!portAtomicCompareAndSwapU32(&nvfp->register_or_refcount, 936 NVFP_TYPE_REGISTERED, 937 NVFP_TYPE_NONE)) 938 { 939 nv_put_file_private(priv); 940 // UNLOCK: release API lock 941 rmapiLockRelease(); 942 rmStatus = NV_ERR_IN_USE; 943 goto done; 944 } 945 946 // 947 // nvfp->ctl_nvfp is read outside the lock, so set it atomically. 948 // Note that once set, this can never be removed until the fd 949 // associated with nvfp is closed. We hold on to 'priv' until the 950 // fd is closed, too, to ensure that the fd associated with 951 // ctl_nvfp remains valid. 952 // 953 portAtomicSetSize(&nvfp->ctl_nvfp, ctl_nvfp); 954 nvfp->ctl_nvfp_priv = priv; 955 956 // UNLOCK: release API lock 957 rmapiLockRelease(); 958 959 // NOTE: nv_put_file_private(priv) is not called here. It MUST be 960 // called during cleanup of this nvfp. 961 rmStatus = NV_OK; 962 break; 963 } 964 965 default: 966 { 967 NV_PRINTF(LEVEL_ERROR, "unknown NVRM ioctl command: 0x%x\n", cmd); 968 goto done; 969 } 970 } 971 972 rmStatus = NV_OK; 973 done: 974 975 return rmStatus; 976 } 977