private NvInternalResult AllocSpace(ref AllocSpaceArguments arguments) { AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); ulong size = (ulong)arguments.Pages * (ulong)arguments.PageSize; NvInternalResult result = NvInternalResult.Success; lock (addressSpaceContext) { // Note: When the fixed offset flag is not set, // the Offset field holds the alignment size instead. if ((arguments.Flags & AddressSpaceFlags.FixedOffset) != 0) { bool regionInUse = _memoryAllocator.IsRegionInUse(arguments.Offset, size, out ulong freeAddressStartPosition); ulong address; if (!regionInUse) { _memoryAllocator.AllocateRange(arguments.Offset, size, freeAddressStartPosition); address = freeAddressStartPosition; } else { address = NvMemoryAllocator.PteUnmapped; } arguments.Offset = address; } else { ulong address = _memoryAllocator.GetFreeAddress(size, out ulong freeAddressStartPosition, arguments.Offset); if (address != NvMemoryAllocator.PteUnmapped) { _memoryAllocator.AllocateRange(address, size, freeAddressStartPosition); } arguments.Offset = address; } if (arguments.Offset == NvMemoryAllocator.PteUnmapped) { arguments.Offset = 0; Logger.Warning?.Print(LogClass.ServiceNv, $"Failed to allocate size {size:x16}!"); result = NvInternalResult.OutOfMemory; } else { addressSpaceContext.AddReservation(arguments.Offset, size); } } return(result); }
private NvInternalResult MapCommandBuffer(Span <byte> arguments) { int headerSize = Unsafe.SizeOf <MapCommandBufferArguments>(); MapCommandBufferArguments commandBufferHeader = MemoryMarshal.Cast <byte, MapCommandBufferArguments>(arguments)[0]; Span <CommandBufferHandle> commandBufferEntries = MemoryMarshal.Cast <byte, CommandBufferHandle>(arguments.Slice(headerSize)).Slice(0, commandBufferHeader.NumEntries); MemoryManager gmm = NvHostAsGpuDeviceFile.GetAddressSpaceContext(Context).Gmm; foreach (ref CommandBufferHandle commandBufferEntry in commandBufferEntries) { NvMapHandle map = NvMapDeviceFile.GetMapFromHandle(Owner, commandBufferEntry.MapHandle); if (map == null) { Logger.Warning?.Print(LogClass.ServiceNv, $"Invalid handle 0x{commandBufferEntry.MapHandle:x8}!"); return(NvInternalResult.InvalidInput); } lock (map) { if (map.DmaMapAddress == 0) { ulong va = _memoryAllocator.GetFreeAddress((ulong)map.Size, out ulong freeAddressStartPosition, 1, MemoryManager.PageSize); if (va != NvMemoryAllocator.PteUnmapped && va <= uint.MaxValue && (va + (uint)map.Size) <= uint.MaxValue) { _memoryAllocator.AllocateRange(va, (uint)map.Size, freeAddressStartPosition); gmm.Map(map.Address, va, (uint)map.Size); map.DmaMapAddress = va; } else { map.DmaMapAddress = NvMemoryAllocator.PteUnmapped; } } commandBufferEntry.MapAddress = (int)map.DmaMapAddress; } } return(NvInternalResult.Success); }