private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments) { const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16}, size 0x{1:x16} and alignment 0x{2:x16}!"; AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context); ulong physicalAddress; if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0) { lock (addressSpaceContext) { if (addressSpaceContext.TryGetMapPhysicalAddress(arguments.Offset, out physicalAddress)) { ulong virtualAddress = arguments.Offset + arguments.BufferOffset; physicalAddress += arguments.BufferOffset; addressSpaceContext.Gmm.Map(physicalAddress, virtualAddress, arguments.MappingSize); return(NvInternalResult.Success); } else { Logger.Warning?.Print(LogClass.ServiceNv, $"Address 0x{arguments.Offset:x16} not mapped!"); return(NvInternalResult.InvalidInput); } } } NvMapHandle map = NvMapDeviceFile.GetMapFromHandle(Owner, arguments.NvMapHandle); if (map == null) { Logger.Warning?.Print(LogClass.ServiceNv, $"Invalid NvMap handle 0x{arguments.NvMapHandle:x8}!"); return(NvInternalResult.InvalidInput); } ulong pageSize = (ulong)arguments.PageSize; if (pageSize == 0) { pageSize = (ulong)map.Align; } physicalAddress = map.Address + arguments.BufferOffset; ulong size = arguments.MappingSize; if (size == 0) { size = (uint)map.Size; } NvInternalResult result = NvInternalResult.Success; lock (addressSpaceContext) { // Note: When the fixed offset flag is not set, // the Offset field holds the alignment size instead. bool virtualAddressAllocated = (arguments.Flags & AddressSpaceFlags.FixedOffset) == 0; if (!virtualAddressAllocated) { if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size, pageSize)) { addressSpaceContext.Gmm.Map(physicalAddress, arguments.Offset, size); } else { string message = string.Format(mapErrorMsg, arguments.Offset, size, pageSize); Logger.Warning?.Print(LogClass.ServiceNv, message); result = NvInternalResult.InvalidInput; } } else { ulong va = _memoryAllocator.GetFreeAddress(size, out ulong freeAddressStartPosition, pageSize); if (va != NvMemoryAllocator.PteUnmapped) { _memoryAllocator.AllocateRange(va, size, freeAddressStartPosition); } addressSpaceContext.Gmm.Map(physicalAddress, va, size); arguments.Offset = va; } if (arguments.Offset == NvMemoryAllocator.PteUnmapped) { arguments.Offset = 0; Logger.Warning?.Print(LogClass.ServiceNv, $"Failed to map size 0x{size:x16}!"); result = NvInternalResult.InvalidInput; } else { addressSpaceContext.AddMap(arguments.Offset, size, physicalAddress, virtualAddressAllocated); } } return(result); }
private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments) { const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!"; AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Owner); NvMapHandle map = NvMapDeviceFile.GetMapFromHandle(Owner, arguments.NvMapHandle, true); if (map == null) { Logger.PrintWarning(LogClass.ServiceNv, $"Invalid NvMap handle 0x{arguments.NvMapHandle:x8}!"); return(NvInternalResult.InvalidInput); } long physicalAddress; if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0) { lock (addressSpaceContext) { if (addressSpaceContext.TryGetMapPhysicalAddress(arguments.Offset, out physicalAddress)) { long virtualAddress = arguments.Offset + arguments.BufferOffset; physicalAddress += arguments.BufferOffset; if (addressSpaceContext.Vmm.Map(physicalAddress, virtualAddress, arguments.MappingSize) < 0) { string message = string.Format(mapErrorMsg, virtualAddress, arguments.MappingSize); Logger.PrintWarning(LogClass.ServiceNv, message); return(NvInternalResult.InvalidInput); } return(NvInternalResult.Success); } else { Logger.PrintWarning(LogClass.ServiceNv, $"Address 0x{arguments.Offset:x16} not mapped!"); return(NvInternalResult.InvalidInput); } } } physicalAddress = map.Address + arguments.BufferOffset; long size = arguments.MappingSize; if (size == 0) { size = (uint)map.Size; } NvInternalResult result = NvInternalResult.Success; lock (addressSpaceContext) { // Note: When the fixed offset flag is not set, // the Offset field holds the alignment size instead. bool virtualAddressAllocated = (arguments.Flags & AddressSpaceFlags.FixedOffset) == 0; if (!virtualAddressAllocated) { if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size)) { arguments.Offset = addressSpaceContext.Vmm.Map(physicalAddress, arguments.Offset, size); } else { string message = string.Format(mapErrorMsg, arguments.Offset, size); Logger.PrintWarning(LogClass.ServiceNv, message); result = NvInternalResult.InvalidInput; } } else { arguments.Offset = addressSpaceContext.Vmm.Map(physicalAddress, size); } if (arguments.Offset < 0) { arguments.Offset = 0; Logger.PrintWarning(LogClass.ServiceNv, $"Failed to map size 0x{size:x16}!"); result = NvInternalResult.InvalidInput; } else { addressSpaceContext.AddMap(arguments.Offset, size, physicalAddress, virtualAddressAllocated); } } return(result); }