1
0
Fork 0
mirror of https://github.com/Ryujinx/Ryujinx.git synced 2024-12-03 19:42:02 +00:00
Ryujinx/Ryujinx.HLE/HOS/Services/Nv/NvGpuAS/NvGpuASCtx.cs

200 lines
5 KiB
C#
Raw Normal View History

using Ryujinx.Graphics.Memory;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
{
class NvGpuASCtx
{
public NvGpuVmm Vmm { get; private set; }
private class Range
{
public ulong Start { get; private set; }
public ulong End { get; private set; }
2018-12-01 20:01:59 +00:00
public Range(long position, long size)
{
2018-12-01 20:01:59 +00:00
Start = (ulong)position;
End = (ulong)size + Start;
}
}
private class MappedMemory : Range
{
public long PhysicalAddress { get; private set; }
public bool VaAllocated { get; private set; }
public MappedMemory(
2018-12-01 20:01:59 +00:00
long position,
long size,
long physicalAddress,
bool vaAllocated) : base(position, size)
{
2018-12-01 20:24:37 +00:00
PhysicalAddress = physicalAddress;
VaAllocated = vaAllocated;
}
}
2018-12-01 20:01:59 +00:00
private SortedList<long, Range> _maps;
private SortedList<long, Range> _reservations;
2018-12-01 20:01:59 +00:00
public NvGpuASCtx(ServiceCtx context)
{
2018-12-01 20:01:59 +00:00
Vmm = new NvGpuVmm(context.Memory);
2018-12-01 20:01:59 +00:00
_maps = new SortedList<long, Range>();
_reservations = new SortedList<long, Range>();
}
2018-12-01 20:01:59 +00:00
public bool ValidateFixedBuffer(long position, long size)
{
2018-12-01 20:01:59 +00:00
long mapEnd = position + size;
//Check if size is valid (0 is also not allowed).
2018-12-01 20:01:59 +00:00
if ((ulong)mapEnd <= (ulong)position)
{
return false;
}
//Check if address is page aligned.
2018-12-01 20:01:59 +00:00
if ((position & NvGpuVmm.PageMask) != 0)
{
return false;
}
//Check if region is reserved.
2018-12-01 20:01:59 +00:00
if (BinarySearch(_reservations, position) == null)
{
return false;
}
//Check for overlap with already mapped buffers.
2018-12-01 20:01:59 +00:00
Range map = BinarySearchLt(_maps, mapEnd);
2018-12-01 20:01:59 +00:00
if (map != null && map.End > (ulong)position)
{
return false;
}
return true;
}
public void AddMap(
2018-12-01 20:01:59 +00:00
long position,
long size,
long physicalAddress,
bool vaAllocated)
{
2018-12-01 20:01:59 +00:00
_maps.Add(position, new MappedMemory(position, size, physicalAddress, vaAllocated));
}
2018-12-01 20:01:59 +00:00
public bool RemoveMap(long position, out long size)
{
2018-12-01 20:01:59 +00:00
size = 0;
2018-12-01 20:01:59 +00:00
if (_maps.Remove(position, out Range value))
{
2018-12-01 20:01:59 +00:00
MappedMemory map = (MappedMemory)value;
2018-12-01 20:01:59 +00:00
if (map.VaAllocated)
{
2018-12-01 20:01:59 +00:00
size = (long)(map.End - map.Start);
}
return true;
}
return false;
}
2018-12-01 20:01:59 +00:00
public bool TryGetMapPhysicalAddress(long position, out long physicalAddress)
{
2018-12-01 20:01:59 +00:00
Range map = BinarySearch(_maps, position);
2018-12-01 20:01:59 +00:00
if (map != null)
{
2018-12-01 20:01:59 +00:00
physicalAddress = ((MappedMemory)map).PhysicalAddress;
return true;
}
2018-12-01 20:01:59 +00:00
physicalAddress = 0;
return false;
}
2018-12-01 20:01:59 +00:00
public void AddReservation(long position, long size)
{
2018-12-01 20:01:59 +00:00
_reservations.Add(position, new Range(position, size));
}
2018-12-01 20:01:59 +00:00
public bool RemoveReservation(long position)
{
2018-12-01 20:01:59 +00:00
return _reservations.Remove(position);
}
2018-12-01 20:01:59 +00:00
private Range BinarySearch(SortedList<long, Range> lst, long position)
{
2018-12-01 20:01:59 +00:00
int left = 0;
int right = lst.Count - 1;
2018-12-01 20:01:59 +00:00
while (left <= right)
{
2018-12-01 20:01:59 +00:00
int size = right - left;
2018-12-01 20:01:59 +00:00
int middle = left + (size >> 1);
2018-12-01 20:01:59 +00:00
Range rg = lst.Values[middle];
2018-12-01 20:01:59 +00:00
if ((ulong)position >= rg.Start && (ulong)position < rg.End)
{
2018-12-01 20:01:59 +00:00
return rg;
}
2018-12-01 20:01:59 +00:00
if ((ulong)position < rg.Start)
{
2018-12-01 20:01:59 +00:00
right = middle - 1;
}
else
{
2018-12-01 20:01:59 +00:00
left = middle + 1;
}
}
return null;
}
2018-12-01 20:01:59 +00:00
private Range BinarySearchLt(SortedList<long, Range> lst, long position)
{
2018-12-01 20:01:59 +00:00
Range ltRg = null;
2018-12-01 20:01:59 +00:00
int left = 0;
int right = lst.Count - 1;
2018-12-01 20:01:59 +00:00
while (left <= right)
{
2018-12-01 20:01:59 +00:00
int size = right - left;
2018-12-01 20:01:59 +00:00
int middle = left + (size >> 1);
2018-12-01 20:01:59 +00:00
Range rg = lst.Values[middle];
2018-12-01 20:01:59 +00:00
if ((ulong)position < rg.Start)
{
2018-12-01 20:01:59 +00:00
right = middle - 1;
}
else
{
2018-12-01 20:01:59 +00:00
left = middle + 1;
2018-12-01 20:01:59 +00:00
if ((ulong)position > rg.Start)
{
2018-12-01 20:01:59 +00:00
ltRg = rg;
}
}
}
2018-12-01 20:01:59 +00:00
return ltRg;
}
}
}