MapBufferEx: take page size into account (#873)

Fix #744
This commit is contained in:
Thog 2020-01-12 03:14:27 +01:00 committed by Ac_K
parent e485ee049d
commit 29e8576b0d
3 changed files with 21 additions and 11 deletions

View file

@ -66,12 +66,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
/// <param name="pa">CPU virtual address to map into</param> /// <param name="pa">CPU virtual address to map into</param>
/// <param name="size">Size in bytes of the mapping</param> /// <param name="size">Size in bytes of the mapping</param>
/// <param name="alignment">Required alignment of the GPU virtual address in bytes</param>
/// <returns>GPU virtual address where the range was mapped, or an all ones mask in case of failure</returns> /// <returns>GPU virtual address where the range was mapped, or an all ones mask in case of failure</returns>
public ulong Map(ulong pa, ulong size) public ulong MapAllocate(ulong pa, ulong size, ulong alignment)
{ {
lock (_pageTable) lock (_pageTable)
{ {
ulong va = GetFreePosition(size); ulong va = GetFreePosition(size, alignment);
if (va != PteUnmapped) if (va != PteUnmapped)
{ {

View file

@ -1,10 +1,12 @@
using Ryujinx.Common.Logging; using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types;
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap; using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
{ {
@ -165,7 +167,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments) private NvInternalResult MapBufferEx(ref MapBufferExArguments arguments)
{ {
const string mapErrorMsg = "Failed to map fixed buffer with offset 0x{0:x16} and size 0x{1:x16}!"; 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); AddressSpaceContext addressSpaceContext = GetAddressSpaceContext(Context);
@ -178,6 +180,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
return NvInternalResult.InvalidInput; return NvInternalResult.InvalidInput;
} }
ulong pageSize = (ulong)arguments.PageSize;
if (pageSize == 0)
{
pageSize = (ulong)map.Align;
}
long physicalAddress; long physicalAddress;
if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0) if ((arguments.Flags & AddressSpaceFlags.RemapSubRange) != 0)
@ -192,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
if ((long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)virtualAddress, (ulong)arguments.MappingSize) < 0) if ((long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)virtualAddress, (ulong)arguments.MappingSize) < 0)
{ {
string message = string.Format(mapErrorMsg, virtualAddress, arguments.MappingSize); string message = string.Format(mapErrorMsg, virtualAddress, arguments.MappingSize, pageSize);
Logger.PrintWarning(LogClass.ServiceNv, message); Logger.PrintWarning(LogClass.ServiceNv, message);
@ -229,13 +238,13 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
if (!virtualAddressAllocated) if (!virtualAddressAllocated)
{ {
if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size)) if (addressSpaceContext.ValidateFixedBuffer(arguments.Offset, size, pageSize))
{ {
arguments.Offset = (long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)arguments.Offset, (ulong)size); arguments.Offset = (long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)arguments.Offset, (ulong)size);
} }
else else
{ {
string message = string.Format(mapErrorMsg, arguments.Offset, size); string message = string.Format(mapErrorMsg, arguments.Offset, size, pageSize);
Logger.PrintWarning(LogClass.ServiceNv, message); Logger.PrintWarning(LogClass.ServiceNv, message);
@ -244,7 +253,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu
} }
else else
{ {
arguments.Offset = (long)addressSpaceContext.Gmm.Map((ulong)physicalAddress, (ulong)size); arguments.Offset = (long)addressSpaceContext.Gmm.MapAllocate((ulong)physicalAddress, (ulong)size, pageSize);
} }
if (arguments.Offset < 0) if (arguments.Offset < 0)

View file

@ -48,7 +48,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types
_reservations = new SortedList<long, Range>(); _reservations = new SortedList<long, Range>();
} }
public bool ValidateFixedBuffer(long position, long size) public bool ValidateFixedBuffer(long position, long size, ulong alignment)
{ {
long mapEnd = position + size; long mapEnd = position + size;
@ -58,8 +58,8 @@ namespace Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvHostAsGpu.Types
return false; return false;
} }
// Check if address is page aligned. // Check if address is aligned.
if ((position & (long)MemoryManager.PageMask) != 0) if ((position & (long)(alignment - 1)) != 0)
{ {
return false; return false;
} }