1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 1993-2024 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 * @file
26 * @brief Memory descriptor handling utility routines.
27 */
28
29 #include "gpu/mem_mgr/mem_desc.h"
30
31 #include "gpu/bif/kernel_bif.h"
32
33 #include "os/os.h"
34
35 #include "gpu_mgr/gpu_mgr.h"
36 #include "core/locks.h"
37 #include "mem_mgr/io_vaspace.h"
38 #include "mem_mgr/virt_mem_mgr.h"
39 #include "core/system.h"
40 #include "vgpu/vgpu_util.h"
41 #include "platform/sli/sli.h"
42 #include "resserv/rs_client.h"
43
44 #include "gpu/mem_mgr/virt_mem_allocator.h"
45
46 #include "rmconfig.h"
47 #include "vgpu/rpc.h"
48 #include "mem_mgr/mem.h"
49
50 #include "gpu/mem_mgr/mem_mgr.h"
51 #include "gpu/mem_mgr/mem_utils.h"
52
53 #include "gpu/mem_mgr/heap.h"
54
55 #include "gpu/mem_sys/kern_mem_sys.h"
56 #include "mem_mgr/video_mem.h"
57
58 #include "mem_mgr/ctx_buf_pool.h"
59
60 #include "nvrm_registry.h" // For memdescOverrideInstLoc*()
61
62 #include "rmapi/rmapi.h"
63 #include "rmapi/rs_utils.h"
64 #include "class/cl0071.h" // NV01_MEMORY_SYSTEM_OS_DESCRIPTOR
65
66 #include "gpu/bus/kern_bus.h"
67
68 // Structure for keeping track of BAR1 mappings
69 typedef struct
70 {
71 NvU64 FbAperture;
72 NvU64 FbApertureLen;
73 NvP64 pPriv;
74 } FB_MAPPING_INFO;
75
76 //
77 // Common address space lists
78 //
79 const NV_ADDRESS_SPACE ADDRLIST_FBMEM_PREFERRED[] = {ADDR_FBMEM, ADDR_SYSMEM, ADDR_UNKNOWN};
80 const NV_ADDRESS_SPACE ADDRLIST_SYSMEM_PREFERRED[] = {ADDR_SYSMEM, ADDR_FBMEM, ADDR_UNKNOWN};
81 const NV_ADDRESS_SPACE ADDRLIST_FBMEM_ONLY[] = {ADDR_FBMEM, ADDR_UNKNOWN};
82 const NV_ADDRESS_SPACE ADDRLIST_SYSMEM_ONLY[] = {ADDR_SYSMEM, ADDR_UNKNOWN};
83
84 // XXX These could probably encode the whole list in the u32 bits.
memdescAddrSpaceListToU32(const NV_ADDRESS_SPACE * addrlist)85 NvU32 memdescAddrSpaceListToU32(const NV_ADDRESS_SPACE *addrlist)
86 {
87 if (addrlist == ADDRLIST_FBMEM_PREFERRED)
88 return 1;
89 else if (addrlist == ADDRLIST_SYSMEM_PREFERRED)
90 return 2;
91 else if (addrlist == ADDRLIST_FBMEM_ONLY)
92 return 3;
93 else if (addrlist == ADDRLIST_SYSMEM_ONLY)
94 return 4;
95 else
96 return 0;
97 }
98
memdescU32ToAddrSpaceList(NvU32 index)99 const NV_ADDRESS_SPACE *memdescU32ToAddrSpaceList(NvU32 index)
100 {
101 switch (index)
102 {
103 case 1: return ADDRLIST_FBMEM_PREFERRED;
104 case 2: return ADDRLIST_SYSMEM_PREFERRED;
105 case 3: return ADDRLIST_FBMEM_ONLY;
106 case 4: return ADDRLIST_SYSMEM_ONLY;
107 default:
108 return NULL;
109 }
110 }
111
112 /*
113 * @brief Setting a MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE has to initialize
114 * pHeap and bUsingSubAllocator flags
115 */
_memdescSetSubAllocatorFlag(OBJGPU * pGpu,PMEMORY_DESCRIPTOR pMemDesc,NvBool bSet)116 static NV_STATUS _memdescSetSubAllocatorFlag
117 (
118 OBJGPU *pGpu,
119 PMEMORY_DESCRIPTOR pMemDesc,
120 NvBool bSet
121 )
122 {
123 NV_ASSERT_OR_RETURN(pGpu != NULL, NV_ERR_INVALID_ARGUMENT);
124
125 if (!bSet)
126 {
127 NV_PRINTF(LEVEL_ERROR,
128 "Unsetting MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE not supported\n");
129 NV_ASSERT(0);
130 return NV_ERR_INVALID_ARGUMENT;
131 }
132
133 NV_ASSERT(!(pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL));
134
135 // Set flag forcing the allocation to fall into suballocator
136 pMemDesc->_flags |= MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE;
137
138 {
139 Heap *pHeap = pMemDesc->pHeap;
140 NvBool bForceSubheap = NV_FALSE;
141
142 NV_ASSERT(pHeap == NULL || pHeap->heapType == HEAP_TYPE_PHYS_MEM_SUBALLOCATOR);
143
144 if (pMemDesc->_flags & MEMDESC_FLAGS_FORCE_ALLOC_FROM_SUBHEAP)
145 {
146 bForceSubheap = NV_TRUE;
147 }
148
149 if (pHeap == NULL)
150 pHeap = memmgrGetDeviceSuballocator(GPU_GET_MEMORY_MANAGER(pGpu), bForceSubheap);
151
152 NV_ASSERT_OR_RETURN(pHeap != NULL, NV_ERR_INVALID_STATE);
153
154 if (pHeap->heapType == HEAP_TYPE_PHYS_MEM_SUBALLOCATOR)
155 {
156 NV_ASSERT_OK_OR_RETURN(vgpuGetCallingContextGfid(pGpu, &pMemDesc->gfid));
157 pMemDesc->bUsingSuballocator = NV_TRUE;
158 }
159 }
160
161 return NV_OK;
162 }
163
164 /*!
165 * @brief Initializing GFID for guest allocated memdescs
166 */
_memdescSetGuestAllocatedFlag(OBJGPU * pGpu,PMEMORY_DESCRIPTOR pMemDesc,NvBool bSet)167 static NV_STATUS _memdescSetGuestAllocatedFlag
168 (
169 OBJGPU *pGpu,
170 PMEMORY_DESCRIPTOR pMemDesc,
171 NvBool bSet
172 )
173 {
174 // for VGPU header scrubbing in Open Orin package
175
176 NV_ASSERT_OR_RETURN(pGpu != NULL, NV_ERR_INVALID_ARGUMENT);
177
178 if (!bSet)
179 {
180 NV_PRINTF(LEVEL_ERROR,
181 "Unsetting MEMDESC_FLAGS_GUEST_ALLOCATED not supported\n");
182 NV_ASSERT(0);
183 return NV_ERR_INVALID_ARGUMENT;
184 }
185
186 NV_ASSERT_OK_OR_RETURN(vgpuGetCallingContextGfid(pGpu, &pMemDesc->gfid));
187 pMemDesc->_flags |= MEMDESC_FLAGS_GUEST_ALLOCATED;
188
189 return NV_OK;
190 }
191
192 /*!
193 * @brief Allocate and initialize a new empty memory descriptor
194 *
195 * Allocate a new memory descriptor. This allocates the memory descriptor
196 * only. memdescAlloc or memdescDescribe are later used to allocate or associate
197 * memory to the memory descriptor.
198 *
199 * This routine takes size and the physical contiguous of the future allocation
200 * in order to size the PTE array for non-contiguous requests.
201 *
202 * memdescDestroy should be called to free a memory descriptor.
203 *
204 * If MEMDESC_FLAGS_PRE_ALLOCATED is specified, use the memory descriptor
205 * supplied by the client instead of allocating a new one.
206 *
207 * @param[out] ppMemDesc Return pointer to new memory descriptor
208 * @param[in] pGpu
209 * @param[in] Size Size of memory descriptor in bytes.
210 * @param[in] PhysicallyContiguous Need physical contig or can it be scattered?
211 * @param[in] AddressSpace NV_ADDRESS_SPACE requested
212 * @param[in] CpuCacheAttrib CPU cacheability requested
213 * @param[in] Flags MEMDESC_FLAGS_*
214 *
215 * @returns NV_OK on success
216 */
217 NV_STATUS
memdescCreate(MEMORY_DESCRIPTOR ** ppMemDesc,OBJGPU * pGpu,NvU64 Size,NvU64 Alignment,NvBool PhysicallyContiguous,NV_ADDRESS_SPACE AddressSpace,NvU32 CpuCacheAttrib,NvU64 Flags)218 memdescCreate
219 (
220 MEMORY_DESCRIPTOR **ppMemDesc,
221 OBJGPU *pGpu,
222 NvU64 Size,
223 NvU64 Alignment,
224 NvBool PhysicallyContiguous,
225 NV_ADDRESS_SPACE AddressSpace,
226 NvU32 CpuCacheAttrib,
227 NvU64 Flags
228 )
229 {
230 MEMORY_DESCRIPTOR *pMemDesc;
231 NvU64 allocSize, MdSize, PageCount;
232 NvU32 gpuCacheAttrib = NV_MEMORY_UNCACHED;
233 NV_STATUS status = NV_OK;
234
235
236 allocSize = Size;
237
238 //
239 // this memdesc may have gotten forced to sysmem if no carveout,
240 // but for VPR it needs to be in vidmem, so check and re-direct here,
241 // unless running with zero-FB
242 //
243 if ((AddressSpace != ADDR_UNKNOWN) &&
244 (Flags & MEMDESC_ALLOC_FLAGS_PROTECTED) &&
245 (!pGpu->getProperty(pGpu, PDB_PROP_GPU_BROKEN_FB) ||
246 gpuIsCacheOnlyModeEnabled(pGpu)))
247 {
248 AddressSpace = ADDR_FBMEM;
249 }
250
251 if (pGpu != NULL)
252 {
253 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
254
255 if (((AddressSpace == ADDR_SYSMEM) || (AddressSpace == ADDR_UNKNOWN)) &&
256 !(Flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL))
257 {
258 if (pMemoryManager && pMemoryManager->sysmemPageSize)
259 {
260 allocSize = RM_ALIGN_UP(allocSize, pMemoryManager->sysmemPageSize);
261 if (allocSize < Size)
262 {
263 return NV_ERR_INVALID_ARGUMENT;
264 }
265 }
266 }
267
268 if (RMCFG_FEATURE_PLATFORM_MODS || IsT194(pGpu) || IsT234(pGpu))
269 {
270 if ( (AddressSpace == ADDR_FBMEM) &&
271 !(Flags & MEMDESC_ALLOC_FLAGS_PROTECTED) &&
272 memmgrGetUsableMemSizeMB_HAL(pGpu, pMemoryManager) == 0 &&
273 gpuIsUnifiedMemorySpaceEnabled(pGpu))
274 {
275 // On Tegra, force sysmem if carveout and SMMU are not available
276 AddressSpace = ADDR_SYSMEM;
277 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_ALL_INST_IN_SYSMEM))
278 {
279 CpuCacheAttrib = pGpu->instCacheOverride;
280 }
281 }
282
283 //
284 // Support for aligned contiguous SYSMEM allocations.
285 //
286 if ((AddressSpace == ADDR_SYSMEM || AddressSpace == ADDR_UNKNOWN) &&
287 PhysicallyContiguous && (Alignment > RM_PAGE_SIZE))
288 {
289 if (!portSafeAddU64(allocSize, (Alignment - RM_PAGE_SIZE), &allocSize))
290 {
291 return NV_ERR_INVALID_ARGUMENT;
292 }
293 }
294 }
295 }
296
297 //
298 //
299 // Note that we allocate one extra PTE, since we don't know what the PteAdjust
300 // is yet; if the PteAdjust is zero, we simply won't use it. This is in the
301 // MEMORY_DESCRIPTOR structure definition.
302 //
303 // RM_PAGE_SIZE is 4k and RM_PAGE_SHIFT is 12, so shift operation can be
304 // modified from ((allocSize + RM_PAGE_SIZE-1) >> RM_PAGE_SHIFT) to below as
305 // (4k >> 12 = 1). This modification helps us to avoid overflow of variable
306 // allocSize, in case caller of this function passes highest value of NvU64.
307 //
308 // If allocSize is passed as 0, PageCount should be returned as 0.
309 //
310 if (allocSize == 0)
311 {
312 PageCount = 0;
313 }
314 else
315 {
316 PageCount = ((allocSize - 1) >> RM_PAGE_SHIFT) + 1;
317 }
318
319 if (PhysicallyContiguous)
320 {
321 MdSize = sizeof(MEMORY_DESCRIPTOR);
322 }
323 else
324 {
325 MdSize = sizeof(MEMORY_DESCRIPTOR) +
326 (sizeof(RmPhysAddr) * PageCount);
327 NV_ASSERT(MdSize <= 0xffffffffULL);
328 if (MdSize > 0xffffffffULL)
329 return NV_ERR_INSUFFICIENT_RESOURCES;
330 }
331
332 if (Flags & MEMDESC_FLAGS_PAGED_SYSMEM)
333 {
334 // The flag MEMDESC_FLAGS_PAGED_SYSMEM is only for Windows
335 return NV_ERR_NOT_SUPPORTED;
336 }
337
338 if (Flags & MEMDESC_FLAGS_PRE_ALLOCATED)
339 {
340 // Only fixed sized memDesc can be supported
341 if (PhysicallyContiguous == NV_FALSE)
342 {
343 return NV_ERR_BUFFER_TOO_SMALL;
344 }
345
346 NV_ASSERT_OR_RETURN(*ppMemDesc, NV_ERR_NOT_SUPPORTED);
347
348 pMemDesc = *ppMemDesc;
349 }
350 else
351 {
352 pMemDesc = portMemAllocNonPaged((NvU32)MdSize);
353 if (pMemDesc == NULL)
354 {
355 return NV_ERR_NO_MEMORY;
356 }
357 }
358
359 portMemSet(pMemDesc, 0, (NvU32)MdSize);
360
361 // Fill in initial non-zero parameters
362 pMemDesc->pGpu = pGpu;
363 pMemDesc->Size = Size;
364 pMemDesc->PageCount = PageCount;
365 pMemDesc->ActualSize = allocSize;
366 pMemDesc->_addressSpace = AddressSpace;
367 pMemDesc->RefCount = 1;
368 pMemDesc->DupCount = 1;
369 pMemDesc->_subDeviceAllocCount = 1;
370 pMemDesc->_flags = Flags;
371 pMemDesc->_gpuCacheAttrib = gpuCacheAttrib;
372 pMemDesc->_gpuP2PCacheAttrib = NV_MEMORY_UNCACHED;
373 pMemDesc->Alignment = Alignment;
374 pMemDesc->gfid = GPU_GFID_PF;
375 pMemDesc->bUsingSuballocator = NV_FALSE;
376 pMemDesc->bDeferredFree = NV_FALSE;
377 pMemDesc->numaNode = NV0000_CTRL_NO_NUMA_NODE;
378
379 pMemDesc->libosRegionHandle = 0;
380 pMemDesc->baseVirtualAddress = 0;
381
382 // parameter to determine page granularity
383 pMemDesc->pageArrayGranularity = RM_PAGE_SIZE;
384
385 memdescSetCpuCacheAttrib(pMemDesc, CpuCacheAttrib);
386
387 // Set any additional flags
388 pMemDesc->_flags |= MEMDESC_FLAGS_KERNEL_MODE;
389 if (PhysicallyContiguous)
390 pMemDesc->_flags |= MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS;
391 else
392 pMemDesc->_flags &= ~MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS;
393
394 // OBJHEAP may not be created at this time and pMemDesc->pHeap may be NULL after this if-else
395 if (Flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL)
396 {
397 pMemDesc->_flags |= MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL;
398 pMemDesc->_flags &= ~MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE;
399 }
400 else if (Flags & MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE)
401 {
402 NV_ASSERT_OK_OR_GOTO(status, _memdescSetSubAllocatorFlag(pGpu, pMemDesc, NV_TRUE), failed);
403 }
404
405 // In case of guest allocated memory, just initialize GFID
406 if (Flags & MEMDESC_FLAGS_GUEST_ALLOCATED)
407 {
408 NV_ASSERT_OK_OR_GOTO(status, _memdescSetGuestAllocatedFlag(pGpu, pMemDesc, NV_TRUE), failed);
409 }
410
411 failed:
412 if (status != NV_OK)
413 {
414 if (!(Flags & MEMDESC_FLAGS_PRE_ALLOCATED))
415 {
416 portMemFree(pMemDesc);
417 }
418 }
419 else
420 {
421 *ppMemDesc = pMemDesc;
422 }
423
424 return status;
425 }
426
427 /*!
428 * @brief Initialize an caller allocated memory descriptor
429 *
430 * Helper to make it easier to get the memDesc **, and typically used
431 * with memdescDescribe.
432 *
433 * Only can be used for physically contiguous regions with a fixed
434 * size PTE array.
435 *
436 * memdescDestroy should be called to free a memory descriptor.
437 *
438 * If MEMDESC_FLAGS_PRE_ALLOCATED is specified, use the memory descriptor
439 * supplied by the client instead of allocating a new one.
440 *
441 * @param[out] pMemDesc Return pointer to new memory descriptor
442 * @param[in] pGpu
443 * @param[in] Size Size of memory descriptor in bytes
444 * @param[in] AddressSpace NV_ADDRESS_SPACE requested
445 * @param[in] CpuCacheAttrib CPU cacheability requested
446 * @param[in] Flags MEMDESC_FLAGS_*
447 *
448 * @returns void with no malloc there should be no failure cases
449 */
450 void
memdescCreateExisting(MEMORY_DESCRIPTOR * pMemDesc,OBJGPU * pGpu,NvU64 Size,NV_ADDRESS_SPACE AddressSpace,NvU32 CpuCacheAttrib,NvU64 Flags)451 memdescCreateExisting
452 (
453 MEMORY_DESCRIPTOR *pMemDesc,
454 OBJGPU *pGpu,
455 NvU64 Size,
456 NV_ADDRESS_SPACE AddressSpace,
457 NvU32 CpuCacheAttrib,
458 NvU64 Flags
459 )
460 {
461 NV_STATUS status;
462 status = memdescCreate(&pMemDesc, pGpu, Size, 0, NV_TRUE, AddressSpace,
463 CpuCacheAttrib,
464 Flags | MEMDESC_FLAGS_PRE_ALLOCATED | MEMDESC_FLAGS_SKIP_RESOURCE_COMPUTE);
465 NV_ASSERT(status == NV_OK);
466 }
467
468
469 /*!
470 * Increment ref count
471 */
memdescAddRef(MEMORY_DESCRIPTOR * pMemDesc)472 void memdescAddRef
473 (
474 MEMORY_DESCRIPTOR *pMemDesc
475 )
476 {
477 NV_ASSERT(pMemDesc != NULL);
478 ++(pMemDesc->RefCount);
479 }
480
481 /*!
482 * Decrement ref count
483 */
memdescRemoveRef(MEMORY_DESCRIPTOR * pMemDesc)484 void memdescRemoveRef
485 (
486 MEMORY_DESCRIPTOR *pMemDesc
487 )
488 {
489 NV_ASSERT_OR_RETURN_VOID(pMemDesc != NULL);
490 --(pMemDesc->RefCount);
491 }
492
493 //
494 // Destroy all IOMMU mappings under this memdesc, including child
495 // mappings for root memdescs.
496 //
497 // TODO: merge the new IOMMU paths with the SMMU paths (see bug 1625121).
498 //
499 static void
_memdescFreeIommuMappings(PMEMORY_DESCRIPTOR pMemDesc)500 _memdescFreeIommuMappings(PMEMORY_DESCRIPTOR pMemDesc)
501 {
502 #if (RMCFG_FEATURE_PLATFORM_UNIX || RMCFG_FEATURE_PLATFORM_MODS) && !NVCPU_IS_ARM
503 PIOVAMAPPING pIovaMapping = pMemDesc->_pIommuMappings;
504
505 if (!pIovaMapping)
506 return;
507
508 if (memdescIsSubMemoryMemDesc(pMemDesc))
509 {
510 iovaMappingDestroy(pIovaMapping);
511 return;
512 }
513
514 while (pIovaMapping)
515 {
516 PIOVAMAPPING pTmpIovaMapping = pIovaMapping->pNext;
517 iovaMappingDestroy(pIovaMapping);
518 pIovaMapping = pTmpIovaMapping;
519 }
520
521 pMemDesc->_pIommuMappings = NULL;
522 #endif
523 }
524
525 /*!
526 * Destroy a memory descriptor if last reference is released
527 *
528 * If the memory descriptor is down to one reference, we need
529 * to check with the bus code check if that reference needs
530 * to be reclaimed.
531 *
532 * @param[in] pMemDesc Memory descriptor to be destroyed
533 *
534 * @returns None
535 */
536 void
memdescDestroy(MEMORY_DESCRIPTOR * pMemDesc)537 memdescDestroy
538 (
539 MEMORY_DESCRIPTOR *pMemDesc
540 )
541 {
542 // Allow null frees
543 if (!pMemDesc)
544 {
545 return;
546 }
547
548 memdescRemoveRef(pMemDesc);
549
550 // if still more references are there for pMemDesc (pMemDesc->RefCount != 0), then bail out.
551
552 if (pMemDesc->RefCount == 0)
553 {
554 MEM_DESC_DESTROY_CALLBACK *pCb = memdescGetDestroyCallbackList(pMemDesc);
555 MEM_DESC_DESTROY_CALLBACK *pNext;
556
557 if (pMemDesc->_flags & MEMDESC_FLAGS_RESTORE_PTE_KIND_ON_FREE)
558 {
559 NV_ASSERT_OK(kbusUpdateStaticBar1VAMapping_HAL(pMemDesc->pGpu,
560 GPU_GET_KERNEL_BUS(pMemDesc->pGpu), pMemDesc,
561 NV_TRUE));
562 }
563
564 if (pMemDesc->_flags & MEMDESC_FLAGS_DUMMY_TOPLEVEL)
565 {
566 // When called from RmFreeFrameBuffer() and memdescFree could not do it because it is unallocated.
567 pMemDesc->_pNext = NULL;
568 pMemDesc->_subDeviceAllocCount = 1;
569 }
570
571 NV_ASSERT(pMemDesc->childDescriptorCnt == 0);
572 NV_ASSERT(pMemDesc->_addressSpace == ADDR_FBMEM || pMemDesc->pHeap == NULL);
573
574 //
575 // If there is private memdata, use the CB to free
576 //
577 if (pMemDesc->_pMemData && pMemDesc->_pMemDataReleaseCallback)
578 {
579 pMemDesc->_pMemDataReleaseCallback(pMemDesc);
580 }
581
582 if (pMemDesc->bDeferredFree)
583 {
584 memdescFree(pMemDesc);
585 }
586 else if (pMemDesc->Allocated != 0)
587 {
588 //
589 // The caller forgot to free the actual memory before destroying the memdesc.
590 // Please fix this by calling memdescFree().
591 // To prevent memory leaks, we explicitly free here until its fixed elsewhere.
592 //
593 NV_PRINTF(LEVEL_ERROR, "Destroying unfreed memory %p\n", pMemDesc);
594 NV_PRINTF(LEVEL_ERROR, "Please call memdescFree()\n");
595 memdescFree(pMemDesc);
596 NV_ASSERT(!pMemDesc->Allocated);
597 }
598
599 if (memdescGetStandbyBuffer(pMemDesc))
600 {
601 memdescFree(memdescGetStandbyBuffer(pMemDesc));
602 memdescDestroy(memdescGetStandbyBuffer(pMemDesc));
603 memdescSetStandbyBuffer(pMemDesc, NULL);
604 }
605
606 //
607 // Submemory descriptors will be destroyed without going through a free
608 // path, so we need to make sure that we remove the IOMMU submapping
609 // here. For root descriptors, we should already have removed all the
610 // associated IOVA mappings.
611 //
612 // However, for memory descriptors that weren't allocated by the RM,
613 // (e.g., were created from a user allocation), we won't go through a
614 // free path at all. In this case, mappings for other GPUs may still be
615 // attached to this root memory descriptor, so release them now.
616 //
617 _memdescFreeIommuMappings(pMemDesc);
618
619 // Notify all interested parties of destruction
620 while (pCb)
621 {
622 pNext = pCb->pNext;
623 pCb->destroyCallback(pMemDesc->pGpu, pCb->pObject, pMemDesc);
624 // pCb is now invalid
625 pCb = pNext;
626 }
627
628 portMemFree(pMemDesc->pPteSpaMappings);
629 pMemDesc->pPteSpaMappings = NULL;
630 portMemFree(pMemDesc->pSubMemDescList);
631 pMemDesc->pSubMemDescList = NULL;
632
633 if (pMemDesc->pPteEgmMappings != NULL)
634 {
635 portMemFree(pMemDesc->pPteEgmMappings);
636 pMemDesc->pPteEgmMappings = NULL;
637 }
638
639 if (pMemDesc->_pParentDescriptor)
640 {
641 if ((pMemDesc->_flags & MEMDESC_FLAGS_PRE_ALLOCATED) == 0)
642 pMemDesc->_pParentDescriptor->childDescriptorCnt--;
643 memdescDestroy(pMemDesc->_pParentDescriptor);
644 pMemDesc->_pParentDescriptor = NULL;
645 }
646
647 // Verify memdesc is not top
648 NV_ASSERT(memdescHasSubDeviceMemDescs(pMemDesc) == NV_FALSE);
649
650 if ((pMemDesc->_flags & MEMDESC_FLAGS_PRE_ALLOCATED) == 0)
651 {
652 portMemFree(pMemDesc);
653 }
654 }
655 }
656
657 /*!
658 * @brief Function that frees subdevice memory descriptors. If there are no
659 * subdevice memory descriptors function just simply resets memdesc structure.
660 * Top level memory descriptor is not destroyed.
661 *
662 * @param[in,out] pMemDesc Top level memory descriptor.
663 *
664 * @returns None
665 */
666 static void
_memSubDeviceFreeAndDestroy(MEMORY_DESCRIPTOR * pMemDesc)667 _memSubDeviceFreeAndDestroy
668 (
669 MEMORY_DESCRIPTOR *pMemDesc
670 )
671 {
672 MEMORY_DESCRIPTOR *pSubDevMemDesc = pMemDesc->_pNext;
673 MEMORY_DESCRIPTOR *pNextMemDesc;
674 OBJGPU *pGpu = pMemDesc->pGpu;
675 NvBool bBcState;
676
677 // No subdevice memdescs
678 if (pSubDevMemDesc == NULL || pGpu == NULL)
679 {
680 return;
681 }
682
683 bBcState = gpumgrGetBcEnabledStatus(pGpu);
684 gpumgrSetBcEnabledStatus(pGpu, NV_FALSE);
685
686 do
687 {
688 pNextMemDesc = pSubDevMemDesc->_pNext;
689 pSubDevMemDesc->_pNext = NULL;
690 memdescFree(pSubDevMemDesc);
691 memdescDestroy(pSubDevMemDesc);
692 pSubDevMemDesc = pNextMemDesc;
693 } while (pSubDevMemDesc != NULL);
694
695 gpumgrSetBcEnabledStatus(pGpu, bBcState);
696 }
697
698 /*!
699 * @brief Lower memdesc allocation layer for the special case of allocation
700 in the VPR region when MODS is managing it.
701 *
702 * @param[in] pMemDesc Memory descriptor to allocate
703 *
704 * @returns NV_OK on successful allocation.
705 * NV_ERR_NOT_SUPPORTED if not supported
706 */
707 static NV_STATUS
_memdescAllocVprRegion(MEMORY_DESCRIPTOR * pMemDesc)708 _memdescAllocVprRegion
709 (
710 MEMORY_DESCRIPTOR *pMemDesc
711 )
712 {
713 return NV_ERR_NOT_SUPPORTED;
714 }
715
716 /*!
717 * @brief Allocate and populate the EGM array based off of the already
718 * populated _pteArray of the memdesc
719 *
720 * @param[in] pMemDesc Memory descriptor to allocate EGM array in
721 *
722 * @returns NV_OK on successful allocation. NV_ERR if not.
723 */
724 static NV_INLINE NV_STATUS
_memdescAllocEgmArray(MEMORY_DESCRIPTOR * pMemDesc)725 _memdescAllocEgmArray
726 (
727 MEMORY_DESCRIPTOR *pMemDesc
728 )
729 {
730 //
731 // Since we allocate an extra PTE, we need to account for that in case we
732 // need it for the EGM array. This is why there is a '+ 1' for pageCount.
733 //
734 NvU64 i;
735 NvU64 pageCount = pMemDesc->PageCount + 1;
736
737 //
738 // Get the root memory descriptor's memory manager to be able to get the
739 // EGM base of that GPU, instead of the mapping GPU in the case of this
740 // array being used in a submemdesc. The submemdesc should always have the
741 // mapping of the root since it's a submemdesc derived from the root, and
742 // not based on the mapping GPU.
743 //
744 MEMORY_DESCRIPTOR *pRootMemDesc = memdescGetRootMemDesc(pMemDesc, NULL);
745 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pRootMemDesc->pGpu);
746
747 if (pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS)
748 {
749 pageCount = 1;
750 }
751
752 if (pMemDesc->pPteEgmMappings == NULL)
753 {
754 pMemDesc->pPteEgmMappings = portMemAllocNonPaged(sizeof(RmPhysAddr) * pageCount);
755 }
756
757 NV_ASSERT_OR_RETURN(pMemDesc->pPteEgmMappings != NULL, NV_ERR_NO_MEMORY);
758
759 for (i = 0; i < pageCount; i++)
760 {
761 pMemDesc->pPteEgmMappings[i] = pMemDesc->_pteArray[i] -
762 pMemoryManager->localEgmBasePhysAddr;
763 }
764
765 return NV_OK;
766 }
767
768 /*!
769 * @brief Lower memdesc allocation layer. Provides underlying allocation
770 * functionality.
771 *
772 * @param[in,out] pMemDesc Memory descriptor to allocate
773 *
774 * @returns NV_OK on successful allocation. Various NV_ERR_GENERIC codes otherwise.
775 */
776 static NV_STATUS
_memdescAllocInternal(MEMORY_DESCRIPTOR * pMemDesc)777 _memdescAllocInternal
778 (
779 MEMORY_DESCRIPTOR *pMemDesc
780 )
781 {
782 OBJGPU *pGpu = pMemDesc->pGpu;
783 NV_STATUS status = NV_OK;
784 FB_ALLOC_INFO *pFbAllocInfo = NULL;
785 FB_ALLOC_PAGE_FORMAT *pFbAllocPageFormat = NULL;
786
787 if (pMemDesc->Allocated)
788 {
789 NV_ASSERT(!pMemDesc->Allocated);
790 return NV_ERR_INVALID_OBJECT_BUFFER;
791 }
792
793 // Special case of an allocation request in MODS managed VPR region.
794 status = _memdescAllocVprRegion(pMemDesc);
795 if (status != NV_ERR_NOT_SUPPORTED)
796 goto done;
797
798 switch (pMemDesc->_addressSpace)
799 {
800 case ADDR_EGM:
801 case ADDR_SYSMEM:
802 // System memory can be obtained from osAllocPages
803 status = osAllocPages(pMemDesc);
804 if (status != NV_OK)
805 {
806 goto done;
807 }
808
809 if (memdescIsEgm(pMemDesc))
810 {
811 NV_ASSERT_OK_OR_GOTO(status,
812 _memdescAllocEgmArray(pMemDesc),
813 done);
814 }
815
816 //
817 // The pages have been allocated, so mark the descriptor as
818 // allocated. The IOMMU-mapping code needs the memdesc to be
819 // allocated in order to create the mapping.
820 //
821 pMemDesc->Allocated = 1;
822
823 //
824 // TODO: merge new IOMMU paths with the SMMU paths below (see bug
825 // 1625121). For now they are parallel, and only one will be
826 // used.
827 //
828 if (!memdescGetFlag(pMemDesc, MEMDESC_FLAGS_CPU_ONLY) &&
829 !memdescIsEgm(pMemDesc) &&
830 !memdescGetFlag(pMemDesc, MEMDESC_FLAGS_SKIP_IOMMU_MAPPING))
831 {
832 status = memdescMapIommu(pMemDesc, pGpu->busInfo.iovaspaceId);
833 if (status != NV_OK)
834 {
835 pMemDesc->Allocated = 0;
836 osFreePages(pMemDesc);
837 goto done;
838 }
839 }
840
841 if (pMemDesc->_flags & MEMDESC_FLAGS_PROVIDE_IOMMU_MAP)
842 {
843 NV_PRINTF(LEVEL_ERROR, "SMMU mapping allocation is not supported for ARMv7.\n");
844 NV_ASSERT(0);
845 status = NV_ERR_NOT_SUPPORTED;
846 goto done;
847 }
848 else if ((pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS) &&
849 RMCFG_FEATURE_PLATFORM_MODS)
850 {
851 if (pMemDesc->Alignment > RM_PAGE_SIZE)
852 {
853 RmPhysAddr addr = memdescGetPhysAddr(pMemDesc, AT_CPU, 0);
854 NvU64 offset;
855
856 NV_ASSERT((addr & (RM_PAGE_SIZE - 1)) == 0);
857
858 NV_ASSERT((pMemDesc->Alignment & (pMemDesc->Alignment - 1)) == 0);
859 offset = addr & (pMemDesc->Alignment - 1);
860
861 if (offset)
862 {
863 NV_ASSERT((pMemDesc->PageCount * pMemDesc->pageArrayGranularity - pMemDesc->Size) >= offset);
864 NV_ASSERT(pMemDesc->PteAdjust == 0);
865 pMemDesc->PteAdjust += NvU64_LO32(pMemDesc->Alignment - offset);
866 }
867 }
868 }
869
870 break;
871 case ADDR_FBMEM:
872 {
873 Heap *pHeap = pMemDesc->pHeap;
874
875 if (RMCFG_FEATURE_PMA &&
876 (pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL))
877 {
878 CTX_BUF_POOL_INFO *pCtxBufPool = NULL;
879 pCtxBufPool = memdescGetCtxBufPool(pMemDesc);
880 NV_ASSERT_TRUE_OR_GOTO(status, pCtxBufPool != NULL, NV_ERR_INVALID_STATE, done);
881
882 // If pool is setup then allocate from pool
883 NV_ASSERT_OK_OR_GOTO(status, ctxBufPoolAllocate(pCtxBufPool, pMemDesc), done);
884 }
885 else
886 {
887 // XXX Hack!
888 MEMORY_ALLOCATION_REQUEST allocRequest = {0};
889 NV_MEMORY_ALLOCATION_PARAMS allocData = {0};
890 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
891 NvU64 requestedSize = pMemDesc->Size;
892
893 allocRequest.pUserParams = &allocData;
894
895 // Don't allow FB allocations if FB is broken unless running in L2 cache only mode
896 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_BROKEN_FB) &&
897 !gpuIsCacheOnlyModeEnabled(pGpu))
898 {
899 DBG_BREAKPOINT();
900 status = NV_ERR_BROKEN_FB;
901 goto done;
902 }
903
904 allocData.owner = HEAP_OWNER_RM_CHANNEL_CTX_BUFFER;
905 allocData.type = NVOS32_TYPE_IMAGE;
906 allocData.flags = NVOS32_ALLOC_FLAGS_ALIGNMENT_FORCE;
907
908 // remove the "grows_down" flag when bReservedMemAtBottom is set so as to move RM memory to the bottom.
909 if (!pMemoryManager->bReservedMemAtBottom)
910 {
911 allocData.flags |= NVOS32_ALLOC_FLAGS_FORCE_MEM_GROWS_DOWN;
912 }
913
914 // Allocate in high priority memory?
915 if (pMemDesc->_flags & MEMDESC_FLAGS_HIGH_PRIORITY)
916 {
917 allocData.attr2 |= DRF_DEF(OS32, _ATTR2, _PRIORITY, _HIGH);
918 }
919 else if (pMemDesc->_flags & MEMDESC_FLAGS_LOW_PRIORITY)
920 {
921 allocData.attr2 |= DRF_DEF(OS32, _ATTR2, _PRIORITY, _LOW);
922 }
923
924 allocData.size = pMemDesc->Size;
925 allocData.alignment = pMemDesc->Alignment;
926 allocRequest.pMemDesc = pMemDesc;
927
928 if (pMemDesc->_pageSize == RM_PAGE_SIZE)
929 {
930 allocData.attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _4KB);
931 }
932 else if (pMemDesc->_pageSize == RM_PAGE_SIZE_64K ||
933 pMemDesc->_pageSize == RM_PAGE_SIZE_128K)
934 {
935 allocData.attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _BIG);
936 }
937
938 allocData.flags |= pMemDesc->Alignment ?
939 NVOS32_ALLOC_FLAGS_ALIGNMENT_FORCE :
940 NVOS32_ALLOC_FLAGS_FORCE_ALIGN_HOST_PAGE;
941
942 if (pMemDesc->_flags & MEMDESC_FLAGS_FIXED_ADDRESS_ALLOCATE)
943 {
944 allocData.flags |= NVOS32_ALLOC_FLAGS_FIXED_ADDRESS_ALLOCATE;
945 allocData.offset = pMemDesc->_pteArray[0];
946 }
947
948 if (pMemDesc->_gpuCacheAttrib == NV_MEMORY_CACHED)
949 {
950 allocData.attr2 |= DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _YES);
951 }
952 else
953 {
954 // Force internal allocations to uncached unless explicitly requested.
955 allocData.attr2 |= DRF_DEF(OS32, _ATTR2, _GPU_CACHEABLE, _NO);
956 }
957
958 allocData.attr2 = FLD_SET_DRF(OS32, _ATTR2, _INTERNAL, _YES, allocData.attr2);
959
960 if (pMemDesc->_flags & MEMDESC_ALLOC_FLAGS_PROTECTED)
961 {
962 allocData.flags |= NVOS32_ALLOC_FLAGS_PROTECTED;
963 }
964
965 //
966 // Assume all RM internal allocations to go into protected (CPR)
967 // video memory unless specified otherwise explicitly
968 //
969 if (gpuIsCCFeatureEnabled(pGpu))
970 {
971 if (pMemDesc->_flags & MEMDESC_FLAGS_ALLOC_IN_UNPROTECTED_MEMORY)
972 {
973 //
974 // CC-TODO: Remove this check after non-CPR region is
975 // created. Not sure if RM will ever need to use non-CPR
976 // region for itself
977 //
978 NV_PRINTF(LEVEL_ERROR, "Non-CPR region still not created\n");
979 NV_ASSERT_OR_RETURN(0, NV_ERR_INVALID_ARGUMENT);
980 }
981 else
982 {
983 allocData.flags |= NVOS32_ALLOC_FLAGS_PROTECTED;
984 }
985 }
986
987 allocData.attr |= DRF_DEF(OS32, _ATTR, _PHYSICALITY, _CONTIGUOUS);
988
989 pFbAllocInfo = portMemAllocNonPaged(sizeof(FB_ALLOC_INFO));
990 NV_ASSERT_TRUE_OR_GOTO(status, pFbAllocInfo != NULL, NV_ERR_NO_MEMORY, done);
991
992 pFbAllocPageFormat = portMemAllocNonPaged(sizeof(FB_ALLOC_PAGE_FORMAT));
993 NV_ASSERT_TRUE_OR_GOTO(status, pFbAllocPageFormat != NULL, NV_ERR_NO_MEMORY, done);
994
995 portMemSet(pFbAllocInfo, 0, sizeof(FB_ALLOC_INFO));
996 portMemSet(pFbAllocPageFormat, 0, sizeof(FB_ALLOC_PAGE_FORMAT));
997 pFbAllocInfo->pageFormat = pFbAllocPageFormat;
998
999 memUtilsInitFBAllocInfo(&allocData, pFbAllocInfo, 0, 0); // Client/device N/A
1000
1001 status = memmgrAllocResources(pGpu, pMemoryManager, &allocRequest, pFbAllocInfo);
1002 if (status != NV_OK)
1003 goto done;
1004
1005 status = vidmemAllocResources(pGpu, pMemoryManager, &allocRequest, pFbAllocInfo, pHeap);
1006 if (status != NV_OK)
1007 goto done;
1008
1009 pMemDesc->Alignment = allocData.alignment;
1010
1011 // Update MemDesc GPU cacheability with results of allocation
1012 if (DRF_VAL(OS32, _ATTR2, _GPU_CACHEABLE, allocData.attr2) == NVOS32_ATTR2_GPU_CACHEABLE_YES)
1013 {
1014 pMemDesc->_gpuCacheAttrib = NV_MEMORY_CACHED;
1015 }
1016 else
1017 {
1018 pMemDesc->_gpuCacheAttrib = NV_MEMORY_UNCACHED;
1019 }
1020
1021 //
1022 // Adjust size to the requested size, not the heap rounded size. A number of callers
1023 // depend on this. In the future we will have the PageCount be accurate.
1024 //
1025 pMemDesc->Size = requestedSize;
1026 pMemDesc->PageCount = ((pMemDesc->Size + pMemDesc->PteAdjust + pMemDesc->pageArrayGranularity - 1) >>
1027 BIT_IDX_32(pMemDesc->pageArrayGranularity));
1028 }
1029 // We now have the memory
1030 pMemDesc->Allocated = 1;
1031
1032 // If the allocation succeeds and if its PhysMemSubAlloc, increment the refCount
1033 if ((status == NV_OK) && (pHeap != NULL) &&
1034 (pHeap->heapType == HEAP_TYPE_PHYS_MEM_SUBALLOCATOR))
1035 {
1036 heapAddRef(pHeap);
1037 }
1038 break;
1039 }
1040
1041 default:
1042 // Don't know how to do any other types of memory yet
1043 DBG_BREAKPOINT();
1044 status = NV_ERR_GENERIC;
1045 goto done;
1046 }
1047
1048 done:
1049 if (status == NV_OK)
1050 {
1051 memdescPrintMemdesc(pMemDesc, NV_TRUE, MAKE_NV_PRINTF_STR("memdesc allocated"));
1052 }
1053 else if (pMemDesc->pPteEgmMappings != NULL)
1054 {
1055 portMemFree(pMemDesc->pPteEgmMappings);
1056 pMemDesc->pPteEgmMappings = NULL;
1057 }
1058 portMemFree(pFbAllocPageFormat);
1059 portMemFree(pFbAllocInfo);
1060
1061 return status;
1062 }
1063
1064 /*!
1065 * @brief Upper memdesc allocation layer. Provides support for per-subdevice
1066 * sysmem buffers and lockless sysmem allocation.
1067 *
1068 * @param[in,out] pMemDesc Memory descriptor to allocate
1069 *
1070 * @returns NV_OK on successful allocation. Various NV_ERR_GENERIC codes otherwise.
1071 */
1072 NV_STATUS
memdescAlloc(MEMORY_DESCRIPTOR * pMemDesc)1073 memdescAlloc
1074 (
1075 MEMORY_DESCRIPTOR *pMemDesc
1076 )
1077 {
1078 OBJGPU *pGpu = pMemDesc->pGpu;
1079 NV_STATUS status = NV_OK;
1080 NvBool bcState = NV_FALSE;
1081 OBJSYS *pSys = SYS_GET_INSTANCE();
1082 NvBool reAcquire;
1083 NvU32 gpuMask = 0;
1084
1085 NV_ASSERT_OR_RETURN(!pMemDesc->Allocated, NV_ERR_INVALID_OBJECT_BUFFER);
1086
1087 switch (pMemDesc->_addressSpace)
1088 {
1089 case ADDR_SYSMEM:
1090 case ADDR_EGM:
1091 // Can't alloc sysmem on GSP firmware.
1092 if (RMCFG_FEATURE_PLATFORM_GSP && !memdescGetFlag(pMemDesc, MEMDESC_FLAGS_GUEST_ALLOCATED))
1093 {
1094 //
1095 // TO DO: Make this an error once existing allocations are cleaned up.
1096 // After that pHeap selection can be moved to memdescAllocInternal()
1097 //
1098 NV_PRINTF(LEVEL_WARNING,
1099 "WARNING sysmem alloc on GSP firmware\n");
1100 pMemDesc->_addressSpace = ADDR_FBMEM;
1101 pMemDesc->pHeap = GPU_GET_HEAP(pGpu);
1102 }
1103 //
1104 // If AMD SEV is enabled but CC or APM is not enabled on the GPU,
1105 // all RM and client allocations must to to unprotected sysmem.
1106 // So, we override any unprotected/protected flag set by either RM
1107 // or client.
1108 // If APM is enabled and RM is allocating sysmem for its internal use
1109 // use such memory has to be unprotected as protected sysmem is not
1110 // accessible to GPU
1111 //
1112 if ((sysGetStaticConfig(pSys))->bOsCCEnabled)
1113 {
1114 if (!gpuIsCCorApmFeatureEnabled(pGpu) ||
1115 (gpuIsApmFeatureEnabled(pGpu) &&
1116 !memdescGetFlag(pMemDesc, MEMDESC_FLAGS_SYSMEM_OWNED_BY_CLIENT)))
1117 {
1118 memdescSetFlag(pMemDesc,
1119 MEMDESC_FLAGS_ALLOC_IN_UNPROTECTED_MEMORY, NV_TRUE);
1120 }
1121 }
1122 else
1123 {
1124 //
1125 // This flag has no meaning on non-SEV systems. So, unset it. The
1126 // OS layer currently honours this flag irrespective of whether
1127 // SEV is enabled or not
1128 //
1129 memdescSetFlag(pMemDesc,
1130 MEMDESC_FLAGS_ALLOC_IN_UNPROTECTED_MEMORY, NV_FALSE);
1131 }
1132
1133 break;
1134 case ADDR_FBMEM:
1135 {
1136 //
1137 // When APM is enabled, all RM internal vidmem allocations go to
1138 // unprotected memory. There is an underlying assumption that
1139 // memdescAlloc won't be directly called in the client vidmem alloc
1140 // codepath. Note that memdescAlloc still gets called in the client
1141 // sysmem alloc codepath. See CONFCOMP-529
1142 //
1143 if (gpuIsApmFeatureEnabled(pGpu))
1144 {
1145 memdescSetFlag(pMemDesc,
1146 MEMDESC_FLAGS_ALLOC_IN_UNPROTECTED_MEMORY, NV_TRUE);
1147 }
1148 // If FB is broken then don't allow the allocation, unless running in L2 cache only mode
1149 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_BROKEN_FB) &&
1150 !gpuIsCacheOnlyModeEnabled(pGpu))
1151 {
1152 status = NV_ERR_BROKEN_FB;
1153 NV_PRINTF(LEVEL_ERROR, "Unsupported FB bound allocation on broken FB(0FB) platform\n");
1154 DBG_BREAKPOINT();
1155 }
1156
1157 NV_ASSERT(pMemDesc->pHeap == NULL);
1158 // Set the pHeap based on who owns this allocation
1159 if (pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL)
1160 {
1161 //
1162 // pHeap is not required in memdesc for ctx buf pools because each ctx buf
1163 // pool is tied to PMA and this pools is cached inside memdesc.
1164 //
1165 CTX_BUF_POOL_INFO *pCtxBufPool = memdescGetCtxBufPool(pMemDesc);
1166 NV_ASSERT_OR_RETURN(pCtxBufPool != NULL, NV_ERR_INVALID_STATE);
1167 }
1168 else if (pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE)
1169 {
1170 NvBool bForceSubheap = NV_FALSE;
1171
1172 if (pMemDesc->_flags & MEMDESC_FLAGS_FORCE_ALLOC_FROM_SUBHEAP)
1173 {
1174 bForceSubheap = NV_TRUE;
1175 }
1176
1177 pMemDesc->pHeap = memmgrGetDeviceSuballocator(GPU_GET_MEMORY_MANAGER(pGpu), bForceSubheap);
1178 }
1179 else if (GPU_GET_MEMORY_MANAGER(pGpu) != NULL &&
1180 RMCFG_MODULE_HEAP &&
1181 pMemDesc->_addressSpace == ADDR_FBMEM)
1182 {
1183 pMemDesc->pHeap = GPU_GET_HEAP(pGpu);
1184 }
1185
1186 break;
1187 }
1188 default:
1189 // Don't know how to do any other types of memory yet
1190 DBG_BREAKPOINT();
1191 return NV_ERR_GENERIC;
1192 }
1193
1194 if (status != NV_OK)
1195 {
1196 return status;
1197 }
1198
1199 if (gpumgrGetBcEnabledStatus(pGpu))
1200 {
1201 // Broadcast memdescAlloc call with flag set to allocate per subdevice.
1202 if (pMemDesc->_flags & MEMDESC_FLAGS_ALLOC_PER_SUBDEVICE)
1203 {
1204 NvU32 i;
1205 MEMORY_DESCRIPTOR *pSubDevMemDesc = pMemDesc;
1206 MEMORY_DESCRIPTOR *pPrev = pMemDesc;
1207 OBJGPU *pGpuChild;
1208
1209 pMemDesc->_subDeviceAllocCount = NumSubDevices(pGpu);
1210
1211 for (i = 0; i < pMemDesc->_subDeviceAllocCount; i++)
1212 {
1213 // Get pGpu for this subdeviceinst
1214 pGpuChild = gpumgrGetGpuFromSubDeviceInst(gpuGetDeviceInstance(pGpu), i);
1215 if (NULL == pGpuChild)
1216 {
1217 NV_ASSERT(0);
1218 status = NV_ERR_OBJECT_NOT_FOUND;
1219 goto subdeviceAlloc_failed;
1220 }
1221
1222 //
1223 // We are accessing the fields of the top level desc here directly without using the
1224 // accessor routines on purpose.
1225 //
1226 status = memdescCreate(&pSubDevMemDesc, pGpuChild, pMemDesc->Size, pMemDesc->Alignment,
1227 !!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS),
1228 pMemDesc->_addressSpace,
1229 pMemDesc->_cpuCacheAttrib,
1230 pMemDesc->_flags & ~MEMDESC_FLAGS_ALLOC_PER_SUBDEVICE);
1231
1232 if (status != NV_OK)
1233 {
1234 NV_ASSERT(0);
1235 goto subdeviceAlloc_failed;
1236 }
1237
1238 pSubDevMemDesc->_gpuCacheAttrib = pMemDesc->_gpuCacheAttrib;
1239 pSubDevMemDesc->_pageSize = pMemDesc->_pageSize;
1240
1241 // Force broadcast state to false when allocating a subdevice memdesc
1242 gpumgrSetBcEnabledStatus(pGpuChild, NV_FALSE);
1243
1244 status = memdescAlloc(pSubDevMemDesc);
1245
1246 if (pMemDesc->_addressSpace == ADDR_FBMEM)
1247 {
1248 //
1249 // The top level memdesc could have flags that don't reflect contiguity which
1250 // is set after memdescAlloc.
1251 //
1252 pMemDesc->Alignment = pSubDevMemDesc->Alignment;
1253 pMemDesc->_flags = pSubDevMemDesc->_flags | MEMDESC_FLAGS_ALLOC_PER_SUBDEVICE;
1254 pMemDesc->ActualSize = pSubDevMemDesc->ActualSize;
1255 }
1256
1257 // Restore broadcast state to true after allocating a subdevice memdesc
1258 gpumgrSetBcEnabledStatus(pGpuChild, NV_TRUE);
1259
1260 if (status != NV_OK)
1261 {
1262 memdescDestroy(pSubDevMemDesc);
1263 NV_ASSERT(0);
1264 goto subdeviceAlloc_failed;
1265 }
1266
1267 // Check for similarity in allocations for previous allocated subdev with current allocated subdev.
1268 // If subdev0 ~ subdev1 && subdev1~subdev2 then subdev0 ~ subdev2 and so on...Thus can check symmetry across all subdev allocations
1269 if (i > 0)
1270 {
1271 NV_ASSERT(pPrev->Size == pSubDevMemDesc->Size);
1272 NV_ASSERT(pPrev->PteAdjust == pSubDevMemDesc->PteAdjust);
1273 NV_ASSERT(pPrev->_addressSpace == pSubDevMemDesc->_addressSpace);
1274 NV_ASSERT(pPrev->_flags == pSubDevMemDesc->_flags);
1275 NV_ASSERT(pPrev->_pteKind == pSubDevMemDesc->_pteKind);
1276 NV_ASSERT(pPrev->_pteKindCompressed == pSubDevMemDesc->_pteKindCompressed);
1277 NV_ASSERT(pPrev->pHeap != pSubDevMemDesc->pHeap);
1278 }
1279
1280 pPrev->_pNext = pSubDevMemDesc;
1281 pPrev = pSubDevMemDesc;
1282 }
1283 pMemDesc->Allocated = 1;
1284 return NV_OK;
1285 }
1286 else if (pMemDesc->_addressSpace == ADDR_FBMEM)
1287 {
1288 // Broadcast memdescAlloc call on vidmem *without* flag set to allocate per subdevice
1289 NV_ASSERT(0);
1290 }
1291 }
1292
1293 // Unicast memdescAlloc call but with flag set to allocate per subdevice.
1294 NV_ASSERT(!((pMemDesc->_flags & MEMDESC_FLAGS_ALLOC_PER_SUBDEVICE) && !gpumgrGetBcEnabledStatus(pGpu)));
1295
1296 reAcquire = NV_FALSE;
1297 bcState = NV_FALSE;
1298
1299 if ((pMemDesc->_flags & MEMDESC_FLAGS_LOCKLESS_SYSMEM_ALLOC) && (pMemDesc->_addressSpace != ADDR_FBMEM))
1300 {
1301 bcState = gpumgrGetBcEnabledStatus(pGpu);
1302 if (RMCFG_FEATURE_RM_BASIC_LOCK_MODEL)
1303 {
1304 //
1305 // There is no equivalent routine for osCondReleaseRmSema in
1306 // the new basic lock model.
1307
1308 //
1309 // However, we can't drop the RM system semaphore in this
1310 // path because on non-windows platforms (i.e. MODS) it
1311 // has undesirable consequences. So for now we must
1312 // bracket this section with a reference to the feature
1313 // flag until we can rework this interface.
1314 //
1315 //
1316 // Check to make sure we own the lock and that we are
1317 // not at elevated IRQL; this models the behavior
1318 // of osCondReleaseRmSema.
1319 //
1320 if (!osIsRaisedIRQL() &&
1321 (rmGpuGroupLockIsOwner(pGpu->gpuInstance, GPU_LOCK_GRP_DEVICE, &gpuMask) ||
1322 rmGpuGroupLockIsOwner(pGpu->gpuInstance, GPU_LOCK_GRP_SUBDEVICE, &gpuMask)))
1323 {
1324 //
1325 // Release all owned gpu locks rather than just the
1326 // device-related locks because the caller may be holding more
1327 // than the required device locks. All currently owned
1328 // locks will be re-acquired before returning.
1329 //
1330 // This prevents potential GPU locking violations (e.g., if the
1331 // caller is holding all the gpu locks but only releases the
1332 // first of two device locks, then attempting to re-acquire
1333 // the first device lock will be a locking violation with
1334 // respect to the second device lock.)
1335 //
1336 gpuMask = rmGpuLocksGetOwnedMask();
1337 rmGpuGroupLockRelease(gpuMask, GPUS_LOCK_FLAGS_NONE);
1338 reAcquire = NV_TRUE;
1339 }
1340 }
1341 else
1342 {
1343 reAcquire = osCondReleaseRmSema(pSys->pSema);
1344 }
1345 }
1346
1347 // Actually allocate the memory
1348 NV_CHECK_OK(status, LEVEL_ERROR, _memdescAllocInternal(pMemDesc));
1349
1350 if (status != NV_OK)
1351 {
1352 pMemDesc->pHeap = NULL;
1353 }
1354
1355 if (reAcquire)
1356 {
1357 if (osAcquireRmSema(pSys->pSema) != NV_OK)
1358 {
1359 DBG_BREAKPOINT();
1360
1361 }
1362
1363 if (rmGpuGroupLockAcquire(pGpu->gpuInstance, GPU_LOCK_GRP_MASK,
1364 GPUS_LOCK_FLAGS_NONE, RM_LOCK_MODULES_MEM,
1365 &gpuMask) != NV_OK)
1366 {
1367 DBG_BREAKPOINT();
1368 }
1369 // Releasing the semaphore allows another thread to enter RM and
1370 // modify broadcast state. We need to set it back (see bug 368643)
1371 gpumgrSetBcEnabledStatus(pGpu, bcState);
1372 }
1373
1374 return status;
1375
1376 subdeviceAlloc_failed:
1377 _memSubDeviceFreeAndDestroy(pMemDesc);
1378 pMemDesc->_subDeviceAllocCount = 1;
1379 pMemDesc->_pNext = NULL;
1380 return status;
1381 }
1382
1383 /*!
1384 * Allocate memory from one of the possible locations specified in pList.
1385 *
1386 * @param[in,out] pMemDesc Memory descriptor to allocate
1387 * @param[in] pList List of NV_ADDRESS_SPACE values. Terminated
1388 * by an ADDR_UNKNOWN entry.
1389 *
1390 * @returns NV_OK on successful allocation. Various NV_ERR_GENERIC codes otherwise.
1391 */
1392 NV_STATUS
memdescAllocList(MEMORY_DESCRIPTOR * pMemDesc,const NV_ADDRESS_SPACE * pList)1393 memdescAllocList
1394 (
1395 MEMORY_DESCRIPTOR *pMemDesc,
1396 const NV_ADDRESS_SPACE *pList
1397 )
1398 {
1399 NV_STATUS status = NV_ERR_INVALID_ARGUMENT;
1400 NvU32 i = 0;
1401
1402 if (!pList)
1403 {
1404 return status;
1405 }
1406
1407 //
1408 // this memdesc may have gotten forced to sysmem if no carveout,
1409 // but for VPR it needs to be in vidmem, so check and re-direct here
1410 //
1411 if (pMemDesc->_flags & MEMDESC_ALLOC_FLAGS_PROTECTED)
1412 {
1413 OBJGPU *pGpu = pMemDesc->pGpu;
1414
1415 // Only force to vidmem if not running with zero-FB.
1416 if (!pGpu->getProperty(pGpu, PDB_PROP_GPU_BROKEN_FB) ||
1417 gpuIsCacheOnlyModeEnabled(pGpu))
1418 {
1419 pList = ADDRLIST_FBMEM_ONLY;
1420 }
1421 }
1422
1423 while (pList[i] != ADDR_UNKNOWN)
1424 {
1425 pMemDesc->_addressSpace = pList[i];
1426 status = memdescAlloc(pMemDesc);
1427
1428 if (status == NV_OK)
1429 {
1430 return status;
1431 }
1432
1433 i++;
1434 }
1435
1436 return status;
1437 }
1438
1439 /*!
1440 * @brief Lower memdesc free layer. Provides underlying free
1441 * functionality.
1442 *
1443 * @param[in,out] pMemDesc Memory descriptor to free
1444 *
1445 * @returns None
1446 */
1447 static void
_memdescFreeInternal(MEMORY_DESCRIPTOR * pMemDesc)1448 _memdescFreeInternal
1449 (
1450 MEMORY_DESCRIPTOR *pMemDesc
1451 )
1452 {
1453 MEM_DESC_DESTROY_CALLBACK *pCb, *pNext;
1454 NvU64 oldSize;
1455
1456 // Allow null frees
1457 if (!pMemDesc)
1458 {
1459 return;
1460 }
1461
1462 pCb = memdescGetDestroyCallbackList(pMemDesc);
1463
1464 // Notify all interested parties of destruction
1465 while (pCb)
1466 {
1467 pNext = pCb->pNext;
1468 pCb->destroyCallback(pMemDesc->pGpu, pCb->pObject, pMemDesc);
1469 // pCb is now invalid
1470 pCb = pNext;
1471 }
1472
1473 if (memdescHasSubDeviceMemDescs(pMemDesc))
1474 return;
1475
1476 memdescPrintMemdesc(pMemDesc, NV_FALSE, MAKE_NV_PRINTF_STR("memdesc being freed"));
1477
1478 // Bail our early in case this memdesc describes a MODS managed VPR region.
1479 if (memdescGetFlag(pMemDesc, MEMDESC_FLAGS_VPR_REGION_CLIENT_MANAGED))
1480 return;
1481
1482 switch (pMemDesc->_addressSpace)
1483 {
1484 case ADDR_SYSMEM:
1485 case ADDR_EGM:
1486 // invalidate if memory is cached in FB L2 cache.
1487 if (pMemDesc->_gpuCacheAttrib == NV_MEMORY_CACHED)
1488 {
1489 OBJGPU *pGpu = pMemDesc->pGpu;
1490
1491 //
1492 // If this memdesc managed to outlive its pGpu getting detached,
1493 // we're plenty off the rails already, but avoid using the pGpu
1494 // and carry on as best we can
1495 //
1496 if (gpumgrIsGpuPointerValid(pGpu))
1497 {
1498 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
1499 {
1500 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu);
1501 NV_ASSERT_OK(kmemsysCacheOp_HAL(pGpu, pKernelMemorySystem, pMemDesc,
1502 FB_CACHE_SYSTEM_MEMORY,
1503 FB_CACHE_INVALIDATE));
1504 }
1505 SLI_LOOP_END
1506 }
1507 else
1508 {
1509 NV_ASSERT_FAILED("Sysmemdesc outlived its attached pGpu");
1510 }
1511 }
1512
1513 oldSize = pMemDesc->Size;
1514 pMemDesc->Size = pMemDesc->ActualSize;
1515 pMemDesc->PageCount = ((pMemDesc->ActualSize + pMemDesc->pageArrayGranularity - 1) >> BIT_IDX_64(pMemDesc->pageArrayGranularity));
1516
1517 osFreePages(pMemDesc);
1518
1519 pMemDesc->Size = oldSize;
1520 pMemDesc->PageCount = ((oldSize + pMemDesc->pageArrayGranularity - 1) >> BIT_IDX_64(pMemDesc->pageArrayGranularity));
1521
1522 break;
1523
1524 case ADDR_FBMEM:
1525 {
1526 Heap *pHeap = pMemDesc->pHeap;
1527 NV_STATUS status = NV_OK;
1528 OBJGPU *pGpu = pMemDesc->pGpu;
1529
1530 if (RMCFG_FEATURE_PMA &&
1531 (pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CTX_BUF_POOL))
1532 {
1533 CTX_BUF_POOL_INFO *pCtxBufPool = memdescGetCtxBufPool(pMemDesc);
1534 if (pCtxBufPool == NULL)
1535 {
1536 DBG_BREAKPOINT();
1537 NV_PRINTF(LEVEL_ERROR, "ctx buf pool not found\n");
1538 return;
1539 }
1540 NV_STATUS status = ctxBufPoolFree(pCtxBufPool, pMemDesc);
1541 if (status != NV_OK)
1542 {
1543 DBG_BREAKPOINT();
1544 NV_PRINTF(LEVEL_ERROR, "Failed to free memdesc from context buffer pool\n");
1545 }
1546 }
1547 else
1548 {
1549 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
1550
1551 NV_ASSERT(pHeap != NULL);
1552
1553 if (!pHeap)
1554 return;
1555
1556 status = memmgrFree(pGpu, pMemoryManager, pHeap, 0x0, 0x0, 0x0,
1557 HEAP_OWNER_RM_CHANNEL_CTX_BUFFER,
1558 pMemDesc);
1559 NV_ASSERT(status == NV_OK);
1560 }
1561
1562 // If this heap is being used to manage PMSA memory, reduce the refcount accordingly
1563 if ((status == NV_OK) && (pHeap != NULL) &&
1564 (pHeap->heapType == HEAP_TYPE_PHYS_MEM_SUBALLOCATOR))
1565 {
1566 heapRemoveRef(pHeap);
1567 }
1568 break;
1569 }
1570
1571 default:
1572 // Don't know how to do any other types of memory yet
1573 DBG_BREAKPOINT();
1574 }
1575 }
1576
1577 /*!
1578 * @brief Upper memdesc free layer. Provides support for per-subdevice
1579 * sysmem buffers and lockless sysmem allocation. Because of SLI and subdevice
1580 * submem allocations (refer to submem chart) support, if memory has never
1581 * been allocated function will just unlink subdevice structure and destroy
1582 * subdevice descriptors.
1583 *
1584 * @param[in,out] pMemDesc Memory descriptor to free
1585 *
1586 * @returns None
1587 */
1588 void
memdescFree(MEMORY_DESCRIPTOR * pMemDesc)1589 memdescFree
1590 (
1591 MEMORY_DESCRIPTOR *pMemDesc
1592 )
1593 {
1594 // Allow null frees
1595 if (!pMemDesc)
1596 {
1597 return;
1598 }
1599
1600
1601 if (memdescIsSubMemoryMemDesc(pMemDesc))
1602 {
1603 NV_ASSERT(!pMemDesc->_pInternalMapping);
1604
1605 if (pMemDesc->_addressSpace == ADDR_SYSMEM)
1606 {
1607 // The memdesc is being freed so destroy all of its IOMMU mappings.
1608 _memdescFreeIommuMappings(pMemDesc);
1609 }
1610
1611 if (pMemDesc->_addressSpace != ADDR_FBMEM &&
1612 pMemDesc->_addressSpace != ADDR_SYSMEM &&
1613 pMemDesc->_addressSpace != ADDR_EGM)
1614 {
1615 return;
1616 }
1617
1618 _memSubDeviceFreeAndDestroy(pMemDesc);
1619 }
1620 else
1621 {
1622 //
1623 // In case RM attempts to free memory that has more than 1 refcount, the free is deferred until refcount reaches 0
1624 //
1625 // Bug 3307574 RM crashes when client's specify sysmem UserD location.
1626 // RM attempts to peek at the client allocated UserD when waiting for a channel to go idle.
1627 //
1628 if (pMemDesc->RefCount > 1 && pMemDesc->Allocated == 1)
1629 {
1630 pMemDesc->bDeferredFree = NV_TRUE;
1631 return;
1632 }
1633
1634 if (!pMemDesc->Allocated)
1635 {
1636 return;
1637 }
1638 pMemDesc->Allocated--;
1639 if (0 != pMemDesc->Allocated)
1640 {
1641 return;
1642 }
1643
1644 // If standbyBuffer memory was allocated then free it
1645 if (pMemDesc->_pStandbyBuffer)
1646 {
1647 memdescFree(pMemDesc->_pStandbyBuffer);
1648 memdescDestroy(pMemDesc->_pStandbyBuffer);
1649 pMemDesc->_pStandbyBuffer = NULL;
1650 }
1651
1652 NV_ASSERT(!pMemDesc->_pInternalMapping);
1653
1654 if (pMemDesc->_addressSpace == ADDR_SYSMEM)
1655 {
1656 // The memdesc is being freed so destroy all of its IOMMU mappings.
1657 _memdescFreeIommuMappings(pMemDesc);
1658 }
1659
1660 if (pMemDesc->_addressSpace != ADDR_FBMEM &&
1661 pMemDesc->_addressSpace != ADDR_EGM &&
1662 pMemDesc->_addressSpace != ADDR_SYSMEM)
1663 {
1664 return;
1665 }
1666
1667 _memSubDeviceFreeAndDestroy(pMemDesc);
1668
1669 _memdescFreeInternal(pMemDesc);
1670 }
1671
1672 // Reset tracking state
1673 pMemDesc->_pNext = NULL;
1674 pMemDesc->_subDeviceAllocCount = 1;
1675
1676 //
1677 // Reset tracking state of parent
1678 // Why it is needed:
1679 // When a submemory toplevel memdesc with subdevices is freed,
1680 // the subdecice memdescs and their parent are destroyed or their
1681 // refcount decreased.
1682 // When the parent subdevice descriptors are destroyed, their
1683 // top level descriptor is left alone and has a dangling
1684 // _pNext pointer
1685 //
1686 if ((pMemDesc->_pParentDescriptor != NULL) &&
1687 (memdescHasSubDeviceMemDescs(pMemDesc->_pParentDescriptor)) &&
1688 (pMemDesc->_pParentDescriptor->RefCount == 1))
1689 {
1690 pMemDesc->_pParentDescriptor->_pNext = NULL;
1691 pMemDesc->_pParentDescriptor->_subDeviceAllocCount = 1;
1692 }
1693 }
1694
1695 /*!
1696 * @brief Lock the paged virtual memory descripted by the memory descriptor
1697 *
1698 * @param[in] pMemDesc Memory descriptor to lock
1699 *
1700 * @returns NV_OK on successful allocation. Various NV_ERR_GENERIC codes otherwise.
1701 */
1702 NV_STATUS
memdescLock(MEMORY_DESCRIPTOR * pMemDesc)1703 memdescLock
1704 (
1705 MEMORY_DESCRIPTOR *pMemDesc
1706 )
1707 {
1708
1709 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
1710 if (!(pMemDesc->_flags & MEMDESC_FLAGS_PAGED_SYSMEM))
1711 {
1712 return NV_ERR_ILLEGAL_ACTION;
1713 }
1714
1715 return osLockMem(pMemDesc);
1716 }
1717
1718 /*!
1719 * @brief Unlock the paged virtual memory descripted by the memory descriptor
1720 *
1721 * @param[in] pMemDesc Memory descriptor to unlock
1722 *
1723 * @returns NV_OK on successful allocation. Various NV_ERR_GENERIC codes otherwise.
1724 */
1725 NV_STATUS
memdescUnlock(MEMORY_DESCRIPTOR * pMemDesc)1726 memdescUnlock
1727 (
1728 MEMORY_DESCRIPTOR *pMemDesc
1729 )
1730 {
1731 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
1732 if (!(pMemDesc->_flags & MEMDESC_FLAGS_PAGED_SYSMEM))
1733 {
1734 return NV_ERR_ILLEGAL_ACTION;
1735 }
1736
1737 return osUnlockMem(pMemDesc);
1738 }
1739
1740 /*!
1741 * @brief Get a CPU mapping to the memory described by a memory descriptor
1742 *
1743 * This is for memory descriptors used by RM clients, not by the RM itself.
1744 * For internal mappings the busMapRmAperture() hal routines are used.
1745 *
1746 * @param[in] pMemDesc Memory descriptor to map
1747 * @param[in] Offset Offset into memory descriptor to start map
1748 * @param[in] Size Size of mapping
1749 * @param[in] Kernel Kernel or user address space
1750 * @param[in] Protect NV_PROTECT_*
1751 * @param[out] pAddress Return address
1752 * @param[out] pPriv Return cookie to be passed back to memdescUnmap
1753 *
1754 * @returns NV_STATUS
1755 */
1756
1757 NV_STATUS
memdescMapOld(MEMORY_DESCRIPTOR * pMemDesc,NvU64 Offset,NvU64 Size,NvBool Kernel,NvU32 Protect,void ** pAddress,void ** pPriv)1758 memdescMapOld
1759 (
1760 MEMORY_DESCRIPTOR *pMemDesc,
1761 NvU64 Offset,
1762 NvU64 Size,
1763 NvBool Kernel,
1764 NvU32 Protect,
1765 void **pAddress,
1766 void **pPriv
1767 )
1768 {
1769 NvP64 pAddressP64 = NV_PTR_TO_NvP64(*pAddress);
1770 NvP64 pPrivP64 = NV_PTR_TO_NvP64(*pPriv);
1771 NV_STATUS status;
1772
1773 #if !defined(NV_64_BITS)
1774 NV_ASSERT(Kernel);
1775 #endif
1776
1777 status = memdescMap(pMemDesc,
1778 Offset,
1779 Size,
1780 Kernel,
1781 Protect,
1782 &pAddressP64,
1783 &pPrivP64);
1784
1785 *pAddress = NvP64_VALUE(pAddressP64);
1786 *pPriv = NvP64_VALUE(pPrivP64);
1787
1788 return status;
1789 }
1790
1791 NV_STATUS
memdescMap(MEMORY_DESCRIPTOR * pMemDesc,NvU64 Offset,NvU64 Size,NvBool Kernel,NvU32 Protect,NvP64 * pAddress,NvP64 * pPriv)1792 memdescMap
1793 (
1794 MEMORY_DESCRIPTOR *pMemDesc,
1795 NvU64 Offset,
1796 NvU64 Size,
1797 NvBool Kernel,
1798 NvU32 Protect,
1799 NvP64 *pAddress,
1800 NvP64 *pPriv
1801 )
1802 {
1803 NV_STATUS status = NV_OK;
1804 NvU64 rootOffset = 0;
1805
1806 NV_ASSERT_OR_RETURN(((Offset + Size) <= memdescGetSize(pMemDesc)), NV_ERR_INVALID_ARGUMENT);
1807
1808 pMemDesc = memdescGetRootMemDesc(pMemDesc, &rootOffset);
1809 Offset += rootOffset;
1810
1811 if (pMemDesc->PteAdjust &&
1812 (pMemDesc->Alignment > RM_PAGE_SIZE) &&
1813 (pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS) &&
1814 RMCFG_FEATURE_PLATFORM_MODS)
1815 {
1816 Offset += pMemDesc->PteAdjust;
1817 }
1818
1819 NV_ASSERT_OR_RETURN(!memdescHasSubDeviceMemDescs(pMemDesc), NV_ERR_INVALID_OBJECT_BUFFER);
1820
1821 switch (pMemDesc->_addressSpace)
1822 {
1823 case ADDR_SYSMEM:
1824 case ADDR_EGM:
1825 {
1826 status = osMapSystemMemory(pMemDesc, Offset, Size,
1827 Kernel, Protect, pAddress, pPriv);
1828 if (status != NV_OK)
1829 {
1830 return status;
1831 }
1832 break;
1833 }
1834
1835 case ADDR_FBMEM:
1836 {
1837 OBJGPU *pGpu = pMemDesc->pGpu;
1838 NvU32 mode = NV_MEMORY_WRITECOMBINED;
1839 KernelBus *pKernelBus;
1840 FB_MAPPING_INFO *pMapping;
1841 RmPhysAddr bar1PhysAddr;
1842 NvBool bCoherentCpuMapping;
1843
1844 NV_ASSERT_OR_RETURN(pGpu != NULL, NV_ERR_INVALID_ARGUMENT);
1845
1846 pKernelBus = GPU_GET_KERNEL_BUS(pGpu);
1847 bCoherentCpuMapping = pGpu->getProperty(pGpu, PDB_PROP_GPU_COHERENT_CPU_MAPPING);
1848
1849 // Need struct to keep track of the info for this mapping
1850 pMapping = portMemAllocNonPaged(sizeof(FB_MAPPING_INFO));
1851 if (pMapping == NULL)
1852 {
1853 return NV_ERR_NO_MEMORY;
1854 }
1855
1856 if (bCoherentCpuMapping)
1857 {
1858 if (Kernel)
1859 {
1860 status = kbusMapCoherentCpuMapping_HAL(pGpu,
1861 pKernelBus,
1862 pMemDesc,
1863 Offset,
1864 Size,
1865 Protect,
1866 pAddress,
1867 &pMapping->pPriv);
1868 }
1869 else
1870 {
1871 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu);
1872 NvU64 fbOffset = memdescGetPhysAddr(pMemDesc, AT_CPU, Offset);
1873 bar1PhysAddr = pKernelMemorySystem->coherentCpuFbBase + fbOffset;
1874
1875 // Until we have proper discontig support for NUMA, this assumes that the unix path is a noop
1876 *pAddress = (NvP64) bar1PhysAddr;
1877 }
1878
1879
1880 if (status != NV_OK)
1881 {
1882 portMemFree(pMapping);
1883 return status;
1884 }
1885
1886 NV_PRINTF(LEVEL_INFO, "Allocating coherent link mapping. VA: %p PA: 0x%llx size: 0x%llx\n",
1887 NvP64_VALUE(*pAddress),
1888 memdescGetPhysAddr(pMemDesc, AT_GPU, Offset), Size);
1889
1890 *pPriv = NV_PTR_TO_NvP64(pMapping);
1891 break;
1892 }
1893
1894 // Determine where in BAR1 the mapping will go
1895 pMapping->FbApertureLen = Size;
1896 status = kbusMapFbApertureSingle(pGpu, pKernelBus,
1897 pMemDesc, Offset,
1898 &pMapping->FbAperture,
1899 &pMapping->FbApertureLen,
1900 BUS_MAP_FB_FLAGS_MAP_UNICAST,
1901 NULL);
1902 if (status != NV_OK)
1903 {
1904 portMemFree(pMapping);
1905 return status;
1906 }
1907
1908 bar1PhysAddr = gpumgrGetGpuPhysFbAddr(pGpu) + pMapping->FbAperture;
1909 mode = NV_MEMORY_WRITECOMBINED;
1910
1911 // Create the mapping
1912 if (Kernel)
1913 {
1914 status = osMapPciMemoryKernel64(pGpu, bar1PhysAddr,
1915 Size, Protect, pAddress,
1916 mode);
1917 }
1918 else
1919 {
1920 status = osMapPciMemoryUser(pGpu->pOsGpuInfo, bar1PhysAddr,
1921 Size, Protect, pAddress,
1922 &pMapping->pPriv,
1923 mode);
1924 }
1925
1926 if (status != NV_OK)
1927 {
1928 if (!bCoherentCpuMapping)
1929 {
1930 kbusUnmapFbApertureSingle(pGpu, pKernelBus, pMemDesc,
1931 pMapping->FbAperture,
1932 pMapping->FbApertureLen,
1933 BUS_MAP_FB_FLAGS_MAP_UNICAST);
1934 }
1935 portMemFree(pMapping);
1936 return status;
1937 }
1938
1939 *pPriv = NV_PTR_TO_NvP64(pMapping);
1940 break;
1941 }
1942
1943 default:
1944 // Don't know how to do any other types of memory yet
1945 DBG_BREAKPOINT();
1946 return NV_ERR_GENERIC;
1947 }
1948 return NV_OK;
1949 }
1950 void
memdescUnmapOld(MEMORY_DESCRIPTOR * pMemDesc,NvBool Kernel,NvU32 ProcessId,void * Address,void * Priv)1951 memdescUnmapOld
1952 (
1953 MEMORY_DESCRIPTOR *pMemDesc,
1954 NvBool Kernel,
1955 NvU32 ProcessId,
1956 void *Address,
1957 void *Priv
1958 )
1959 {
1960 memdescUnmap(pMemDesc,
1961 Kernel,
1962 ProcessId,
1963 NV_PTR_TO_NvP64(Address),
1964 NV_PTR_TO_NvP64(Priv));
1965 }
1966
1967 /*!
1968 * @brief Remove a mapping for the memory descriptor, reversing memdescMap
1969 *
1970 * @param[in] pMemDesc Memory descriptor to unmap
1971 * @param[in] Kernel Kernel or user address space
1972 * @param[in] ProcessId Process ID if user space
1973 * @param[in] Address Mapped address
1974 * @param[in] Priv Return priv cookie from memdescMap
1975 *
1976 * @returns None
1977 */
1978 void
memdescUnmap(MEMORY_DESCRIPTOR * pMemDesc,NvBool Kernel,NvU32 ProcessId,NvP64 Address,NvP64 Priv)1979 memdescUnmap
1980 (
1981 MEMORY_DESCRIPTOR *pMemDesc,
1982 NvBool Kernel,
1983 NvU32 ProcessId,
1984 NvP64 Address,
1985 NvP64 Priv
1986 )
1987 {
1988 // Allow null unmaps
1989 if (!Address)
1990 return;
1991
1992 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
1993
1994
1995 // find first allocated parent descriptor
1996 while (!pMemDesc->Allocated && pMemDesc->_pParentDescriptor)
1997 {
1998 pMemDesc = pMemDesc->_pParentDescriptor;
1999 }
2000
2001 switch (pMemDesc->_addressSpace)
2002 {
2003 case ADDR_SYSMEM:
2004 case ADDR_EGM:
2005 {
2006 osUnmapSystemMemory(pMemDesc, Kernel, ProcessId, Address, Priv);
2007 break;
2008 }
2009
2010 case ADDR_FBMEM:
2011 {
2012 OBJGPU *pGpu = pMemDesc->pGpu;
2013 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu);
2014 FB_MAPPING_INFO *pMapping = (FB_MAPPING_INFO *)NvP64_VALUE(Priv);
2015 NvBool bCoherentCpuMapping = pGpu->getProperty(pGpu, PDB_PROP_GPU_COHERENT_CPU_MAPPING);
2016 NvU64 Size = pMapping->FbApertureLen;
2017
2018 NV_ASSERT(!(pMemDesc->_flags & MEMDESC_FLAGS_CPU_ONLY));
2019
2020 if (bCoherentCpuMapping)
2021 {
2022 if (Kernel)
2023 {
2024 kbusUnmapCoherentCpuMapping_HAL(pGpu, pKernelBus, pMemDesc, Address, pMapping->pPriv);
2025 }
2026 else
2027 {
2028 osUnmapPciMemoryUser(pGpu->pOsGpuInfo, Address, Size,
2029 pMapping->pPriv);
2030 }
2031
2032 portMemFree(pMapping);
2033 break;
2034 }
2035
2036 kbusUnmapFbApertureSingle(pGpu, pKernelBus, pMemDesc,
2037 pMapping->FbAperture,
2038 Size,
2039 BUS_MAP_FB_FLAGS_MAP_UNICAST);
2040 if (Kernel)
2041 {
2042 osUnmapPciMemoryKernel64(pGpu, Address);
2043 }
2044 else
2045 {
2046 osUnmapPciMemoryUser(pGpu->pOsGpuInfo, Address, Size,
2047 pMapping->pPriv);
2048 }
2049
2050 portMemFree(pMapping);
2051 break;
2052 }
2053
2054 default:
2055 // Don't know how to do any other types of memory yet
2056 DBG_BREAKPOINT();
2057 }
2058 }
2059
2060 typedef enum
2061 {
2062 MEMDESC_MAP_INTERNAL_TYPE_GSP, // On GSP, use a pre-existing mapping
2063 MEMDESC_MAP_INTERNAL_TYPE_COHERENT_FBMEM, // For NVLINK, use a pre-existing mapping for fbmem
2064 MEMDESC_MAP_INTERNAL_TYPE_BAR2, // Use BAR2 (fbmem or reflected sysmem)
2065 MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT, // Use OS to map sysmem
2066 } MEMDESC_MAP_INTERNAL_TYPE;
2067
2068 static MEMDESC_MAP_INTERNAL_TYPE
memdescGetMapInternalType(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc)2069 memdescGetMapInternalType
2070 (
2071 OBJGPU *pGpu,
2072 MEMORY_DESCRIPTOR *pMemDesc
2073 )
2074 {
2075 if (RMCFG_FEATURE_PLATFORM_GSP)
2076 {
2077 return MEMDESC_MAP_INTERNAL_TYPE_GSP;
2078 }
2079 else if (pMemDesc->_addressSpace == ADDR_FBMEM &&
2080 pGpu->getProperty(pGpu, PDB_PROP_GPU_COHERENT_CPU_MAPPING))
2081 {
2082 // Temporary hack to keep the same behavior on GV100F (dVOLTA & DFPGA)
2083 if (IsDFPGA(pGpu))
2084 return MEMDESC_MAP_INTERNAL_TYPE_BAR2;
2085
2086 return MEMDESC_MAP_INTERNAL_TYPE_COHERENT_FBMEM;
2087 }
2088 else
2089 {
2090 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu);
2091 NvBool bUseDirectMap = NV_FALSE;
2092 NV_STATUS status;
2093
2094 status = kbusUseDirectSysmemMap_HAL(pGpu, pKernelBus, pMemDesc, &bUseDirectMap);
2095 NV_ASSERT_OR_RETURN(status == NV_OK, MEMDESC_MAP_INTERNAL_TYPE_BAR2);
2096
2097 return bUseDirectMap ? MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT : MEMDESC_MAP_INTERNAL_TYPE_BAR2;
2098 }
2099
2100 return MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT;
2101 }
2102
2103 void
memdescFlushGpuCaches(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc)2104 memdescFlushGpuCaches
2105 (
2106 OBJGPU *pGpu,
2107 MEMORY_DESCRIPTOR *pMemDesc
2108 )
2109 {
2110 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu);
2111
2112 if (memdescGetGpuCacheAttrib(pMemDesc) == NV_MEMORY_CACHED)
2113 {
2114 //
2115 // Only the non-coherent memory path is available, so writeback GPU L2
2116 // invalidate the GPU L2
2117 //
2118 kmemsysCacheOp_HAL(pGpu, pKernelMemorySystem, pMemDesc, FB_CACHE_MEM_UNDEFINED, FB_CACHE_EVICT);
2119 }
2120 }
2121
2122 void
memdescFlushCpuCaches(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc)2123 memdescFlushCpuCaches
2124 (
2125 OBJGPU *pGpu,
2126 MEMORY_DESCRIPTOR *pMemDesc
2127 )
2128 {
2129 // Flush WC to get the data written to this mapping out to memory
2130 osFlushCpuWriteCombineBuffer();
2131
2132 KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pGpu);
2133
2134 // Special care is needed on SOC, where the GPU cannot snoop the CPU L2
2135 if ((pKernelBif != NULL) &&
2136 !kbifIsSnoopDmaCapable(pGpu, pKernelBif) &&
2137 (memdescGetCpuCacheAttrib(pMemDesc) == NV_MEMORY_CACHED))
2138 {
2139 // Flush CPU L2 so that the GPU will see any changes the CPU made
2140 osFlushCpuCache();
2141 }
2142 }
2143
2144 /*
2145 * @brief map memory descriptor for internal access
2146 *
2147 * flags - subset of TRANSFER_FLAGS_
2148 */
2149 void*
memdescMapInternal(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,NvU32 flags)2150 memdescMapInternal
2151 (
2152 OBJGPU *pGpu,
2153 MEMORY_DESCRIPTOR *pMemDesc,
2154 NvU32 flags
2155 )
2156 {
2157 MEMDESC_MAP_INTERNAL_TYPE mapType;
2158 NV_STATUS status;
2159
2160 NV_ASSERT_OR_RETURN(pMemDesc != NULL, NULL);
2161
2162 if (pMemDesc->_addressSpace == ADDR_FBMEM)
2163 {
2164 pMemDesc = memdescGetMemDescFromGpu(pMemDesc, pGpu);
2165 }
2166
2167 mapType = memdescGetMapInternalType(pGpu, pMemDesc);
2168
2169 // We need to flush & invalidate GPU L2 cache only for directed BAR mappings.
2170 // Reflected BAR mappings will access memory via GPU, and hence go through GPU L2 cache.
2171 if (mapType == MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT)
2172 memdescFlushGpuCaches(pGpu, pMemDesc);
2173
2174 if (pMemDesc->_pInternalMapping != NULL)
2175 {
2176 NV_ASSERT(pMemDesc->_internalMappingRefCount);
2177
2178 // Existing BAR2 mapping may be invalid due to GPU reset
2179 if (mapType == MEMDESC_MAP_INTERNAL_TYPE_BAR2)
2180 {
2181 pMemDesc->_pInternalMapping = kbusValidateBar2ApertureMapping_HAL(pGpu, GPU_GET_KERNEL_BUS(pGpu), pMemDesc,
2182 pMemDesc->_pInternalMapping);
2183 NV_CHECK_OR_RETURN(LEVEL_ERROR, pMemDesc->_pInternalMapping != NULL, NULL);
2184 }
2185
2186 pMemDesc->_internalMappingRefCount++;
2187 return pMemDesc->_pInternalMapping;
2188 }
2189
2190 switch (mapType)
2191 {
2192 case MEMDESC_MAP_INTERNAL_TYPE_GSP:
2193 NV_CHECK_OR_RETURN(LEVEL_ERROR, pMemDesc->_pInternalMapping != NULL, NULL);
2194 break;
2195 case MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT:
2196 {
2197 status = memdescMapOld(pMemDesc, 0, pMemDesc->Size, NV_TRUE, NV_PROTECT_READ_WRITE,
2198 &pMemDesc->_pInternalMapping, &pMemDesc->_pInternalMappingPriv);
2199 NV_CHECK_OR_RETURN(LEVEL_ERROR, status == NV_OK, NULL);
2200 break;
2201 }
2202 case MEMDESC_MAP_INTERNAL_TYPE_COHERENT_FBMEM:
2203 {
2204 NV_ASSERT(pGpu->getProperty(pGpu, PDB_PROP_GPU_ATS_SUPPORTED));
2205 status = kbusMapCoherentCpuMapping_HAL(pGpu,
2206 GPU_GET_KERNEL_BUS(pGpu),
2207 pMemDesc,
2208 0,
2209 memdescGetSize(pMemDesc),
2210 NV_PROTECT_READ_WRITE,
2211 &pMemDesc->_pInternalMapping,
2212 &pMemDesc->_pInternalMappingPriv);
2213 NV_CHECK_OR_RETURN(LEVEL_ERROR, status == NV_OK, NULL);
2214 break;
2215 }
2216 case MEMDESC_MAP_INTERNAL_TYPE_BAR2:
2217 pMemDesc->_pInternalMapping = kbusMapBar2Aperture_HAL(pGpu, GPU_GET_KERNEL_BUS(pGpu), pMemDesc, flags);
2218 NV_CHECK_OR_RETURN(LEVEL_INFO, pMemDesc->_pInternalMapping != NULL, NULL);
2219 break;
2220
2221 default:
2222 DBG_BREAKPOINT();
2223 }
2224
2225 pMemDesc->_internalMappingRefCount = 1;
2226 return pMemDesc->_pInternalMapping;
2227 }
2228
memdescUnmapInternal(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,NvU32 flags)2229 void memdescUnmapInternal
2230 (
2231 OBJGPU *pGpu,
2232 MEMORY_DESCRIPTOR *pMemDesc,
2233 NvU32 flags
2234 )
2235 {
2236 MEMDESC_MAP_INTERNAL_TYPE mapType;
2237
2238 NV_ASSERT_OR_RETURN_VOID(pMemDesc != NULL);
2239 NV_ASSERT_OR_RETURN_VOID(pMemDesc->_pInternalMapping != NULL && pMemDesc->_internalMappingRefCount != 0);
2240
2241 if (pMemDesc->_addressSpace == ADDR_FBMEM)
2242 {
2243 pMemDesc = memdescGetMemDescFromGpu(pMemDesc, pGpu);
2244 }
2245
2246 mapType = memdescGetMapInternalType(pGpu, pMemDesc);
2247
2248 if (mapType == MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT || mapType == MEMDESC_MAP_INTERNAL_TYPE_BAR2)
2249 {
2250 memdescFlushCpuCaches(pGpu, pMemDesc);
2251 }
2252
2253 if (--pMemDesc->_internalMappingRefCount == 0)
2254 {
2255 switch (mapType)
2256 {
2257 case MEMDESC_MAP_INTERNAL_TYPE_GSP:
2258 break;
2259 case MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT:
2260 memdescUnmapOld(pMemDesc, NV_TRUE, 0,
2261 pMemDesc->_pInternalMapping, pMemDesc->_pInternalMappingPriv);
2262 break;
2263
2264 case MEMDESC_MAP_INTERNAL_TYPE_COHERENT_FBMEM:
2265 {
2266 //
2267 // This flag is set when there is an update in BAR1/FLA PDE/PTE and when mmufill
2268 // of BAR1 and FLA read on NINB_VC which doesn't probe the cpu cache.
2269 //
2270 // TODO: This flag needs to be set when updating PDE/PTE for invisible BAR2 also.
2271 //
2272 if (flags & TRANSFER_FLAGS_FLUSH_CPU_CACHE_WAR_BUG4686457)
2273 {
2274 osFlushGpuCoherentCpuCacheRange(pGpu->pOsGpuInfo,
2275 (NvUPtr)pMemDesc->_pInternalMapping,
2276 pMemDesc->ActualSize);
2277 }
2278
2279 kbusUnmapCoherentCpuMapping_HAL(pGpu, GPU_GET_KERNEL_BUS(pGpu), pMemDesc,
2280 pMemDesc->_pInternalMapping, pMemDesc->_pInternalMappingPriv);
2281 break;
2282 }
2283 case MEMDESC_MAP_INTERNAL_TYPE_BAR2:
2284 {
2285 NvU8 *p = (NvU8 *)pMemDesc->_pInternalMapping;
2286
2287 kbusUnmapBar2ApertureWithFlags_HAL(pGpu, GPU_GET_KERNEL_BUS(pGpu), pMemDesc, &p, flags);
2288 break;
2289 }
2290
2291 default:
2292 DBG_BREAKPOINT();
2293 }
2294
2295 pMemDesc->_pInternalMapping = NULL;
2296 pMemDesc->_pInternalMappingPriv = NULL;
2297 pMemDesc->_internalMappingRefCount = 0;
2298 }
2299
2300 // Flush for direct mappings too to keep the behavior
2301 if (((flags & TRANSFER_FLAGS_DEFER_FLUSH) == 0) &&
2302 (mapType == MEMDESC_MAP_INTERNAL_TYPE_SYSMEM_DIRECT || mapType == MEMDESC_MAP_INTERNAL_TYPE_BAR2))
2303 {
2304 kbusFlush_HAL(pGpu, GPU_GET_KERNEL_BUS(pGpu),
2305 kbusGetFlushAperture(GPU_GET_KERNEL_BUS(pGpu), memdescGetAddressSpace(pMemDesc)));
2306 }
2307 }
2308
2309 /*!
2310 * Describe an existing region of memory in a memory descriptor
2311 *
2312 * Memory must be physically contiguous.
2313 *
2314 * The memory descriptor must be initialized with
2315 * memdescCreate*(), typically memdescCreateExisting()
2316 * prior to calling memdescDescribe.
2317 *
2318 * memdescDescribe() now only updates the fields needed in the call.
2319 *
2320 * @param[out] pMemDesc Memory descriptor to fill
2321 * @param[in] AddressSpace Address space of memory
2322 * @param[in] Base Physical address of region
2323 * @param[in] Size Size of region
2324 *
2325 * @returns None
2326 */
2327 void
memdescDescribe(MEMORY_DESCRIPTOR * pMemDesc,NV_ADDRESS_SPACE AddressSpace,RmPhysAddr Base,NvU64 Size)2328 memdescDescribe
2329 (
2330 MEMORY_DESCRIPTOR *pMemDesc,
2331 NV_ADDRESS_SPACE AddressSpace,
2332 RmPhysAddr Base,
2333 NvU64 Size
2334 )
2335 {
2336 // Some sanity checks to see if we went through MemCreate*() first
2337 NV_ASSERT((pMemDesc->RefCount == 1) &&
2338 (memdescGetDestroyCallbackList(pMemDesc) == NULL) &&
2339 (pMemDesc->PteAdjust == 0));
2340
2341 NV_ASSERT(pMemDesc->_pIommuMappings == NULL);
2342 NV_ASSERT(pMemDesc->Allocated == 0);
2343 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
2344
2345 //
2346 // Check if the base address accounts for the DMA window start address
2347 // (always in the high, unaddressable bits of the address) and add it
2348 // if necessary. On most platforms, the DMA window start address will
2349 // simply be 0.
2350 //
2351 // This is most likely to happen in cases where the Base address is
2352 // read directly from a register or MMU entry, which does not already
2353 // account for the DMA window.
2354 //
2355 if (pMemDesc->pGpu == NULL)
2356 {
2357 NV_PRINTF(LEVEL_WARNING,
2358 "unable to check Base 0x%016llx for DMA window\n", Base);
2359 }
2360 else if (AddressSpace == ADDR_SYSMEM)
2361 {
2362 OBJGPU *pGpu = pMemDesc->pGpu;
2363 if (pGpu)
2364 {
2365 KernelBif *pKernelBif = GPU_GET_KERNEL_BIF(pGpu);
2366 NvU32 physAddrWidth = gpuGetPhysAddrWidth_HAL(pGpu, ADDR_SYSMEM);
2367 if ((Base & ~(NVBIT64(physAddrWidth) - 1)) == 0)
2368 {
2369 Base += pKernelBif->dmaWindowStartAddress;
2370 }
2371 }
2372 }
2373
2374 if (pMemDesc->Alignment != 0)
2375 {
2376 NV_ASSERT(NV_FLOOR_TO_QUANTA(Base, pMemDesc->Alignment) == Base);
2377 }
2378
2379 pMemDesc->Size = Size;
2380 pMemDesc->ActualSize = NV_ROUNDUP(Size, pMemDesc->pageArrayGranularity);
2381 pMemDesc->_flags |= MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS;
2382 pMemDesc->_addressSpace = AddressSpace;
2383 pMemDesc->_pteArray[0] = Base & ~RM_PAGE_MASK;
2384 pMemDesc->_subDeviceAllocCount = 1;
2385 pMemDesc->PteAdjust = NvU64_LO32(Base) & RM_PAGE_MASK;
2386 pMemDesc->PageCount = ((Size + pMemDesc->PteAdjust + RM_PAGE_SIZE - 1) >> RM_PAGE_SHIFT);
2387 pMemDesc->_pParentDescriptor = NULL;
2388 pMemDesc->childDescriptorCnt = 0;
2389 }
2390
2391 /*!
2392 * Static helper called from memdescFillPages.
2393 * When dynamic granularity memdescs are enabled. We only need to copy over the pages
2394 * without worrying about converting them to 4K.
2395 *
2396 * @param[in] pMemDesc Memory descriptor to fill
2397 * @param[in] pageIndex Index into memory descriptor to fill from
2398 * @param[in] pPages Array of physical addresses
2399 * @param[in] pageCount Number of entries in pPages
2400 * @param[in] pageSize Size of each page in pPages
2401 *
2402 * @returns None
2403 */
2404 static void
_memdescFillPagesAtNativeGranularity(MEMORY_DESCRIPTOR * pMemDesc,NvU32 pageIndex,NvU64 * pPages,NvU32 pageCount,NvU64 pageSize)2405 _memdescFillPagesAtNativeGranularity
2406 (
2407 MEMORY_DESCRIPTOR *pMemDesc,
2408 NvU32 pageIndex,
2409 NvU64 *pPages,
2410 NvU32 pageCount,
2411 NvU64 pageSize
2412 )
2413 {
2414 NV_STATUS status;
2415
2416 NV_ASSERT(pageIndex + pageCount < pMemDesc->PageCount);
2417
2418 status = memdescSetPageArrayGranularity(pMemDesc, pageSize);
2419 if (status != NV_OK)
2420 {
2421 return;
2422 }
2423
2424 for (NvU32 i = 0; i < pageCount; i++)
2425 {
2426 pMemDesc->_pteArray[pageIndex + i] = pPages[i];
2427 }
2428
2429 pMemDesc->ActualSize = pageCount * pageSize;
2430 }
2431
2432 /*!
2433 * Fill the PTE array of a memory descriptor with an array of addresses
2434 * returned by pmaAllocatePages().
2435 *
2436 * Memory must be physically discontiguous. For the contiguous case
2437 * memdescDescribe() is more apt.
2438 *
2439 * The memory descriptor must be initialized with memdescCreate*(),
2440 * typically memdescCreateExisting() prior to calling
2441 * memdescFillPages().
2442 *
2443 * @param[in] pMemDesc Memory descriptor to fill
2444 * @param[in] pageIndex Index into memory descriptor to fill from
2445 * @param[in] pPages Array of physical addresses
2446 * @param[in] pageCount Number of entries in pPages
2447 * @param[in] pageSize Size of each page in pPages
2448 *
2449 * @returns None
2450 */
2451 void
memdescFillPages(MEMORY_DESCRIPTOR * pMemDesc,NvU32 pageIndex,NvU64 * pPages,NvU32 pageCount,NvU64 pageSize)2452 memdescFillPages
2453 (
2454 MEMORY_DESCRIPTOR *pMemDesc,
2455 NvU32 pageIndex,
2456 NvU64 *pPages,
2457 NvU32 pageCount,
2458 NvU64 pageSize
2459 )
2460 {
2461 OBJGPU *pGpu = gpumgrGetSomeGpu();
2462 NvU32 i, j, k;
2463 NvU32 numChunks4k = pageSize / RM_PAGE_SIZE;
2464 NvU32 offset4k = numChunks4k * pageIndex;
2465 NvU32 pageCount4k = numChunks4k * pageCount;
2466 NvU32 result4k, limit4k;
2467 NvU64 addr;
2468
2469 NV_ASSERT(pMemDesc != NULL);
2470
2471 if (GPU_GET_MEMORY_MANAGER(pGpu)->bEnableDynamicGranularityPageArrays)
2472 {
2473 _memdescFillPagesAtNativeGranularity(pMemDesc, pageIndex, pPages, pageCount, pageSize);
2474 return;
2475 }
2476
2477 NV_ASSERT(offset4k < pMemDesc->PageCount);
2478 NV_ASSERT(portSafeAddU32(offset4k, pageCount4k, &result4k));
2479
2480 //
2481 // There is a possibility that the pMemDesc was created using 4K aligned
2482 // allocSize, but the actual memory allocator could align up the allocation
2483 // size based on its supported pageSize, (e.g. PMA supports 64K pages). In
2484 // that case, pageCount4k would be greater than pMemdesc->pageCount. We
2485 // limit pageCount4k to stay within pMemdesc->pageCount in that case.
2486 //
2487 if (result4k > pMemDesc->PageCount)
2488 pageCount4k = pMemDesc->PageCount - offset4k;
2489
2490 NV_ASSERT(pageSize > 0);
2491 NV_ASSERT(0 == (pageSize & (RM_PAGE_SIZE - 1)));
2492 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
2493
2494 // Fill _pteArray array using numChunks4k as a stride
2495 for (i = 0, j = offset4k; i < pageCount; i++, j += numChunks4k)
2496 {
2497 pMemDesc->_pteArray[j] = addr = pPages[i];
2498
2499 // Fill _pteArray at 4K granularity
2500 limit4k = NV_MIN(j + numChunks4k, pageCount4k);
2501
2502 addr += RM_PAGE_SIZE;
2503 for (k = j + 1; k < limit4k; k++, addr += RM_PAGE_SIZE)
2504 pMemDesc->_pteArray[k] = addr;
2505 }
2506 }
2507
2508 /*!
2509 * @brief Acquire exclusive use for memdesc for RM.
2510 *
2511 * @param[inout] pMemDesc Memory descriptor
2512 *
2513 * @returns Boolean indicating whether we successfully acquired the memdesc for exclusive use
2514 */
2515 NvBool
memdescAcquireRmExclusiveUse(MEMORY_DESCRIPTOR * pMemDesc)2516 memdescAcquireRmExclusiveUse
2517 (
2518 MEMORY_DESCRIPTOR *pMemDesc
2519 )
2520 {
2521 NV_CHECK_OR_RETURN(LEVEL_ERROR, pMemDesc->_pParentDescriptor == NULL &&
2522 !pMemDesc->bRmExclusiveUse &&
2523 pMemDesc->DupCount == 1,
2524 NV_FALSE);
2525
2526 pMemDesc->bRmExclusiveUse = NV_TRUE;
2527 return NV_TRUE;
2528 }
2529
2530 //
2531 // SubMemory per subdevice chart: (MD - Memory Descriptor, SD - subdevice)
2532 //
2533 // If we try to create submemory of descriptor which has subdevices:
2534 //
2535 // [Top level MD]
2536 // ^ |
2537 // | +--------> [ Subdevice 0 MD ] --------> [Subdevice 1 MD]
2538 // | ^ ^
2539 // | | |
2540 // [SubMemory top level MD] | |
2541 // | | |
2542 // +--------> [Subdevice 0 SubMemory MD] --------> [Subdevice 1 SubMemory MD]
2543 //
2544 // Top Level MD : parent of SubMemoryTopLevelMD; has subdescriptors
2545 // for two subdevices
2546 // SubMemory top level MD : has pointer to parent memory descriptor; has two
2547 // subdevice MDs
2548 // Subdevice 0 MD : subdevice MD of topLevelMD and parent of SD0
2549 // submemory descriptor; has pointer to next in the
2550 // list of subdevice MDs
2551 // Subdevice 0 SubMemory MD : submemory of subdevice 0 MD; has pointer to
2552 // parent, subdevice 0 MD and to next in list of
2553 // submemory subdevice memory descriptors
2554 //
2555
2556
2557
2558 /*!
2559 * @brief Create a new memory descriptor that is a subset of pMemDesc. If
2560 * pMemDesc has subdevice memory descriptors subMemory will be created for all
2561 * subdevices and new memory descriptor will be top level for them (ASCII art)
2562 *
2563 * @param[out] ppMemDescNew New memory descriptor
2564 * @param[in] pMemDesc Original memory descriptor
2565 * @param[in] pGpu The GPU that this memory will be mapped to
2566 * @param[in] Offset Sub memory descriptor starts at pMemdesc+Offset
2567 * @param[in] Size For Size bytes
2568 *
2569 * @returns None
2570 */
2571 NV_STATUS
memdescCreateSubMem(MEMORY_DESCRIPTOR ** ppMemDescNew,MEMORY_DESCRIPTOR * pMemDesc,OBJGPU * pGpu,NvU64 Offset,NvU64 Size)2572 memdescCreateSubMem
2573 (
2574 MEMORY_DESCRIPTOR **ppMemDescNew,
2575 MEMORY_DESCRIPTOR *pMemDesc,
2576 OBJGPU *pGpu,
2577 NvU64 Offset,
2578 NvU64 Size
2579 )
2580 {
2581 NV_STATUS status;
2582 MEMORY_DESCRIPTOR *pMemDescNew;
2583 NvU32 subDevInst;
2584 NvU64 tmpSize = Size;
2585 MEMORY_DESCRIPTOR *pLast;
2586 MEMORY_DESCRIPTOR *pNew;
2587 OBJGPU *pGpuChild;
2588 const NvU64 pageArrayGranularity = pMemDesc->pageArrayGranularity;
2589 const NvU64 pageArrayGranularityMask = pMemDesc->pageArrayGranularity - 1;
2590 const NvU32 pageArrayGranularityShift = BIT_IDX_64(pMemDesc->pageArrayGranularity);
2591
2592 // Default to the original memdesc's GPU if none is specified
2593 if (pGpu == NULL)
2594 {
2595 pGpu = pMemDesc->pGpu;
2596 }
2597
2598 // Allocation size should be adjusted for the memory descriptor _pageSize.
2599 // Also note that the first 4k page may not be at _pageSize boundary so at
2600 // the time of the mapping, we maybe overmapping at the beginning or end of
2601 // the descriptor. To fix it in the right way, memory descriptor needs to
2602 // be further cleaned. Do not round to page size if client specifies so.
2603 if (!(pMemDesc->_flags & MEMDESC_FLAGS_PAGE_SIZE_ALIGN_IGNORE) &&
2604 pMemDesc->_pageSize != 0)
2605 {
2606 PMEMORY_DESCRIPTOR pTempMemDesc = pMemDesc;
2607 NvU64 pageOffset;
2608
2609 if (memdescHasSubDeviceMemDescs(pMemDesc))
2610 {
2611 NV_ASSERT(pGpu);
2612 pTempMemDesc = memdescGetMemDescFromGpu(pMemDesc, pGpu);
2613 }
2614
2615 pageOffset = memdescGetPhysAddr(pTempMemDesc, AT_CPU, Offset) &
2616 (pTempMemDesc->_pageSize - 1);
2617
2618 // Check for integer overflow
2619 if (!portSafeAddU64(pageOffset, Size, &tmpSize))
2620 {
2621 return NV_ERR_INVALID_ARGUMENT;
2622 }
2623
2624 tmpSize = RM_ALIGN_UP(pageOffset + Size, pTempMemDesc->_pageSize);
2625
2626 // Check for integer overflow
2627 if (tmpSize < pageOffset + Size)
2628 {
2629 return NV_ERR_INVALID_ARGUMENT;
2630 }
2631 }
2632
2633 // Allocate the new MEMORY_DESCRIPTOR
2634 status = memdescCreate(&pMemDescNew, pGpu, tmpSize, 0,
2635 !!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS),
2636 pMemDesc->_addressSpace,
2637 pMemDesc->_cpuCacheAttrib,
2638 ((pMemDesc->_flags & ~MEMDESC_FLAGS_PRE_ALLOCATED) | MEMDESC_FLAGS_SKIP_RESOURCE_COMPUTE));
2639
2640 if (status != NV_OK)
2641 {
2642 return status;
2643 }
2644
2645 // Fill in various fields as best we can; XXX this can get sort of sketchy
2646 // in places, which should be all the more motivation to rip some of these
2647 // fields out of the MEMORY_DESCRIPTOR.
2648 if (pMemDesc->_flags & MEMDESC_FLAGS_KERNEL_MODE)
2649 pMemDescNew->_flags |= MEMDESC_FLAGS_KERNEL_MODE;
2650 else
2651 pMemDescNew->_flags &= ~MEMDESC_FLAGS_KERNEL_MODE;
2652
2653 //
2654 // This flag used to indicate the memdesc needs to restore pte kind
2655 // when it is freed. It should only not be set for any sub memDesc.
2656 //
2657 pMemDescNew->_flags &= ~MEMDESC_FLAGS_RESTORE_PTE_KIND_ON_FREE;
2658
2659 pMemDescNew->Size = Size;
2660 pMemDescNew->_pteKind = pMemDesc->_pteKind;
2661 pMemDescNew->_hwResId = pMemDesc->_hwResId;
2662 if (pMemDesc->_flags & MEMDESC_FLAGS_ENCRYPTED)
2663 pMemDescNew->_flags |= MEMDESC_FLAGS_ENCRYPTED;
2664 else
2665 pMemDescNew->_flags &= ~MEMDESC_FLAGS_ENCRYPTED;
2666 pMemDescNew->_pageSize = pMemDesc->_pageSize;
2667 pMemDescNew->pageArrayGranularity = pageArrayGranularity;
2668 pMemDescNew->_gpuCacheAttrib = pMemDesc->_gpuCacheAttrib;
2669 pMemDescNew->_gpuP2PCacheAttrib = pMemDesc->_gpuP2PCacheAttrib;
2670 pMemDescNew->gfid = pMemDesc->gfid;
2671 pMemDescNew->bUsingSuballocator = pMemDesc->bUsingSuballocator;
2672 pMemDescNew->_pParentDescriptor = pMemDesc;
2673 pMemDesc->childDescriptorCnt++;
2674 pMemDescNew->bRmExclusiveUse = pMemDesc->bRmExclusiveUse;
2675 pMemDescNew->numaNode = pMemDesc->numaNode;
2676
2677 pMemDescNew->subMemOffset = Offset;
2678
2679 // increase refCount of parent descriptor
2680 memdescAddRef(pMemDesc);
2681
2682 // Fill in the PteArray and PteAdjust
2683 if ((pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS) ||
2684 (pMemDesc->PageCount == 1))
2685 {
2686 // Compute the base address, then fill it in
2687 RmPhysAddr Base = pMemDesc->_pteArray[0] + pMemDesc->PteAdjust + Offset;
2688 pMemDescNew->_pteArray[0] = Base & ~pageArrayGranularityMask;
2689 pMemDescNew->PteAdjust = NvU64_LO32(Base) & pageArrayGranularityMask;
2690
2691 if (memdescIsEgm(pMemDesc))
2692 {
2693 NV_ASSERT_OK_OR_GOTO(status,
2694 _memdescAllocEgmArray(pMemDescNew),
2695 fail);
2696 }
2697 }
2698 else
2699 {
2700 // More complicated...
2701 RmPhysAddr Adjust;
2702 NvU32 PageIndex, i;
2703
2704 // We start this many bytes into the memory alloc
2705 Adjust = pMemDesc->PteAdjust + Offset;
2706
2707 // Break it down into pages (PageIndex) and bytes (PteAdjust)
2708 PageIndex = (NvU32)(Adjust >> pageArrayGranularityShift);
2709 pMemDescNew->PteAdjust = NvU64_LO32(Adjust) & pageArrayGranularityMask;
2710
2711 // Fill in the PTEs; remember to copy the extra PTE, in case we need it
2712 if (pMemDesc->PageCount)
2713 {
2714 for (i = 0; i < pMemDescNew->PageCount+1; i++)
2715 {
2716 NvU32 j = i + PageIndex;
2717 if (j < pMemDesc->PageCount)
2718 {
2719 pMemDescNew->_pteArray[i] = pMemDesc->_pteArray[j];
2720 }
2721 else
2722 {
2723 //
2724 // This case can happen with page size greater than 4KB.
2725 // Since pages are always tracked at 4KB granularity the
2726 // subset description may overflow the parent memdesc.
2727 //
2728 // In this case the best we can do is describe the contiguous
2729 // memory after the last 4KB page in the sub-memdesc.
2730 //
2731 // TODO: Tracking memdesc pages at native page size would
2732 // remove the need for several hacks, including this one.
2733 //
2734 NV_ASSERT(i > 0);
2735 pMemDescNew->_pteArray[i] = pMemDescNew->_pteArray[i - 1] + pMemDescNew->pageArrayGranularity;
2736 }
2737 }
2738
2739 if (memdescIsEgm(pMemDesc))
2740 {
2741 NV_ASSERT_OK_OR_GOTO(status,
2742 _memdescAllocEgmArray(pMemDescNew),
2743 fail);
2744 }
2745 }
2746 }
2747
2748 if ((pMemDesc->_addressSpace == ADDR_SYSMEM) &&
2749 !memdescIsEgm(pMemDesc) &&
2750 !memdescGetFlag(memdescGetMemDescFromGpu(pMemDesc, pGpu), MEMDESC_FLAGS_CPU_ONLY) &&
2751 !memdescGetFlag(memdescGetMemDescFromGpu(pMemDesc, pGpu), MEMDESC_FLAGS_MAP_SYSCOH_OVER_BAR1) &&
2752 !memdescGetFlag(memdescGetMemDescFromGpu(pMemDesc, pGpu), MEMDESC_FLAGS_SKIP_IOMMU_MAPPING))
2753 {
2754 //
2755 // For different IOVA spaces, the IOMMU mapping will often not be a
2756 // subrange of the original mapping.
2757 //
2758 // Request the submapping to be associated with the submemdesc.
2759 //
2760 // TODO: merge the new IOMMU paths with the SMMU path above (see bug
2761 // 1625121).
2762 //
2763 status = memdescMapIommu(pMemDescNew, pGpu->busInfo.iovaspaceId);
2764 if (status != NV_OK)
2765 {
2766 memdescDestroy(pMemDescNew);
2767 return status;
2768 }
2769 }
2770
2771 // Support for SLI submemory per-subdevice allocations (refer to chart)
2772 if (memdescHasSubDeviceMemDescs(pMemDesc))
2773 {
2774 NvBool bBcState = gpumgrGetBcEnabledStatus(pGpu);
2775
2776 if (gpumgrGetBcEnabledStatus(pGpu) && (pMemDesc->_addressSpace == ADDR_FBMEM))
2777 {
2778 NV_ASSERT(!!(pMemDesc->_flags & MEMDESC_FLAGS_ALLOC_PER_SUBDEVICE));
2779 gpumgrSetBcEnabledStatus(pGpu, NV_FALSE);
2780 }
2781 pLast = pMemDescNew;
2782
2783 pMemDescNew->_subDeviceAllocCount = pMemDesc->_subDeviceAllocCount;
2784
2785 for (subDevInst = 0; subDevInst < pMemDesc->_subDeviceAllocCount; subDevInst++)
2786 {
2787 pGpuChild = gpumgrGetGpuFromSubDeviceInst(gpuGetDeviceInstance(pGpu), subDevInst);
2788 status = memdescCreateSubMem(&pNew, memdescGetMemDescFromGpu(pMemDesc, pGpuChild), pGpuChild, Offset, Size);
2789
2790 if (status != NV_OK)
2791 {
2792 while (NULL != pMemDescNew)
2793 {
2794 pNew = pMemDescNew;
2795 pMemDescNew = pMemDescNew->_pNext;
2796 memdescDestroy(pNew);
2797 }
2798 return status;
2799 }
2800
2801 pLast->_pNext = pNew;
2802 pLast = pNew;
2803 }
2804
2805 gpumgrSetBcEnabledStatus(pGpu, bBcState);
2806 }
2807
2808 *ppMemDescNew = pMemDescNew;
2809
2810 return NV_OK;
2811
2812 fail:
2813 memdescDestroy(pMemDescNew);
2814 return status;
2815 }
2816
2817 /*!
2818 * Given a memdesc, this checks if the allocated memory falls under subheap or in GPA address space
2819 */
2820 static NvBool
_memIsSriovMappingsEnabled(PMEMORY_DESCRIPTOR pMemDesc)2821 _memIsSriovMappingsEnabled
2822 (
2823 PMEMORY_DESCRIPTOR pMemDesc
2824 )
2825 {
2826 return gpuIsSriovEnabled(pMemDesc->pGpu) &&
2827 (((pMemDesc->_flags & MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE) && pMemDesc->bUsingSuballocator) ||
2828 (pMemDesc->_flags & MEMDESC_FLAGS_GUEST_ALLOCATED));
2829 }
2830
2831 /*!
2832 * Fills pGpaEntries with numEntries GPAs from pMemDesc->_pteArray starting at
2833 * the given starting index. For physically contiguous memdescs, fills with
2834 * RM_PAGE_SIZE strides.
2835 */
2836 static void
_memdescFillGpaEntriesForSpaTranslation(PMEMORY_DESCRIPTOR pMemDesc,RmPhysAddr * pGpaEntries,NvU32 start,NvU32 numEntries)2837 _memdescFillGpaEntriesForSpaTranslation
2838 (
2839 PMEMORY_DESCRIPTOR pMemDesc,
2840 RmPhysAddr *pGpaEntries,
2841 NvU32 start,
2842 NvU32 numEntries
2843 )
2844 {
2845 if (pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS)
2846 {
2847 NvU32 i;
2848
2849 for (i = 0; i < numEntries; i++)
2850 {
2851 pGpaEntries[i] = pMemDesc->_pteArray[0] + (((RmPhysAddr) (start + i)) * pMemDesc->pageArrayGranularity);
2852 }
2853 }
2854 else
2855 {
2856 portMemCopy(&pGpaEntries[0], numEntries * sizeof(pGpaEntries[0]),
2857 &pMemDesc->_pteArray[start], numEntries * sizeof(pGpaEntries[0]));
2858 }
2859 }
2860
2861 /*!
2862 * This function translates GPA -> SPA for a given memdesc and updates pPteSpaMappings with list of SPA addresses.
2863 * If memdesc is contiguous and if the translated SPA count > 1, this function fails for now.
2864 */
2865 NV_STATUS
_memdescUpdateSpaArray(PMEMORY_DESCRIPTOR pMemDesc)2866 _memdescUpdateSpaArray
2867 (
2868 PMEMORY_DESCRIPTOR pMemDesc
2869 )
2870 {
2871 NV_STATUS status = NV_OK;
2872 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pMemDesc->pGpu);
2873 NvU32 allocCnt;
2874 NvU32 i;
2875 NV2080_CTRL_INTERNAL_VMMU_GET_SPA_FOR_GPA_ENTRIES_PARAMS *pParams = NULL;
2876
2877 if ((pMemDesc->pPteSpaMappings) || (!pMemDesc->PageCount))
2878 {
2879 status = NV_OK;
2880 goto _memUpdateSpArray_exit;
2881 }
2882
2883 allocCnt = memdescGetPteArraySize(pMemDesc, AT_PA);
2884
2885 // Allocate the array to hold pages up to PageCount
2886 pMemDesc->pPteSpaMappings = portMemAllocNonPaged(sizeof(RmPhysAddr) * allocCnt);
2887 if (pMemDesc->pPteSpaMappings == NULL)
2888 {
2889 status = NV_ERR_NO_MEMORY;
2890 goto _memUpdateSpArray_exit;
2891 }
2892
2893 pParams = portMemAllocStackOrHeap(sizeof(*pParams));
2894 if (pParams == NULL)
2895 {
2896 status = NV_ERR_NO_MEMORY;
2897 goto _memUpdateSpArray_exit;
2898 }
2899 portMemSet(pParams, 0, sizeof(*pParams));
2900
2901 pParams->gfid = pMemDesc->gfid;
2902
2903 for (i = 0; i < allocCnt; i += NV2080_CTRL_INTERNAL_VMMU_MAX_SPA_FOR_GPA_ENTRIES)
2904 {
2905 NvU32 numEntries = NV_MIN(allocCnt - i, NV2080_CTRL_INTERNAL_VMMU_MAX_SPA_FOR_GPA_ENTRIES);
2906 pParams->numEntries = numEntries;
2907
2908 _memdescFillGpaEntriesForSpaTranslation(pMemDesc, &pParams->gpaEntries[0],
2909 i, numEntries);
2910
2911 status = pRmApi->Control(pRmApi,
2912 pMemDesc->pGpu->hInternalClient,
2913 pMemDesc->pGpu->hInternalSubdevice,
2914 NV2080_CTRL_CMD_INTERNAL_VMMU_GET_SPA_FOR_GPA_ENTRIES,
2915 pParams,
2916 sizeof(*pParams));
2917 if (status != NV_OK)
2918 {
2919 NV_PRINTF(LEVEL_ERROR, "Getting SPA for GPA failed: GFID=%u, GPA=0x%llx\n",
2920 pMemDesc->gfid, pMemDesc->_pteArray[i]);
2921 goto _memUpdateSpArray_exit;
2922 }
2923
2924 portMemCopy(&pMemDesc->pPteSpaMappings[i], numEntries * sizeof(pParams->spaEntries[0]),
2925 &pParams->spaEntries[0], numEntries * sizeof(pParams->spaEntries[0]));
2926 }
2927
2928 _memUpdateSpArray_exit:
2929 if (status != NV_OK)
2930 {
2931 portMemFree(pMemDesc->pPteSpaMappings);
2932 pMemDesc->pPteSpaMappings = NULL;
2933 }
2934 portMemFreeStackOrHeap(pParams);
2935
2936 return status;
2937 }
2938
2939 /*!
2940 * @brief Return the physical addresses of pMemdesc
2941 *
2942 * @param[in] pMemDesc Memory descriptor used
2943 * @param[in] pGpu GPU to return the addresses for
2944 * @param[in] addressTranslation Address translation identifier
2945 * @param[in] offset Offset into memory descriptor
2946 * @param[in] stride How much to advance the offset for each
2947 * consecutive address
2948 * @param[in] count How many addresses to retrieve
2949 * @param[out] pAddresses Returned array of addresses
2950 *
2951 */
memdescGetPhysAddrsForGpu(MEMORY_DESCRIPTOR * pMemDesc,OBJGPU * pGpu,ADDRESS_TRANSLATION addressTranslation,NvU64 offset,NvU64 stride,NvU64 count,RmPhysAddr * pAddresses)2952 void memdescGetPhysAddrsForGpu(MEMORY_DESCRIPTOR *pMemDesc,
2953 OBJGPU *pGpu,
2954 ADDRESS_TRANSLATION addressTranslation,
2955 NvU64 offset,
2956 NvU64 stride,
2957 NvU64 count,
2958 RmPhysAddr *pAddresses)
2959 {
2960 //
2961 // Get the PTE array that we should use for phys addr lookups based on the
2962 // MMU context. (see bug 1625121)
2963 //
2964 NvU64 i;
2965 NvU64 pageIndex;
2966 RmPhysAddr *pteArray = memdescGetPteArrayForGpu(pMemDesc, pGpu, addressTranslation);
2967 const NvBool contiguous = (memdescGetPteArraySize(pMemDesc, addressTranslation) == 1);
2968 const NvU64 pageArrayGranularityMask = pMemDesc->pageArrayGranularity - 1;
2969 const NvU32 pageArrayGranularityShift = BIT_IDX_64(pMemDesc->pageArrayGranularity);
2970
2971 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
2972 offset += pMemDesc->PteAdjust;
2973
2974 for (i = 0; i < count; ++i)
2975 {
2976 if (contiguous)
2977 {
2978 pAddresses[i] = pteArray[0] + offset;
2979 }
2980 else
2981 {
2982 pageIndex = offset >> pageArrayGranularityShift;
2983 NV_CHECK_OR_RETURN_VOID(LEVEL_ERROR, pageIndex < pMemDesc->PageCount);
2984 pAddresses[i] = pteArray[pageIndex] + (offset & pageArrayGranularityMask);
2985 }
2986
2987 offset += stride;
2988 }
2989 }
2990
2991
2992 /*!
2993 * @brief Return the physical addresses of pMemdesc
2994 *
2995 * @param[in] pMemDesc Memory descriptor used
2996 * @param[in] addressTranslation Address translation identifier
2997 * @param[in] offset Offset into memory descriptor
2998 * @param[in] stride How much to advance the offset for each
2999 * consecutive address
3000 * @param[in] count How many addresses to retrieve
3001 * @param[out] pAddresses Returned array of addresses
3002 *
3003 */
memdescGetPhysAddrs(MEMORY_DESCRIPTOR * pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU64 offset,NvU64 stride,NvU64 count,RmPhysAddr * pAddresses)3004 void memdescGetPhysAddrs(MEMORY_DESCRIPTOR *pMemDesc,
3005 ADDRESS_TRANSLATION addressTranslation,
3006 NvU64 offset,
3007 NvU64 stride,
3008 NvU64 count,
3009 RmPhysAddr *pAddresses)
3010 {
3011 memdescGetPhysAddrsForGpu(pMemDesc, pMemDesc->pGpu, addressTranslation, offset, stride, count, pAddresses);
3012 }
3013
3014 /*!
3015 * @brief Return the physical address of pMemdesc+Offset
3016 *
3017 * "long description"
3018 *
3019 * @param[in] pMemDesc Memory descriptor used
3020 * @param[in] addressTranslation Address translation identifier
3021 * @param[in] offset Offset into memory descriptor
3022 *
3023 * @returns A physical address
3024 */
3025 RmPhysAddr
memdescGetPhysAddr(MEMORY_DESCRIPTOR * pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU64 offset)3026 memdescGetPhysAddr
3027 (
3028 MEMORY_DESCRIPTOR *pMemDesc,
3029 ADDRESS_TRANSLATION addressTranslation,
3030 NvU64 offset
3031 )
3032 {
3033 RmPhysAddr addr;
3034 memdescGetPhysAddrs(pMemDesc, addressTranslation, offset, 0, 1, &addr);
3035 return addr;
3036 }
3037
3038 /*!
3039 * @brief Return physical address for page specified by PteIndex
3040 *
3041 * @param[in] pMemDesc Memory descriptor to use
3042 * @param[in] addressTranslation Address translation identifier
3043 * @param[in] PteIndex Look up this PteIndex
3044 *
3045 * @returns A physical address
3046 */
3047 RmPhysAddr
memdescGetPte(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU32 PteIndex)3048 memdescGetPte
3049 (
3050 PMEMORY_DESCRIPTOR pMemDesc,
3051 ADDRESS_TRANSLATION addressTranslation,
3052 NvU32 PteIndex
3053 )
3054 {
3055 //
3056 // Get the PTE array that we should use for phys addr lookups based on the
3057 // MMU context. (see bug 1625121)
3058 //
3059 RmPhysAddr *pteArray = memdescGetPteArray(pMemDesc, addressTranslation);
3060 RmPhysAddr PhysAddr;
3061
3062 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3063
3064 if (pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS)
3065 {
3066 PhysAddr = pteArray[0] + (PteIndex << RM_PAGE_SHIFT);
3067 }
3068 else
3069 {
3070 PhysAddr = pteArray[PteIndex];
3071 }
3072
3073 return PhysAddr;
3074 }
3075
3076 /*!
3077 * @brief Return physical address for page specified by PteIndex
3078 *
3079 * @param[in] pMemDesc Memory descriptor to use
3080 * @param[in] addressTranslation Address translation identifier
3081 * @param[in] PteIndex Look up this PteIndex
3082 * @param[in] PhysAddr PTE address
3083 *
3084 * @returns None
3085 */
3086 void
memdescSetPte(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU32 PteIndex,RmPhysAddr PhysAddr)3087 memdescSetPte
3088 (
3089 PMEMORY_DESCRIPTOR pMemDesc,
3090 ADDRESS_TRANSLATION addressTranslation,
3091 NvU32 PteIndex,
3092 RmPhysAddr PhysAddr
3093 )
3094 {
3095 //
3096 // Get the PTE array that we should use for phys addr lookups based on the
3097 // MMU context. (see bug 1625121)
3098 //
3099 RmPhysAddr *pteArray = memdescGetPteArray(pMemDesc, addressTranslation);
3100 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3101
3102 if (pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS)
3103 {
3104 NV_ASSERT_OR_RETURN_VOID(PteIndex == 0);
3105 }
3106
3107 pteArray[PteIndex] = PhysAddr;
3108
3109 // Free pteArraySpa
3110 portMemFree(pMemDesc->pPteSpaMappings);
3111 pMemDesc->pPteSpaMappings = NULL;
3112 }
3113
3114 /*!
3115 * @brief Return page array size based on the MMU context
3116 * For SRIOV, the host context (AT_PA) will
3117 * have discontiguous view of the GPA in SPA space
3118 * This is treated similar to discontiguous memdescs
3119 *
3120 * @param[in] pMemDesc Memory descriptor to use
3121 * @param[in] addressTranslation Address translation identifier
3122 *
3123 * @returns PageArray
3124 */
memdescGetPteArraySize(MEMORY_DESCRIPTOR * pMemDesc,ADDRESS_TRANSLATION addressTranslation)3125 NvU32 memdescGetPteArraySize(MEMORY_DESCRIPTOR *pMemDesc, ADDRESS_TRANSLATION addressTranslation)
3126 {
3127 // Contiguous allocations in SPA domain can be non-contiguous at vmmusegment granularity.
3128 // Hence treat SPA domain allocations as non-contiguous by default.
3129 if (!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS) ||
3130 ((addressTranslation == AT_PA) && (pMemDesc->_addressSpace == ADDR_FBMEM) && _memIsSriovMappingsEnabled(pMemDesc)))
3131 {
3132 return NvU64_LO32(pMemDesc->PageCount);
3133 }
3134 return 1;
3135 }
3136
3137 /*!
3138 * @brief Return page array
3139 *
3140 * @param[in] pMemDesc Memory descriptor to use
3141 * @param[in] pGpu GPU to get the PTE array for.
3142 * @param[in] addressTranslation Address translation identifier
3143 *
3144 * @returns PageArray
3145 */
3146 RmPhysAddr *
memdescGetPteArrayForGpu(PMEMORY_DESCRIPTOR pMemDesc,OBJGPU * pGpu,ADDRESS_TRANSLATION addressTranslation)3147 memdescGetPteArrayForGpu
3148 (
3149 PMEMORY_DESCRIPTOR pMemDesc,
3150 OBJGPU *pGpu,
3151 ADDRESS_TRANSLATION addressTranslation
3152 )
3153 {
3154 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3155
3156 switch (AT_VALUE(addressTranslation))
3157 {
3158 //
3159 // In SRIOV systems, an access from guest has to go through the following translations
3160 // GVA -> GPA -> SPA
3161 //
3162 // Given HOST manages channel/memory management for guest, there are certain code paths that
3163 // expects VA -> GPA translations and some may need GPA -> SPA translations. We use addressTranslation
3164 // to differentiate between these cases.
3165 // Since GPA -> SPA is very similar to IOMMU xlation and since existing AT_PA is used only in
3166 // SYSMEM allocations, we decided to reuse AT_PA addressTranslation to fetch GPA -> SPA xlations.
3167 // In case of non-SRIOV systems, using AT_PA will fall back to AT_GPU or default context.
3168 //
3169 // pMemDesc -> _pteArray tracks GVA -> GPA translations
3170 // pMemDesc -> pPteSpaMappings tracks GPA -> SPA translations
3171 //
3172
3173 case AT_VALUE(AT_PA):
3174 {
3175 if (pGpu != NULL)
3176 {
3177 if (pMemDesc->_addressSpace == ADDR_FBMEM)
3178 {
3179 if (_memIsSriovMappingsEnabled(pMemDesc))
3180 {
3181 if (!pMemDesc->pPteSpaMappings)
3182 _memdescUpdateSpaArray(pMemDesc);
3183
3184 return pMemDesc->pPteSpaMappings;
3185 }
3186 }
3187 }
3188 }
3189 case AT_VALUE(AT_GPU):
3190 {
3191 // Imported ADDR_FABRIC_V2 memdescs are device-less.
3192 if (pGpu != NULL)
3193 {
3194 if (memdescIsEgm(pMemDesc) && (pMemDesc->pPteEgmMappings != NULL))
3195 {
3196 return pMemDesc->pPteEgmMappings;
3197 }
3198
3199 PIOVAMAPPING pIovaMap = memdescGetIommuMap(pMemDesc,
3200 pGpu->busInfo.iovaspaceId);
3201 if (pIovaMap != NULL)
3202 {
3203 return pIovaMap->iovaArray;
3204 }
3205 }
3206
3207 //
3208 // If no IOMMU mapping exists in the default IOVASPACE, fall
3209 // through and use the physical memory descriptor instead.
3210 //
3211 }
3212 default:
3213 {
3214 return pMemDesc->_pteArray;
3215 }
3216 }
3217 }
3218
3219
3220
3221 /*!
3222 * @brief Convert aperture into a descriptive string.
3223 *
3224 * @param[in] addressSpace
3225 *
3226 * @returns String
3227 *
3228 * @todo "text"
3229 */
3230 const char *
memdescGetApertureString(NV_ADDRESS_SPACE addressSpace)3231 memdescGetApertureString
3232 (
3233 NV_ADDRESS_SPACE addressSpace
3234 )
3235 {
3236 static NV_PRINTF_STRING_SECTION const char ADDR_FBMEM_STR[] = "VIDEO MEMORY";
3237 static NV_PRINTF_STRING_SECTION const char ADDR_SYSMEM_STR[] = "SYSTEM MEMORY";
3238
3239 if (addressSpace == ADDR_FBMEM)
3240 {
3241 return ADDR_FBMEM_STR;
3242 }
3243
3244 if (addressSpace == ADDR_SYSMEM)
3245 {
3246 return ADDR_SYSMEM_STR;
3247 }
3248
3249 return NULL;
3250 }
3251
3252 /*!
3253 * @brief Compare two memory descriptors to see if the memory described the same
3254 *
3255 * @param[in] pMemDescOne
3256 * @param[in] pMemDescTwo
3257 *
3258 * @returns NV_TRUE if the memory descriptors refer to the same memory
3259 */
3260 NvBool
memdescDescIsEqual(MEMORY_DESCRIPTOR * pMemDescOne,MEMORY_DESCRIPTOR * pMemDescTwo)3261 memdescDescIsEqual
3262 (
3263 MEMORY_DESCRIPTOR *pMemDescOne,
3264 MEMORY_DESCRIPTOR *pMemDescTwo
3265 )
3266 {
3267 if ((pMemDescOne == NULL) || (pMemDescTwo == NULL))
3268 return NV_FALSE;
3269
3270 if (pMemDescOne->_addressSpace != pMemDescTwo->_addressSpace)
3271 return NV_FALSE;
3272
3273 // All the physical memory views should match.
3274 if ((memdescGetPhysAddr(pMemDescOne, AT_CPU, 0) != memdescGetPhysAddr(pMemDescTwo, AT_CPU, 0)) ||
3275 (memdescGetPhysAddr(pMemDescOne, AT_GPU, 0) != memdescGetPhysAddr(pMemDescTwo, AT_GPU, 0)))
3276 return NV_FALSE;
3277
3278 if (memdescGetCpuCacheAttrib(pMemDescOne) != memdescGetCpuCacheAttrib(pMemDescTwo))
3279 return NV_FALSE;
3280
3281 if (pMemDescOne->Size != pMemDescTwo->Size)
3282 return NV_FALSE;
3283
3284 if (pMemDescOne->Alignment != pMemDescTwo->Alignment)
3285 return NV_FALSE;
3286
3287 if (pMemDescOne->_pageSize != pMemDescTwo->_pageSize)
3288 return NV_FALSE;
3289
3290 return NV_TRUE;
3291 }
3292
3293 /*!
3294 * @brief Add callback block to the destroy callback queue
3295 *
3296 * @param[in] pMemDesc Memory descriptor to update
3297 * @param[in] pCb Callee allocated block with callback func/arg
3298 *
3299 * @returns nothing
3300 */
3301 void
memdescAddDestroyCallback(MEMORY_DESCRIPTOR * pMemDesc,MEM_DESC_DESTROY_CALLBACK * pCb)3302 memdescAddDestroyCallback
3303 (
3304 MEMORY_DESCRIPTOR *pMemDesc,
3305 MEM_DESC_DESTROY_CALLBACK *pCb
3306 )
3307 {
3308 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3309 pCb->pNext = memdescGetDestroyCallbackList(pMemDesc);
3310 memdescSetDestroyCallbackList(pMemDesc, pCb);
3311 }
3312
3313 /*!
3314 * @brief Remove callback block from the destroy callback queue
3315 *
3316 * @param[in] pMemDesc Memory descriptor to update
3317 * @param[in] pRemoveCb Callee allocated block with callback func/arg
3318 *
3319 * @returns nothing
3320 */
3321 void
memdescRemoveDestroyCallback(MEMORY_DESCRIPTOR * pMemDesc,MEM_DESC_DESTROY_CALLBACK * pRemoveCb)3322 memdescRemoveDestroyCallback
3323 (
3324 MEMORY_DESCRIPTOR *pMemDesc,
3325 MEM_DESC_DESTROY_CALLBACK *pRemoveCb
3326 )
3327 {
3328 MEM_DESC_DESTROY_CALLBACK *pCb = memdescGetDestroyCallbackList(pMemDesc);
3329 MEM_DESC_DESTROY_CALLBACK *pPrev = NULL;
3330
3331 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3332 while (pCb)
3333 {
3334 if (pCb == pRemoveCb)
3335 {
3336 if (pPrev == NULL)
3337 {
3338 memdescSetDestroyCallbackList(pMemDesc, pCb->pNext);
3339 }
3340 else
3341 {
3342 pPrev->pNext = pCb->pNext;
3343 }
3344 break;
3345 }
3346 pPrev = pCb;
3347 pCb = pCb->pNext;
3348 }
3349 }
3350
3351 /*!
3352 * @brief Retrieves a subdevice's memory descriptor by subdevice instance
3353 *
3354 * Subdevice memory descriptors are memory descriptors that describe
3355 * per-subdevice memory buffers. This functionality is required by our current
3356 * SLI programming model as our memdescAlloc() calls are primarily broadcast
3357 * operations. A singular memdesc works for video memory as the
3358 * heaps are symmetric. However, we run into trouble when dealing with system
3359 * memory as both GPUs then share the same address space and symmetric
3360 * addressing is no longer possible.
3361 *
3362 * N.B. The rational for exposing this routine is that it keeps SLI-isms out of
3363 * most of the RM -- the alternative approach would've been to pass in the
3364 * subdevice or a pGpu for all memdesc methods which would require more code
3365 * changes solely for SLI. Long term hopefully we can transition to a unicast
3366 * allocation model (SLI loops above memdescAlloc()/memdescCreate()) and the
3367 * subdevice support in memdesc can (easily) be deleted. This approach also
3368 * provides a safety net against misuse, e.g., if we added pGpu to
3369 * memdescGetPhysAddr, current code which utilizes that routine outside an SLI loop
3370 * would execute cleanly even though it's incorrect.
3371 *
3372 * @param[in] pMemDesc Memory descriptor to query
3373 * @param[in] subDeviceInst SLI subdevice instance (subdevice - 1)
3374 *
3375 * @returns Memory descriptor if one exist for the subdevice.
3376 * NULL if none is found.
3377 */
3378 MEMORY_DESCRIPTOR *
memdescGetMemDescFromSubDeviceInst(MEMORY_DESCRIPTOR * pMemDesc,NvU32 subDeviceInst)3379 memdescGetMemDescFromSubDeviceInst(MEMORY_DESCRIPTOR *pMemDesc, NvU32 subDeviceInst)
3380 {
3381 if (!memdescHasSubDeviceMemDescs(pMemDesc))
3382 {
3383 return pMemDesc;
3384 }
3385 else
3386 {
3387 return memdescGetMemDescFromIndex(pMemDesc, subDeviceInst);
3388 }
3389 }
3390
3391 /*!
3392 * @brief Retrieves a subdevice's memory descriptor by GPU object
3393 *
3394 * See memdescGetMemDescFromSubDeviceInst for an explanation of subdevice memory
3395 * descriptors
3396 *
3397 * @param[in] pMemDesc Memory descriptor to query
3398 * @param[in] pGpu
3399 *
3400 * @returns Memory descriptor if one exist for the GPU.
3401 * NULL if none is found.
3402 */
3403 MEMORY_DESCRIPTOR *
memdescGetMemDescFromGpu(MEMORY_DESCRIPTOR * pMemDesc,OBJGPU * pGpu)3404 memdescGetMemDescFromGpu(MEMORY_DESCRIPTOR *pMemDesc, OBJGPU *pGpu)
3405 {
3406 NvU32 subDeviceInst = gpumgrGetSubDeviceInstanceFromGpu(pGpu);
3407
3408 return memdescGetMemDescFromSubDeviceInst(pMemDesc, subDeviceInst);
3409 }
3410
3411 /*!
3412 * @brief Retrieves a subdevice's memory descriptor by memdesc index.
3413 *
3414 * See memdescGetMemDescFromSubDeviceInst for an explanation of subdevice memory
3415 * descriptors
3416 *
3417 * @param[in] pMemDesc Memory descriptor to query
3418 * @param[in] index Index into array of memdesc
3419 *
3420 * @returns Memory descriptor if one exist for the GPU.
3421 * NULL if none is found.
3422 */
3423 MEMORY_DESCRIPTOR *
memdescGetMemDescFromIndex(MEMORY_DESCRIPTOR * pMemDesc,NvU32 index)3424 memdescGetMemDescFromIndex(MEMORY_DESCRIPTOR *pMemDesc, NvU32 index)
3425 {
3426 if (!memdescHasSubDeviceMemDescs(pMemDesc))
3427 {
3428 return pMemDesc;
3429 }
3430 else
3431 {
3432 MEMORY_DESCRIPTOR *pSubDevMemDesc = pMemDesc->_pNext;
3433
3434 NV_ASSERT(pSubDevMemDesc);
3435
3436 while (index--)
3437 {
3438 pSubDevMemDesc = pSubDevMemDesc->_pNext;
3439
3440 if (!pSubDevMemDesc)
3441 {
3442 NV_ASSERT(0);
3443 return NULL;
3444 }
3445 }
3446
3447 return pSubDevMemDesc;
3448 }
3449 }
3450
3451 /*!
3452 * @brief Set address for a fixed heap allocation.
3453 *
3454 * Offset must refer to the heap. A later memdescAlloc() will
3455 * force this offset.
3456 *
3457 * @param[in] pMemDesc Memory descriptor to update
3458 * @param[in] fbOffset Offset to refer to
3459 *
3460 * @returns nothing
3461 */
3462 void
memdescSetHeapOffset(MEMORY_DESCRIPTOR * pMemDesc,RmPhysAddr fbOffset)3463 memdescSetHeapOffset
3464 (
3465 MEMORY_DESCRIPTOR *pMemDesc,
3466 RmPhysAddr fbOffset
3467 )
3468 {
3469 NV_ASSERT(pMemDesc->_addressSpace == ADDR_FBMEM);
3470 NV_ASSERT(pMemDesc->Allocated == NV_FALSE);
3471
3472 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3473 pMemDesc->_flags |= MEMDESC_FLAGS_FIXED_ADDRESS_ALLOCATE;
3474 pMemDesc->_pteArray[0] = fbOffset;
3475 }
3476
3477 /*!
3478 * @brief Set GPU cacheability
3479 *
3480 * A later memdescAlloc() will use this setting.
3481 *
3482 * @param[in] pMemDesc Memory descriptor to update
3483 * @param[in] cacheAttrib Set memory to GPU cacheable
3484 *
3485 * @returns nothing
3486 */
memdescSetGpuCacheAttrib(MEMORY_DESCRIPTOR * pMemDesc,NvU32 cacheAttrib)3487 void memdescSetGpuCacheAttrib
3488 (
3489 MEMORY_DESCRIPTOR *pMemDesc,
3490 NvU32 cacheAttrib
3491 )
3492 {
3493 NV_ASSERT(pMemDesc->Allocated == NV_FALSE);
3494
3495 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3496 pMemDesc->_gpuCacheAttrib = cacheAttrib;
3497 }
3498
3499 /*!
3500 * @brief Get GPU P2P cache attributes
3501 *
3502 * @param[in] pMemDesc Memory descriptor pointer
3503 *
3504 * @returns Current GPU P2P cache attributes
3505 */
memdescGetGpuP2PCacheAttrib(MEMORY_DESCRIPTOR * pMemDesc)3506 NvU32 memdescGetGpuP2PCacheAttrib
3507 (
3508 MEMORY_DESCRIPTOR *pMemDesc
3509 )
3510 {
3511 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3512 return pMemDesc->_gpuP2PCacheAttrib;
3513 }
3514
3515 /*!
3516 * @brief Set GPU P2P cacheability
3517 *
3518 * A later memdescAlloc() will use this setting.
3519 *
3520 * @param[in] pMemDesc Memory descriptor to update
3521 * @param[in] cacheAttrib Set memory to GPU P2P cacheable
3522 *
3523 * @returns nothing
3524 */
memdescSetGpuP2PCacheAttrib(MEMORY_DESCRIPTOR * pMemDesc,NvU32 cacheAttrib)3525 void memdescSetGpuP2PCacheAttrib
3526 (
3527 MEMORY_DESCRIPTOR *pMemDesc,
3528 NvU32 cacheAttrib
3529 )
3530 {
3531 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3532 pMemDesc->_gpuP2PCacheAttrib = cacheAttrib;
3533 }
3534
3535 /*!
3536 * @brief Set CPU cacheability
3537 *
3538 * A later memdescAlloc() will use this setting.
3539 *
3540 * @param[in] pMemDesc Memory descriptor to update
3541 * @param[in] cacheAttrib Set memory to CPU cacheable
3542 *
3543 * @returns nothing
3544 */
memdescSetCpuCacheAttrib(MEMORY_DESCRIPTOR * pMemDesc,NvU32 cpuCacheAttrib)3545 void memdescSetCpuCacheAttrib
3546 (
3547 MEMORY_DESCRIPTOR *pMemDesc,
3548 NvU32 cpuCacheAttrib
3549 )
3550 {
3551 //
3552 // When running 64-bit MODS on ARM v8, we need to force all CPU mappings as WC.
3553 // This seems to be an issue with glibc. See bug 1556221.
3554 //
3555 // Ideally, this should have been set based on a Core Logic (CL) property.
3556 // But chipset initialization will only happen during bifStateInit().
3557 // RM can makes sysmem CPU mappings before bifStateInit().
3558 //
3559 if (RMCFG_FEATURE_PLATFORM_MODS && NVCPU_IS_AARCH64)
3560 {
3561 if (cpuCacheAttrib == NV_MEMORY_UNCACHED)
3562 {
3563 cpuCacheAttrib = NV_MEMORY_WRITECOMBINED;
3564 }
3565 }
3566
3567 pMemDesc->_cpuCacheAttrib = cpuCacheAttrib;
3568 }
3569
3570 /*!
3571 * @brief Print contents of a MEMORY_DESCRIPTOR in a human readable format.
3572 *
3573 * @param[in] pMemDesc Memory Descriptor to print
3574 * @param[in] bPrintIndividualPages Individual pages will also be printed
3575 * iff they are discontiguous
3576 * @param[in] pPrefixMessage Message that will be printed before the contents
3577 * of the Memory Descriptor are printed.
3578 *
3579 * @returns nothing
3580 */
memdescPrintMemdesc(MEMORY_DESCRIPTOR * pMemDesc,NvBool bPrintIndividualPages,const char * pPrefixMessage)3581 void memdescPrintMemdesc
3582 (
3583 MEMORY_DESCRIPTOR *pMemDesc,
3584 NvBool bPrintIndividualPages,
3585 const char *pPrefixMessage
3586 )
3587 {
3588 #if 0
3589 NvU32 i;
3590
3591 if ((DBG_RMMSG_CHECK(DBG_LEVEL_INFO) == 0) || (pPrefixMessage == NULL) || (pMemDesc == NULL))
3592 {
3593 return;
3594 }
3595
3596 NV_PRINTF(LEVEL_INFO,
3597 "%s Aperture %s starting at 0x%llx and of size 0x%llx\n",
3598 pPrefixMessage,
3599 memdescGetApertureString(pMemDesc->_addressSpace),
3600 memdescGetPhysAddr(pMemDesc, AT_CPU, 0),
3601 pMemDesc->Size);
3602
3603 if ((bPrintIndividualPages == NV_TRUE) &&
3604 (pMemDesc->PageCount > 1) &&
3605 (!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS)))
3606 {
3607 for (i = 0; i < pMemDesc->PageCount; i++)
3608 {
3609 NV_PRINTF(LEVEL_INFO,
3610 " contains page starting @0x%llx\n",
3611 pMemDesc->_pteArray[i]);
3612 }
3613 }
3614
3615 // TODO: merge with SMMU path above (see bug 1625121).
3616 if (pMemDesc->_pIommuMappings != NULL)
3617 {
3618 if (!memdescIsSubMemoryMemDesc(pMemDesc))
3619 {
3620 PIOVAMAPPING pIovaMap = pMemDesc->_pIommuMappings;
3621 while (pIovaMap != NULL)
3622 {
3623 NV_PRINTF(LEVEL_INFO,
3624 "Has additional IOMMU mapping for IOVA space 0x%x starting @ 0x%llx\n",
3625 pIovaMap->iovaspaceId,
3626 pIovaMap->iovaArray[0]);
3627 pIovaMap = pIovaMap->pNext;
3628 }
3629 }
3630 else
3631 {
3632 NV_PRINTF(LEVEL_INFO,
3633 "Has additional IOMMU mapping starting @ 0x%llx\n",
3634 memdescGetPhysAddr(pMemDesc, AT_PA, 0));
3635 }
3636 }
3637 #endif // NV_PRINTF_ENABLED
3638 }
3639
3640 /*!
3641 * @brief Return page offset from a MEMORY_DESCRIPTOR for an arbitrary power of two page size
3642 *
3643 * PageAdjust covers the 4KB alignment, but must include bits from the address for big pages.
3644 *
3645 * @param[in] pMemDesc Memory Descriptor to print
3646 * @param[in] pageSize Page size (4096, 64K, 128K, etc)
3647 *
3648 * @returns nothing
3649 */
memdescGetPageOffset(MEMORY_DESCRIPTOR * pMemDesc,NvU64 pageSize)3650 NvU64 memdescGetPageOffset
3651 (
3652 MEMORY_DESCRIPTOR *pMemDesc,
3653 NvU64 pageSize
3654 )
3655 {
3656 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3657 return (pMemDesc->PteAdjust + pMemDesc->_pteArray[0]) & (pageSize-1);
3658 }
3659
3660 /*!
3661 * @brief Get PTE kind using GPU
3662 *
3663 * @param[in] pMemDesc Memory descriptor pointer
3664 * @param[in] pGpu GPU to be used get supported kind
3665 * @param[in] addressTranslation Address translation identifier
3666 *
3667 * @returns Current PTE kind value.
3668 */
memdescGetPteKindForGpu(PMEMORY_DESCRIPTOR pMemDesc,OBJGPU * pGpu)3669 NvU32 memdescGetPteKindForGpu
3670 (
3671 PMEMORY_DESCRIPTOR pMemDesc,
3672 OBJGPU *pGpu
3673 )
3674 {
3675 return memmgrGetHwPteKindFromSwPteKind_HAL(pGpu, GPU_GET_MEMORY_MANAGER(pGpu), pMemDesc->_pteKind);
3676 }
3677
3678 /*!
3679 * @brief Set PTE kind using GPU.
3680 *
3681 * @param[in] pMemDesc Memory descriptor pointer
3682 * @param[in] pGpu GPU to be used set supported kind
3683 * @param[in] addressTranslation Address translation identifier
3684 * @param[in] pteKind New PTE kind
3685 *
3686 * @returns nothing
3687 */
memdescSetPteKindForGpu(PMEMORY_DESCRIPTOR pMemDesc,OBJGPU * pGpu,NvU32 pteKind)3688 void memdescSetPteKindForGpu
3689 (
3690 PMEMORY_DESCRIPTOR pMemDesc,
3691 OBJGPU *pGpu,
3692 NvU32 pteKind
3693 )
3694 {
3695 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3696 pMemDesc->_pteKind = memmgrGetSwPteKindFromHwPteKind_HAL(pGpu, GPU_GET_MEMORY_MANAGER(pGpu), pteKind);
3697 memdescSetFlag(pMemDesc, MEMDESC_FLAGS_SET_KIND, NV_TRUE);
3698 }
3699
3700 /*!
3701 * @brief Set PTE kind compressed value.
3702 *
3703 * @param[in] pMemDesc Memory descriptor pointer
3704 * @param[in] pteKind New PTE kind compressed value
3705 *
3706 * @returns nothing
3707 */
memdescSetPteKindCompressed(PMEMORY_DESCRIPTOR pMemDesc,NvU32 pteKindCmpr)3708 void memdescSetPteKindCompressed
3709 (
3710 PMEMORY_DESCRIPTOR pMemDesc,
3711 NvU32 pteKindCmpr
3712 )
3713 {
3714 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3715 pMemDesc->_pteKindCompressed = pteKindCmpr;
3716 }
3717
3718 /*!
3719 * @brief Get PTE kind compressed value.
3720 *
3721 * @param[in] pMemDesc Memory descriptor pointer
3722 * @param[in] addressTranslation Address translation identifier
3723 *
3724 * @returns Current PTE kind compressed value.
3725 */
memdescGetPteKindCompressed(PMEMORY_DESCRIPTOR pMemDesc)3726 NvU32 memdescGetPteKindCompressed
3727 (
3728 PMEMORY_DESCRIPTOR pMemDesc
3729 )
3730 {
3731 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3732 return pMemDesc->_pteKindCompressed;
3733 }
3734
3735 /*!
3736 * @brief Get kernel mapping
3737 *
3738 * @param[in] pMemDesc Memory descriptor pointer
3739 *
3740 * @returns Current kernel mapping
3741 */
memdescGetKernelMapping(MEMORY_DESCRIPTOR * pMemDesc)3742 NvP64 memdescGetKernelMapping
3743 (
3744 MEMORY_DESCRIPTOR *pMemDesc
3745 )
3746 {
3747 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3748 return pMemDesc->_kernelMapping;
3749 }
3750
3751 /*!
3752 * @brief Set kernel mapping
3753 *
3754 * @param[in] pMemDesc Memory descriptor pointer
3755 * @param[in] kernelMapping New kernel mapping
3756 *
3757 * @returns nothing
3758 */
memdescSetKernelMapping(MEMORY_DESCRIPTOR * pMemDesc,NvP64 kernelMapping)3759 void memdescSetKernelMapping
3760 (
3761 MEMORY_DESCRIPTOR *pMemDesc,
3762 NvP64 kernelMapping
3763 )
3764 {
3765 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3766 pMemDesc->_kernelMapping = kernelMapping;
3767 }
3768
3769 /*!
3770 * @brief Get privileged kernel mapping
3771 *
3772 * @param[in] pMemDesc Memory descriptor pointer
3773 *
3774 * @returns Current privileged kernel mapping
3775 */
memdescGetKernelMappingPriv(MEMORY_DESCRIPTOR * pMemDesc)3776 NvP64 memdescGetKernelMappingPriv
3777 (
3778 MEMORY_DESCRIPTOR *pMemDesc
3779 )
3780 {
3781 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3782 return pMemDesc->_kernelMappingPriv;
3783 }
3784
3785 /*!
3786 * @brief Set HW resource identifier (HwResId)
3787 *
3788 * @param[in] pMemDesc Memory descriptor pointer
3789 * @param[in] kernelMappingPriv New privileged kernel mapping
3790 *
3791 * @returns nothing
3792 */
memdescSetKernelMappingPriv(MEMORY_DESCRIPTOR * pMemDesc,NvP64 kernelMappingPriv)3793 void memdescSetKernelMappingPriv
3794 (
3795 MEMORY_DESCRIPTOR *pMemDesc,
3796 NvP64 kernelMappingPriv
3797 )
3798 {
3799 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3800 pMemDesc->_kernelMappingPriv = kernelMappingPriv;
3801 }
3802
3803
3804 /*!
3805 * @brief Set standby buffer memory descriptor
3806 *
3807 * @param[in] pMemDesc Memory descriptor pointer
3808 *
3809 * @returns Pointer to standby buffer memory descriptor
3810 */
memdescGetStandbyBuffer(MEMORY_DESCRIPTOR * pMemDesc)3811 MEMORY_DESCRIPTOR *memdescGetStandbyBuffer
3812 (
3813 MEMORY_DESCRIPTOR *pMemDesc
3814 )
3815 {
3816 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3817 return pMemDesc->_pStandbyBuffer;
3818 }
3819
3820 /*!
3821 * @brief Set standby buffer memory descriptor
3822 *
3823 * @param[in] pMemDesc Memory descriptor pointer
3824 * @param[in] pStandbyBuffer Standby buffer memory descriptor pointer
3825 *
3826 * @returns nothing
3827 */
memdescSetStandbyBuffer(MEMORY_DESCRIPTOR * pMemDesc,MEMORY_DESCRIPTOR * pStandbyBuffer)3828 void memdescSetStandbyBuffer
3829 (
3830 MEMORY_DESCRIPTOR *pMemDesc,
3831 MEMORY_DESCRIPTOR *pStandbyBuffer
3832 )
3833 {
3834 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3835 pMemDesc->_pStandbyBuffer = pStandbyBuffer;
3836 }
3837
3838 /*!
3839 * @brief Set mem destroy callback list pointer
3840 *
3841 * @param[in] pMemDesc Memory descriptor pointer
3842 * @param[in] pMemDestroyCallbackList Memory destroy callback list pointer
3843 *
3844 * @returns nothing
3845 */
memdescSetDestroyCallbackList(MEMORY_DESCRIPTOR * pMemDesc,MEM_DESC_DESTROY_CALLBACK * pCb)3846 void memdescSetDestroyCallbackList
3847 (
3848 MEMORY_DESCRIPTOR *pMemDesc,
3849 MEM_DESC_DESTROY_CALLBACK *pCb
3850 )
3851 {
3852 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3853 pMemDesc->_pMemDestroyCallbackList = pCb;
3854 }
3855
3856 /*!
3857 * @brief Get guest ID for specified memory descriptor
3858 *
3859 * @param[in] pMemDesc Memory descriptor pointer
3860 *
3861 * @returns Guest ID value
3862 */
memdescGetGuestId(MEMORY_DESCRIPTOR * pMemDesc)3863 NvU64 memdescGetGuestId
3864 (
3865 MEMORY_DESCRIPTOR *pMemDesc
3866 )
3867 {
3868 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3869 return pMemDesc->_guestId;
3870 }
3871
3872 /*!
3873 * @brief Set guest ID for memory descriptor
3874 *
3875 * @param[in] pMemDesc Memory descriptor pointer
3876 * @param[in] guestId New guest ID
3877 *
3878 * @returns nothing
3879 */
memdescSetGuestId(MEMORY_DESCRIPTOR * pMemDesc,NvU64 guestId)3880 void memdescSetGuestId
3881 (
3882 MEMORY_DESCRIPTOR *pMemDesc,
3883 NvU64 guestId
3884 )
3885 {
3886 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3887 pMemDesc->_guestId = guestId;
3888 }
3889
3890 /*!
3891 * @brief Get value of specified flag
3892 *
3893 * @param[in] pMemDesc Memory descriptor pointer
3894 * @param[in] flag MEMDESC_FLAGS_* value
3895 *
3896 * @returns Boolean value of specified flag
3897 */
memdescGetFlag(MEMORY_DESCRIPTOR * pMemDesc,NvU64 flag)3898 NvBool memdescGetFlag
3899 (
3900 MEMORY_DESCRIPTOR *pMemDesc,
3901 NvU64 flag
3902 )
3903 {
3904 // For checking contiguity, use the memdescGetContiguity() api
3905 NV_ASSERT(flag != MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS);
3906 // GPU_IN_RESET is set/got from top level memdesc always.
3907 if (flag != MEMDESC_FLAGS_GPU_IN_RESET)
3908 {
3909 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3910 }
3911 return !!(pMemDesc->_flags & flag);
3912 }
3913
3914 /*!
3915 * @brief Set value of specified flag
3916 *
3917 * @param[in] pMemDesc Memory descriptor pointer
3918 * @param[in] flag MEMDESC_FLAGS_* value
3919 * @param[in] bValue Boolean value of flag
3920 *
3921 * @returns nothing
3922 */
memdescSetFlag(MEMORY_DESCRIPTOR * pMemDesc,NvU64 flag,NvBool bValue)3923 void memdescSetFlag
3924 (
3925 MEMORY_DESCRIPTOR *pMemDesc,
3926 NvU64 flag,
3927 NvBool bValue
3928 )
3929 {
3930 // For setting contiguity, use the memdescSetContiguity() api
3931 NV_ASSERT(flag != MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS);
3932
3933 // GPU_IN_RESET is set/got from top level memdesc always.
3934 if (flag != MEMDESC_FLAGS_GPU_IN_RESET)
3935 {
3936 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3937 }
3938
3939 if (flag == MEMDESC_FLAGS_OWNED_BY_CURRENT_DEVICE)
3940 {
3941 NV_ASSERT_OK(_memdescSetSubAllocatorFlag(pMemDesc->pGpu, pMemDesc, bValue));
3942 return;
3943 }
3944 else if (flag == MEMDESC_FLAGS_GUEST_ALLOCATED)
3945 {
3946 NV_ASSERT_OK(_memdescSetGuestAllocatedFlag(pMemDesc->pGpu, pMemDesc, bValue));
3947 return;
3948 }
3949
3950 if (bValue)
3951 pMemDesc->_flags |= flag;
3952 else
3953 pMemDesc->_flags &= ~flag;
3954 }
3955
3956 /*!
3957 * @brief Return memory descriptor address pointer
3958 *
3959 * The address value is returned by osAllocPages
3960 *
3961 * @param[in] pMemDesc Memory descriptor pointer
3962 *
3963 * @returns Memory descriptor address pointer
3964 */
memdescGetAddress(MEMORY_DESCRIPTOR * pMemDesc)3965 NvP64 memdescGetAddress
3966 (
3967 MEMORY_DESCRIPTOR *pMemDesc
3968 )
3969 {
3970 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3971 return pMemDesc->_address;
3972 }
3973
3974 /*!
3975 * @brief Set memory descriptor address pointer
3976 *
3977 * The address value is returned by osAllocPages
3978 *
3979 * @param[in] pMemDesc Memory descriptor pointer
3980 * @param[in] pAddress Pointer to address information
3981 *
3982 * @returns nothing
3983 */
memdescSetAddress(MEMORY_DESCRIPTOR * pMemDesc,NvP64 pAddress)3984 void memdescSetAddress
3985 (
3986 MEMORY_DESCRIPTOR *pMemDesc,
3987 NvP64 pAddress
3988 )
3989 {
3990 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
3991 pMemDesc->_address = pAddress;
3992 }
3993
3994 /*!
3995 * @brief Get memory descriptor os-specific memory data pointer
3996 *
3997 * The pMemData value is returned by osAllocPages
3998 *
3999 * @param[in] pMemDesc Memory descriptor pointer
4000 *
4001 * @returns Memory data pointer
4002 */
memdescGetMemData(MEMORY_DESCRIPTOR * pMemDesc)4003 void *memdescGetMemData
4004 (
4005 MEMORY_DESCRIPTOR *pMemDesc
4006 )
4007 {
4008 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
4009 return pMemDesc->_pMemData;
4010 }
4011
4012 /*!
4013 * @brief Set memory descriptor os-specific memory data pointer
4014 *
4015 * The pMemData value is returned by osAllocPages
4016 *
4017 * @param[in] pMemDesc Memory descriptor pointer
4018 * @param[in] pMemData Pointer to new os-specific memory data
4019 * @param[in] pMemDataReleaseCallback Pointer to CB to be called when memdesc
4020 * is freed.
4021 *
4022 * @returns nothing
4023 */
memdescSetMemData(MEMORY_DESCRIPTOR * pMemDesc,void * pMemData,MEM_DATA_RELEASE_CALL_BACK * pMemDataReleaseCallback)4024 void memdescSetMemData
4025 (
4026 MEMORY_DESCRIPTOR *pMemDesc,
4027 void *pMemData,
4028 MEM_DATA_RELEASE_CALL_BACK *pMemDataReleaseCallback
4029 )
4030 {
4031 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
4032 pMemDesc->_pMemData = pMemData;
4033 pMemDesc->_pMemDataReleaseCallback = pMemDataReleaseCallback;
4034 }
4035
4036 /*!
4037 * @brief Return memory descriptor volatile attribute
4038 *
4039 * @param[in] pMemDesc Memory descriptor pointer
4040 *
4041 * @returns Volatile or not
4042 */
memdescGetVolatility(PMEMORY_DESCRIPTOR pMemDesc)4043 NvBool memdescGetVolatility
4044 (
4045 PMEMORY_DESCRIPTOR pMemDesc
4046 )
4047 {
4048 NvBool bVolatile = NV_FALSE;
4049
4050 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
4051 if (pMemDesc->_addressSpace == ADDR_SYSMEM)
4052 {
4053 bVolatile = (memdescGetGpuCacheAttrib(pMemDesc) == NV_MEMORY_UNCACHED);
4054 }
4055 else
4056 {
4057 NV_ASSERT(pMemDesc->_addressSpace == ADDR_FBMEM);
4058 }
4059
4060 return bVolatile;
4061 }
4062
4063 /*!
4064 * @brief Quick check whether the memory is contiguous or not
4065 *
4066 * @param[in] pMemDesc Memory descriptor used
4067 * @param[in] addressTranslation Address translation identifier
4068 *
4069 * @returns NV_TRUE if contiguous
4070 */
memdescGetContiguity(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation)4071 NvBool memdescGetContiguity(PMEMORY_DESCRIPTOR pMemDesc, ADDRESS_TRANSLATION addressTranslation)
4072 {
4073 return !!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS);
4074 }
4075
4076 /*!
4077 * @brief Detailed Check whether the memory is contiguous or not
4078 *
4079 * @param[in] pMemDesc Memory descriptor used
4080 * @param[in] addressTranslation Address translation identifier
4081 *
4082 * @returns NV_TRUE if contiguous
4083 */
memdescCheckContiguity(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation)4084 NvBool memdescCheckContiguity(PMEMORY_DESCRIPTOR pMemDesc, ADDRESS_TRANSLATION addressTranslation)
4085 {
4086 NvU32 i;
4087
4088 if (!(pMemDesc->_flags & MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS))
4089 {
4090 for (i = 0; i < (pMemDesc->PageCount - 1); i++)
4091 {
4092 if ((memdescGetPte(pMemDesc, addressTranslation, i) + pMemDesc->pageArrayGranularity) !=
4093 memdescGetPte(pMemDesc, addressTranslation, i + 1))
4094 return NV_FALSE;
4095 }
4096 }
4097
4098 return NV_TRUE;
4099 }
4100
4101 /*!
4102 * @brief Set the contiguity of the memory descriptor
4103 *
4104 * @param[in] pMemDesc Memory descriptor used
4105 * @param[in] addressTranslation Address translation identifier
4106 * @param[in] isContiguous Contiguity value
4107 *
4108 * @returns nothing
4109 */
memdescSetContiguity(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvBool isContiguous)4110 void memdescSetContiguity(PMEMORY_DESCRIPTOR pMemDesc, ADDRESS_TRANSLATION addressTranslation, NvBool isContiguous)
4111 {
4112 NV_ASSERT_OR_RETURN_VOID(pMemDesc);
4113
4114 if (isContiguous)
4115 pMemDesc->_flags |= MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS;
4116 else
4117 pMemDesc->_flags &= ~MEMDESC_FLAGS_PHYSICALLY_CONTIGUOUS;
4118 }
4119
4120 /*!
4121 * @brief Get the address space of the memory descriptor
4122 *
4123 * @param[in] pMemDesc Memory descriptor used
4124 * @param[in] addressTranslation Address translation identifier
4125 *
4126 * @returns addresspace
4127 */
memdescGetAddressSpace(PMEMORY_DESCRIPTOR pMemDesc)4128 NV_ADDRESS_SPACE memdescGetAddressSpace(PMEMORY_DESCRIPTOR pMemDesc)
4129 {
4130 NV_ASSERT_OR_RETURN(pMemDesc != NULL, 0);
4131 return pMemDesc->_addressSpace;
4132 }
4133
4134 /*!
4135 * @brief Get page size
4136 *
4137 * @param[in] pMemDesc Memory descriptor pointer
4138 * @param[in] addressTranslation Address translation identifier
4139 *
4140 * @returns Current page size.
4141 */
memdescGetPageSize(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation)4142 NvU64 memdescGetPageSize
4143 (
4144 PMEMORY_DESCRIPTOR pMemDesc,
4145 ADDRESS_TRANSLATION addressTranslation
4146 )
4147 {
4148 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
4149 return pMemDesc->_pageSize;
4150 }
4151
4152 /*!
4153 * @brief Set page size
4154 *
4155 * @param[in] pMemDesc Memory descriptor pointer
4156 * @param[in] addressTranslation Address translation identifier
4157 * @param[in] pteKind New PTE kind
4158 *
4159 * @returns nothing
4160 */
memdescSetPageSize(PMEMORY_DESCRIPTOR pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU64 pageSize)4161 void memdescSetPageSize
4162 (
4163 PMEMORY_DESCRIPTOR pMemDesc,
4164 ADDRESS_TRANSLATION addressTranslation,
4165 NvU64 pageSize
4166 )
4167 {
4168 NV_ASSERT(!memdescHasSubDeviceMemDescs(pMemDesc));
4169 pMemDesc->_pageSize = pageSize;
4170 }
4171
4172 /*!
4173 * @brief Get the Root memory descriptor.
4174 *
4175 * This can also be used to get the root offset as well.
4176 *
4177 * Root memory descriptor is the top level memory descriptor with no parent,
4178 * from which this memory descriptor was derived
4179 *
4180 * @param[in] pMemDesc Pointer to memory descriptor.
4181 * @param[out] pRootOffset Pointer to the root offset parameter.
4182 *
4183 * @returns the Root memory descriptor.
4184 */
memdescGetRootMemDesc(PMEMORY_DESCRIPTOR pMemDesc,NvU64 * pRootOffset)4185 PMEMORY_DESCRIPTOR memdescGetRootMemDesc
4186 (
4187 PMEMORY_DESCRIPTOR pMemDesc,
4188 NvU64 *pRootOffset
4189 )
4190 {
4191 NvU64 offset = 0;
4192
4193 // Find the top-level parent descriptor
4194 while (pMemDesc->_pParentDescriptor)
4195 {
4196 // Sanity check, None of the child descriptors should be allocated
4197 NV_ASSERT(!pMemDesc->Allocated);
4198 offset += pMemDesc->subMemOffset;
4199 pMemDesc = pMemDesc->_pParentDescriptor;
4200 }
4201
4202 if (pRootOffset)
4203 {
4204 *pRootOffset = offset;
4205 }
4206
4207 return pMemDesc;
4208 }
4209 /*!
4210 * @brief Sets the CUSTOM_HEAP flag of MEMDESC.
4211 *
4212 * Since we have ACR region, Memory descriptor can be allocated in ACR region
4213 * in that case, we need to set this flag since we are using the custom ACR HEAP
4214 *
4215 * @param[in] pMemDesc Pointer to memory descriptor.
4216 *
4217 * @returns void.
4218 */
4219 void
memdescSetCustomHeap(PMEMORY_DESCRIPTOR pMemDesc,MEMDESC_CUSTOM_HEAP heap)4220 memdescSetCustomHeap
4221 (
4222 PMEMORY_DESCRIPTOR pMemDesc,
4223 MEMDESC_CUSTOM_HEAP heap
4224 )
4225 {
4226 NV_ASSERT(0);
4227 }
4228
4229 /*!
4230 * @brief Returns the ACR CUSTOM_HEAP flag.
4231 *
4232 *
4233 * @param[in] pMemDesc Pointer to memory descriptor.
4234 *
4235 * @returns NV_TRUE if flag MEMDESC_FLAGS_CUSTOM_HEAP_ACR is SET.
4236 */
4237 MEMDESC_CUSTOM_HEAP
memdescGetCustomHeap(PMEMORY_DESCRIPTOR pMemDesc)4238 memdescGetCustomHeap
4239 (
4240 PMEMORY_DESCRIPTOR pMemDesc
4241 )
4242 {
4243
4244 return MEMDESC_CUSTOM_HEAP_NONE;
4245 }
4246
memdescGetIommuMap(PMEMORY_DESCRIPTOR pMemDesc,NvU32 iovaspaceId)4247 PIOVAMAPPING memdescGetIommuMap
4248 (
4249 PMEMORY_DESCRIPTOR pMemDesc,
4250 NvU32 iovaspaceId
4251 )
4252 {
4253 PIOVAMAPPING pIommuMap = pMemDesc->_pIommuMappings;
4254 while (pIommuMap != NULL)
4255 {
4256 if (pIommuMap->iovaspaceId == iovaspaceId)
4257 {
4258 break;
4259 }
4260
4261 pIommuMap = pIommuMap->pNext;
4262 }
4263
4264 return pIommuMap;
4265 }
4266
memdescAddIommuMap(PMEMORY_DESCRIPTOR pMemDesc,PIOVAMAPPING pIommuMap)4267 NV_STATUS memdescAddIommuMap
4268 (
4269 PMEMORY_DESCRIPTOR pMemDesc,
4270 PIOVAMAPPING pIommuMap
4271 )
4272 {
4273 NV_ASSERT_OR_RETURN((pMemDesc->_pIommuMappings == NULL) ||
4274 (!memdescIsSubMemoryMemDesc(pMemDesc)), NV_ERR_INVALID_ARGUMENT);
4275
4276 //
4277 // Only root physical memdescs can have multiple IOMMU mappings.
4278 // Submemdescs can only have one, and the list linkage is used
4279 // instead to link it as a child of the root IOMMU mapping, so we
4280 // don't want to overwrite that here.
4281 //
4282 if (!memdescIsSubMemoryMemDesc(pMemDesc))
4283 {
4284 pIommuMap->pNext = pMemDesc->_pIommuMappings;
4285 }
4286
4287 pMemDesc->_pIommuMappings = pIommuMap;
4288
4289 return NV_OK;
4290 }
4291
memdescRemoveIommuMap(PMEMORY_DESCRIPTOR pMemDesc,PIOVAMAPPING pIommuMap)4292 void memdescRemoveIommuMap
4293 (
4294 PMEMORY_DESCRIPTOR pMemDesc,
4295 PIOVAMAPPING pIommuMap
4296 )
4297 {
4298 //
4299 // Only root physical memdescs can have multiple IOMMU mappings.
4300 // Submemdescs can only have one, and the list linkage is used
4301 // instead to link it as a child of the root IOMMU mapping, so we
4302 // don't want to overwrite that here.
4303 //
4304 if (!memdescIsSubMemoryMemDesc(pMemDesc))
4305 {
4306 PIOVAMAPPING *ppTmpIommuMap = &pMemDesc->_pIommuMappings;
4307 while ((*ppTmpIommuMap != NULL) && (*ppTmpIommuMap != pIommuMap))
4308 {
4309 ppTmpIommuMap = &(*ppTmpIommuMap)->pNext;
4310 }
4311
4312 if (*ppTmpIommuMap != NULL)
4313 {
4314 *ppTmpIommuMap = pIommuMap->pNext;
4315
4316 }
4317 else
4318 {
4319 NV_ASSERT(*ppTmpIommuMap != NULL);
4320 }
4321 }
4322 else if (pMemDesc->_pIommuMappings == pIommuMap)
4323 {
4324 pMemDesc->_pIommuMappings = NULL;
4325 }
4326 else
4327 {
4328 //
4329 // Trying to remove a submemory mapping that doesn't belong to this
4330 // descriptor?
4331 //
4332 NV_ASSERT(pMemDesc->_pIommuMappings == pIommuMap);
4333 }
4334 }
4335
memdescMapIommu(PMEMORY_DESCRIPTOR pMemDesc,NvU32 iovaspaceId)4336 NV_STATUS memdescMapIommu
4337 (
4338 PMEMORY_DESCRIPTOR pMemDesc,
4339 NvU32 iovaspaceId
4340 )
4341 {
4342 #if (RMCFG_FEATURE_PLATFORM_UNIX || RMCFG_FEATURE_PLATFORM_MODS) && !NVCPU_IS_ARM
4343 if (iovaspaceId != NV_IOVA_DOMAIN_NONE)
4344 {
4345 NV_ADDRESS_SPACE addrSpace = memdescGetAddressSpace(pMemDesc);
4346 OBJGPU *pMappingGpu = gpumgrGetGpuFromId(iovaspaceId);
4347 PMEMORY_DESCRIPTOR pRootMemDesc = memdescGetRootMemDesc(pMemDesc, NULL);
4348 if ((addrSpace == ADDR_SYSMEM) || gpumgrCheckIndirectPeer(pMappingGpu, pRootMemDesc->pGpu))
4349 {
4350 NV_STATUS status;
4351 OBJIOVASPACE *pIOVAS = iovaspaceFromId(iovaspaceId);
4352 NV_ASSERT_OR_RETURN(pIOVAS, NV_ERR_OBJECT_NOT_FOUND);
4353
4354 status = iovaspaceAcquireMapping(pIOVAS, pMemDesc);
4355 NV_ASSERT_OR_RETURN(status == NV_OK, status);
4356 }
4357 }
4358 #endif
4359
4360 //
4361 // Verify that the final physical addresses are indeed addressable by the
4362 // GPU. We only need to do this for internally allocated sysmem (RM owned)
4363 // as well as externally allocated/mapped sysmem. Note, addresses for peer
4364 // (P2P mailbox registers) BARs are actually not handled by the GMMU and
4365 // support a full 64-bit address width, hence validation is not needed.
4366 //
4367 if ((pMemDesc->Allocated ||
4368 memdescGetFlag(pMemDesc, MEMDESC_FLAGS_EXT_PAGE_ARRAY_MEM) ||
4369 memdescGetFlag(pMemDesc, MEMDESC_FLAGS_PEER_IO_MEM)) &&
4370 memdescGetAddressSpace(pMemDesc) == ADDR_SYSMEM)
4371 {
4372 // TODO This should look up the GPU corresponding to the IOVAS instead.
4373 OBJGPU *pGpu = pMemDesc->pGpu;
4374 RmPhysAddr dmaWindowStartAddr = gpuGetDmaStartAddress(pGpu);
4375 RmPhysAddr dmaWindowEndAddr = gpuGetDmaEndAddress_HAL(pGpu);
4376 RmPhysAddr physAddr;
4377
4378 if (memdescGetContiguity(pMemDesc, AT_GPU))
4379 {
4380 physAddr = memdescGetPhysAddr(pMemDesc, AT_GPU, 0);
4381 if ((physAddr < dmaWindowStartAddr) ||
4382 (physAddr + pMemDesc->Size - 1 > dmaWindowEndAddr))
4383 {
4384 NV_PRINTF(LEVEL_ERROR,
4385 "0x%llx-0x%llx is not addressable by GPU 0x%x [0x%llx-0x%llx]\n",
4386 physAddr, physAddr + pMemDesc->Size - 1,
4387 pGpu->gpuId, dmaWindowStartAddr, dmaWindowEndAddr);
4388 memdescUnmapIommu(pMemDesc, iovaspaceId);
4389 return NV_ERR_INVALID_ADDRESS;
4390 }
4391 }
4392 else
4393 {
4394 NvU32 i;
4395 for (i = 0; i < pMemDesc->PageCount; i++)
4396 {
4397 physAddr = memdescGetPte(pMemDesc, AT_GPU, i);
4398 if ((physAddr < dmaWindowStartAddr) ||
4399 (physAddr + (pMemDesc->pageArrayGranularity - 1) > dmaWindowEndAddr))
4400 {
4401 NV_PRINTF(LEVEL_ERROR,
4402 "0x%llx is not addressable by GPU 0x%x [0x%llx-0x%llx]\n",
4403 physAddr, pGpu->gpuId, dmaWindowStartAddr,
4404 dmaWindowEndAddr);
4405 memdescUnmapIommu(pMemDesc, iovaspaceId);
4406 return NV_ERR_INVALID_ADDRESS;
4407 }
4408 }
4409 }
4410 }
4411
4412 return NV_OK;
4413 }
4414
memdescUnmapIommu(PMEMORY_DESCRIPTOR pMemDesc,NvU32 iovaspaceId)4415 void memdescUnmapIommu
4416 (
4417 PMEMORY_DESCRIPTOR pMemDesc,
4418 NvU32 iovaspaceId
4419 )
4420 {
4421 #if (RMCFG_FEATURE_PLATFORM_UNIX || RMCFG_FEATURE_PLATFORM_MODS) && !NVCPU_IS_ARM
4422 PIOVAMAPPING pIovaMapping;
4423 OBJIOVASPACE *pIOVAS;
4424
4425 if (iovaspaceId == NV_IOVA_DOMAIN_NONE)
4426 return;
4427
4428 pIovaMapping = memdescGetIommuMap(pMemDesc, iovaspaceId);
4429 NV_ASSERT(pIovaMapping);
4430
4431 pIOVAS = iovaspaceFromMapping(pIovaMapping);
4432 iovaspaceReleaseMapping(pIOVAS, pIovaMapping);
4433 #endif
4434 }
4435
memdescCheckSubDevicePageSizeConsistency(OBJGPU * pGpu,PMEMORY_DESCRIPTOR pMemDesc,OBJVASPACE * pVAS,NvU64 pageSize,NvU64 pageOffset)4436 void memdescCheckSubDevicePageSizeConsistency
4437 (
4438 OBJGPU *pGpu,
4439 PMEMORY_DESCRIPTOR pMemDesc,
4440 OBJVASPACE *pVAS,
4441 NvU64 pageSize,
4442 NvU64 pageOffset
4443 )
4444 {
4445 NvU64 tempPageSize, tempPageOffset;
4446 PMEMORY_DESCRIPTOR pTempMemDesc = NULL;
4447
4448 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
4449 pTempMemDesc = memdescGetMemDescFromGpu(pMemDesc, pGpu);
4450 tempPageSize = memdescGetPageSize(pTempMemDesc, VAS_ADDRESS_TRANSLATION(pVAS));
4451 tempPageOffset = memdescGetPhysAddr(pTempMemDesc, VAS_ADDRESS_TRANSLATION(pVAS), 0) & (tempPageSize - 1);
4452
4453 // Assert if inconsistent
4454 NV_ASSERT(pageSize == tempPageSize);
4455 NV_ASSERT(pageOffset == tempPageOffset);
4456 SLI_LOOP_END
4457 }
4458
memdescCheckSubDeviceMemContiguityConsistency(OBJGPU * pGpu,PMEMORY_DESCRIPTOR pMemDesc,OBJVASPACE * pVAS,NvBool bIsMemContiguous)4459 void memdescCheckSubDeviceMemContiguityConsistency
4460 (
4461 OBJGPU *pGpu,
4462 PMEMORY_DESCRIPTOR pMemDesc,
4463 OBJVASPACE *pVAS,
4464 NvBool bIsMemContiguous
4465 )
4466 {
4467 NvBool bTempIsMemContiguous = NV_FALSE;
4468
4469 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
4470 bTempIsMemContiguous = memdescGetContiguity(memdescGetMemDescFromGpu(pMemDesc, pGpu), VAS_ADDRESS_TRANSLATION(pVAS));
4471 // Assert if inconsistent
4472 NV_ASSERT(bIsMemContiguous == bTempIsMemContiguous);
4473 SLI_LOOP_END
4474 }
4475
memdescCheckSubDeviceKindComprConsistency(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,OBJVASPACE * pVAS,NvU32 kind,COMPR_INFO * pComprInfo)4476 NV_STATUS memdescCheckSubDeviceKindComprConsistency
4477 (
4478 OBJGPU *pGpu,
4479 MEMORY_DESCRIPTOR *pMemDesc,
4480 OBJVASPACE *pVAS,
4481 NvU32 kind,
4482 COMPR_INFO *pComprInfo
4483 )
4484 {
4485 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
4486 {
4487 MemoryManager *MemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
4488 NvU32 tempKind;
4489 COMPR_INFO tempComprInfo = {0};
4490 NV_STATUS status;
4491
4492 status = memmgrGetKindComprFromMemDesc(MemoryManager,
4493 memdescGetMemDescFromGpu(pMemDesc, pGpu),
4494 0,
4495 &tempKind, &tempComprInfo);
4496
4497 if (NV_OK != status)
4498 SLI_LOOP_RETURN(status);
4499
4500 // Assert if inconsistent
4501 NV_ASSERT(kind == tempKind);
4502 NV_ASSERT(tempComprInfo.compPageShift == pComprInfo->compPageShift &&
4503 tempComprInfo.kind == pComprInfo->kind &&
4504 tempComprInfo.compPageIndexLo == pComprInfo->compPageIndexLo &&
4505 tempComprInfo.compPageIndexHi == pComprInfo->compPageIndexHi &&
4506 tempComprInfo.compTagLineMin == pComprInfo->compTagLineMin &&
4507 tempComprInfo.compTagLineMultiplier == pComprInfo->compTagLineMultiplier);
4508 }
4509 SLI_LOOP_END
4510
4511 return NV_OK;
4512 }
4513
4514 /* @brief Get GPA(guest physical addresses) for given GPU physical addresses.
4515 *
4516 * @param[in] pGpu GPU for which GPAs are needed
4517 * @param[in] pageCount Size of array. Should be 1 for contiguous mappings
4518 * @param[in/out] pGpa Array of GPU PAs to be converted to guest PAs
4519 *
4520 * @returns NV_STATUS
4521 */
memdescGetNvLinkGpa(OBJGPU * pGpu,NvU64 pageCount,RmPhysAddr * pGpa)4522 NV_STATUS memdescGetNvLinkGpa
4523 (
4524 OBJGPU *pGpu,
4525 NvU64 pageCount,
4526 RmPhysAddr *pGpa
4527 )
4528 {
4529 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu);
4530
4531 NV_ASSERT_OR_RETURN(pGpa, NV_ERR_INVALID_ARGUMENT);
4532
4533 NvU32 pageIndex;
4534 // For each page, do the GPU PA to GPA conversion
4535 for (pageIndex = 0; pageIndex < pageCount; pageIndex++)
4536 {
4537 RmPhysAddr gpa;
4538 gpa = pGpa[pageIndex] + pKernelMemorySystem->coherentCpuFbBase;
4539
4540 NV_ASSERT_OR_RETURN((gpa >= pKernelMemorySystem->coherentCpuFbBase) &&
4541 (gpa <= pKernelMemorySystem->coherentCpuFbEnd),
4542 NV_ERR_INVALID_ARGUMENT);
4543
4544 pGpa[pageIndex] = gpa;
4545 }
4546
4547 return NV_OK;
4548 }
4549
4550 NV_STATUS
memdescSetCtxBufPool(PMEMORY_DESCRIPTOR pMemDesc,CTX_BUF_POOL_INFO * pCtxBufPool)4551 memdescSetCtxBufPool
4552 (
4553 PMEMORY_DESCRIPTOR pMemDesc,
4554 CTX_BUF_POOL_INFO *pCtxBufPool
4555 )
4556 {
4557
4558 NV_ASSERT_OR_RETURN(!pMemDesc->Allocated, NV_ERR_INVALID_STATE);
4559 NV_ASSERT_OR_RETURN(!memdescHasSubDeviceMemDescs(pMemDesc), NV_ERR_INVALID_ARGUMENT);
4560
4561 pMemDesc->pCtxBufPool = pCtxBufPool;
4562 return NV_OK;
4563 }
4564
4565 CTX_BUF_POOL_INFO*
memdescGetCtxBufPool(PMEMORY_DESCRIPTOR pMemDesc)4566 memdescGetCtxBufPool
4567 (
4568 PMEMORY_DESCRIPTOR pMemDesc
4569 )
4570 {
4571 NV_ASSERT_OR_RETURN(!memdescHasSubDeviceMemDescs(pMemDesc), NULL);
4572 return pMemDesc->pCtxBufPool;
4573 }
4574
4575 /*!
4576 * @brief Override the registry INST_LOC two-bit enum to an aperture (list) + cpu attr.
4577 *
4578 * Caller must set initial default values.
4579 */
4580 void
memdescOverrideInstLocList(NvU32 instLoc,const char * name,const NV_ADDRESS_SPACE ** ppAllocList,NvU32 * pCpuMappingAttr)4581 memdescOverrideInstLocList
4582 (
4583 NvU32 instLoc, // NV_REG_STR_RM_INST_LOC
4584 const char *name,
4585 const NV_ADDRESS_SPACE **ppAllocList,
4586 NvU32 *pCpuMappingAttr
4587 )
4588 {
4589 switch (instLoc)
4590 {
4591 case NV_REG_STR_RM_INST_LOC_COH:
4592 NV_PRINTF(LEVEL_INFO, "using coh system memory for %s\n", name);
4593 *ppAllocList = ADDRLIST_SYSMEM_ONLY;
4594 *pCpuMappingAttr = NV_MEMORY_CACHED;
4595 break;
4596 case NV_REG_STR_RM_INST_LOC_NCOH:
4597 NV_PRINTF(LEVEL_INFO, "using ncoh system memory for %s\n", name);
4598 *ppAllocList = ADDRLIST_SYSMEM_ONLY;
4599 *pCpuMappingAttr = NV_MEMORY_UNCACHED;
4600 break;
4601 case NV_REG_STR_RM_INST_LOC_VID:
4602 NV_PRINTF(LEVEL_INFO, "using video memory for %s\n", name);
4603 *ppAllocList = ADDRLIST_FBMEM_ONLY;
4604 *pCpuMappingAttr = NV_MEMORY_WRITECOMBINED;
4605 break;
4606 case NV_REG_STR_RM_INST_LOC_DEFAULT:
4607 default:
4608 // Do not update parameters
4609 break;
4610 }
4611 }
4612
4613 /*!
4614 * @brief Override wrapper for callers needed an aperture
4615 */
4616 void
memdescOverrideInstLoc(NvU32 instLoc,const char * name,NV_ADDRESS_SPACE * pAddrSpace,NvU32 * pCpuMappingAttr)4617 memdescOverrideInstLoc
4618 (
4619 NvU32 instLoc,
4620 const char *name,
4621 NV_ADDRESS_SPACE *pAddrSpace,
4622 NvU32 *pCpuMappingAttr
4623 )
4624 {
4625 const NV_ADDRESS_SPACE *pAllocList = NULL;
4626
4627 memdescOverrideInstLocList(instLoc, name, &pAllocList, pCpuMappingAttr);
4628 if (pAllocList != NULL)
4629 *pAddrSpace = pAllocList[0];
4630 }
4631 /*!
4632 * @brief override physical address width
4633 *
4634 * address width to be override in bits.
4635 * @param[in] pGpu
4636 * @param[in] pMemDesc Memory descriptor to update
4637 * @param[in] addresswidth Offset to refer to
4638 *
4639 * @returns nothing
4640 */
4641 void
memdescOverridePhysicalAddressWidthWindowsWAR(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,NvU32 addressWidth)4642 memdescOverridePhysicalAddressWidthWindowsWAR
4643 (
4644 OBJGPU *pGpu,
4645 MEMORY_DESCRIPTOR *pMemDesc,
4646 NvU32 addressWidth
4647 )
4648 {
4649 if (RMCFG_FEATURE_PLATFORM_WINDOWS)
4650 {
4651 if (addressWidth < gpuGetPhysAddrWidth_HAL(pGpu, ADDR_SYSMEM))
4652 {
4653 pMemDesc->_flags |= MEMDESC_FLAGS_OVERRIDE_SYSTEM_ADDRESS_LIMIT;
4654 pMemDesc->_overridenAddressWidth = addressWidth;
4655 }
4656 }
4657 }
4658
4659 void
memdescSetName(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,const char * name,const char * suffix)4660 memdescSetName(OBJGPU *pGpu, MEMORY_DESCRIPTOR *pMemDesc, const char *name, const char* suffix)
4661 {
4662 return;
4663 }
4664
4665 NV_STATUS
memdescSendMemDescToGSP(OBJGPU * pGpu,MEMORY_DESCRIPTOR * pMemDesc,NvHandle * pHandle)4666 memdescSendMemDescToGSP(OBJGPU *pGpu, MEMORY_DESCRIPTOR *pMemDesc, NvHandle *pHandle)
4667 {
4668 NV_STATUS status = NV_OK;
4669 RsClient *pClient;
4670 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
4671 NvU32 flags = 0;
4672 NvU32 index = 0;
4673 NvU32 hClass;
4674 NvU64 *pageNumberList = NULL;
4675 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
4676 NV_MEMORY_LIST_ALLOCATION_PARAMS listAllocParams = {0};
4677
4678 // Nothing to do without GSP
4679 if (!IS_GSP_CLIENT(pGpu))
4680 {
4681 return NV_OK;
4682 }
4683
4684 switch (memdescGetAddressSpace(pMemDesc))
4685 {
4686
4687 case ADDR_FBMEM:
4688 hClass = NV01_MEMORY_LIST_FBMEM;
4689 break;
4690
4691 case ADDR_SYSMEM:
4692 hClass = NV01_MEMORY_LIST_SYSTEM;
4693 break;
4694
4695 default:
4696 return NV_ERR_NOT_SUPPORTED;
4697 }
4698
4699 // Initialize parameters with pMemDesc information
4700 listAllocParams.pteAdjust = pMemDesc->PteAdjust;
4701 listAllocParams.format = memdescGetPteKind(pMemDesc);
4702 listAllocParams.size = pMemDesc->Size;
4703 listAllocParams.hClient = NV01_NULL_OBJECT;
4704 listAllocParams.hParent = NV01_NULL_OBJECT;
4705 listAllocParams.hObject = NV01_NULL_OBJECT;
4706 listAllocParams.limit = pMemDesc->Size - 1;
4707 listAllocParams.flagsOs02 = (DRF_DEF(OS02,_FLAGS,_MAPPING,_NO_MAP) |
4708 (flags & DRF_SHIFTMASK(NVOS02_FLAGS_COHERENCY)));
4709
4710 // Handle pageCount based on pMemDesc contiguity
4711 if (!memdescGetContiguity(pMemDesc, AT_GPU))
4712 {
4713 listAllocParams.flagsOs02 |= DRF_DEF(OS02,_FLAGS,_PHYSICALITY,_NONCONTIGUOUS);
4714 listAllocParams.pageCount = pMemDesc->PageCount;
4715 }
4716 else
4717 {
4718 listAllocParams.pageCount = 1;
4719 }
4720
4721
4722 // Initialize pageNumberList
4723 pageNumberList = portMemAllocNonPaged(sizeof(NvU64) * listAllocParams.pageCount);
4724 for (index = 0; index < listAllocParams.pageCount; index++)
4725 pageNumberList[index] = memdescGetPte(pMemDesc, AT_GPU, index) >> RM_PAGE_SHIFT;
4726 listAllocParams.pageNumberList = pageNumberList;
4727
4728 // Create MemoryList object
4729 NV_ASSERT_OK_OR_GOTO(status,
4730 pRmApi->Alloc(pRmApi,
4731 pMemoryManager->hClient,
4732 pMemoryManager->hSubdevice,
4733 pHandle,
4734 hClass,
4735 &listAllocParams,
4736 sizeof(listAllocParams)),
4737 end);
4738
4739 NV_ASSERT_OK_OR_GOTO(status,
4740 serverGetClientUnderLock(&g_resServ, pMemoryManager->hClient, &pClient),
4741 end);
4742
4743 // Register MemoryList object to GSP
4744 NV_ASSERT_OK_OR_GOTO(status,
4745 memRegisterWithGsp(pGpu,
4746 pClient,
4747 pMemoryManager->hSubdevice,
4748 *pHandle),
4749 end);
4750
4751 end:
4752 if ((status != NV_OK) && (*pHandle != NV01_NULL_OBJECT))
4753 pRmApi->Free(pRmApi, pMemoryManager->hClient, *pHandle);
4754
4755 if (pageNumberList != NULL)
4756 portMemFree(pageNumberList);
4757
4758 return status;
4759 }
4760
4761 NV_STATUS
memdescSetPageArrayGranularity(MEMORY_DESCRIPTOR * pMemDesc,NvU64 pageArrayGranularity)4762 memdescSetPageArrayGranularity
4763 (
4764 MEMORY_DESCRIPTOR *pMemDesc,
4765 NvU64 pageArrayGranularity
4766 )
4767 {
4768 // Make sure pageArrayGranularity is a power of 2 value.
4769 NV_ASSERT_OR_RETURN((pageArrayGranularity & (pageArrayGranularity - 1)) == 0, NV_ERR_INVALID_ARGUMENT);
4770
4771 // Allow setting the same granularity.
4772 if (pMemDesc->pageArrayGranularity == pageArrayGranularity)
4773 {
4774 return NV_OK;
4775 }
4776
4777 // Make sure setting the page array happens before the pteArray is populated.
4778 NV_ASSERT_OR_RETURN(pMemDesc->_pteArray[0] == 0, NV_ERR_INVALID_STATE);
4779
4780 pMemDesc->pageArrayGranularity = pageArrayGranularity;
4781
4782 return NV_OK;
4783 }
4784
4785 NV_STATUS
memdescFillMemdescForPhysAttr(MEMORY_DESCRIPTOR * pMemDesc,ADDRESS_TRANSLATION addressTranslation,NvU64 * pOffset,NvU32 * pMemAperture,NvU32 * pMemKind,NvU32 * pZCullId,NvU32 * pGpuCacheAttr,NvU32 * pGpuP2PCacheAttr,NvU64 * contigSegmentSize)4786 memdescFillMemdescForPhysAttr
4787 (
4788 MEMORY_DESCRIPTOR *pMemDesc,
4789 ADDRESS_TRANSLATION addressTranslation,
4790 NvU64 *pOffset,
4791 NvU32 *pMemAperture,
4792 NvU32 *pMemKind,
4793 NvU32 *pZCullId,
4794 NvU32 *pGpuCacheAttr,
4795 NvU32 *pGpuP2PCacheAttr,
4796 NvU64 *contigSegmentSize
4797 )
4798 {
4799 NvU64 surfOffset = *pOffset, surfBase, surfLimit;
4800 NvU32 zcbitmap;
4801
4802 surfBase = memdescGetPhysAddr(pMemDesc, addressTranslation, 0);
4803 surfLimit = surfBase + pMemDesc->Size - 1;
4804 *pMemKind = memdescGetPteKind(pMemDesc);
4805
4806 *pOffset = memdescGetPhysAddr(pMemDesc, addressTranslation, surfOffset);
4807
4808 if (memdescGetAddressSpace(pMemDesc) == ADDR_FBMEM )
4809 *pMemAperture = NV0041_CTRL_CMD_GET_SURFACE_PHYS_ATTR_APERTURE_VIDMEM;
4810 else if (memdescGetAddressSpace(pMemDesc) == ADDR_SYSMEM)
4811 *pMemAperture = NV0041_CTRL_CMD_GET_SURFACE_PHYS_ATTR_APERTURE_SYSMEM;
4812 else if (memdescGetAddressSpace(pMemDesc) == ADDR_EGM)
4813 *pMemAperture = NV0041_CTRL_CMD_GET_SURFACE_PHYS_ATTR_APERTURE_SYSMEM;
4814 else if (memdescGetAddressSpace(pMemDesc) == ADDR_VIRTUAL )
4815 {
4816 //
4817 // XXX we could theoretically find whatever phys mem object is plugged
4818 // in at surfOffset w/in the virt object... that'd mean scanning
4819 // pMemory->DmaMappingList
4820 //
4821 return NV_ERR_NOT_SUPPORTED;
4822 }
4823 else
4824 return NV_ERR_GENERIC;
4825
4826 if (memdescGetGpuCacheAttrib(pMemDesc) == NV_MEMORY_CACHED)
4827 {
4828 *pGpuCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_CACHED;
4829 }
4830 else if (memdescGetGpuCacheAttrib(pMemDesc) == NV_MEMORY_UNCACHED)
4831 {
4832 *pGpuCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_UNCACHED;
4833 }
4834 else
4835 {
4836 *pGpuCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_CACHED_UNKNOWN;
4837 }
4838
4839 if (memdescGetGpuP2PCacheAttrib(pMemDesc) == NV_MEMORY_CACHED)
4840 {
4841 *pGpuP2PCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_CACHED;
4842 }
4843 else if (memdescGetGpuP2PCacheAttrib(pMemDesc) == NV_MEMORY_UNCACHED)
4844 {
4845 *pGpuP2PCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_UNCACHED;
4846 }
4847 else
4848 {
4849 *pGpuP2PCacheAttr = NV0041_CTRL_GET_SURFACE_PHYS_ATTR_GPU_CACHED_UNKNOWN;
4850 }
4851
4852 zcbitmap = FB_HWRESID_ZCULL_VAL_FERMI(memdescGetHwResId(pMemDesc)); //bitmap form... need a scalar
4853 for ( *pZCullId = 0; zcbitmap; zcbitmap >>= 1, *pZCullId += 1) {;;;}
4854 *pZCullId -= 1; // side effect if there is no zcull id of setting ~0
4855
4856 *contigSegmentSize = surfLimit - (surfBase + surfOffset) + 1;
4857
4858 if ( !memdescGetContiguity(pMemDesc, addressTranslation))
4859 {
4860 // XXX overly conservative. we could scan the PTEs to find out if more pages are contig.
4861 NvU64 surfOffsetLimitSame4KBPage = (4*1024)*((surfBase + surfOffset)/(4*1024)) + (4*1024) - 1;
4862 if ( surfLimit >= surfOffsetLimitSame4KBPage )
4863 *contigSegmentSize = surfOffsetLimitSame4KBPage - (surfBase + surfOffset) + 1;
4864 }
4865
4866 return NV_OK;
4867 }
4868
4869 NvBool
memdescIsEgm(MEMORY_DESCRIPTOR * pMemDesc)4870 memdescIsEgm
4871 (
4872 MEMORY_DESCRIPTOR *pMemDesc
4873 )
4874 {
4875 NV_ADDRESS_SPACE addrSpace;
4876 MEMORY_DESCRIPTOR *pRootMemDesc;
4877 MemoryManager *pMemoryManager;
4878
4879 //
4880 // If memdesc is not device owned, we can't tell if local EGM is enabled
4881 // due to lack of memory manager.
4882 //
4883 if (pMemDesc->pGpu == NULL)
4884 {
4885 return NV_FALSE;
4886 }
4887
4888 addrSpace = memdescGetAddressSpace(pMemDesc);
4889 pRootMemDesc = memdescGetRootMemDesc(pMemDesc, NULL);
4890
4891 if ((pRootMemDesc == NULL) || (pRootMemDesc->pGpu == NULL))
4892 {
4893 return NV_FALSE;
4894 }
4895
4896 pMemoryManager = GPU_GET_MEMORY_MANAGER(pRootMemDesc->pGpu);
4897 if (pMemoryManager == NULL)
4898 {
4899 return NV_FALSE;
4900 }
4901
4902 if ((addrSpace == ADDR_EGM) ||
4903 (memmgrIsLocalEgmEnabled(pMemoryManager) &&
4904 (addrSpace == ADDR_SYSMEM) &&
4905 (memdescGetNumaNode(pMemDesc) == pMemoryManager->localEgmNodeId)))
4906 {
4907 return NV_TRUE;
4908 }
4909
4910 return NV_FALSE;
4911 }
4912