Fixes and remove more of the emulated shared memory

This commit is contained in:
gdk 2021-12-28 09:25:58 -03:00
parent 335d91a367
commit 02718079a0
6 changed files with 54 additions and 65 deletions

View file

@ -324,16 +324,16 @@ namespace Ryujinx.Cpu
/// <inheritdoc/> /// <inheritdoc/>
public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false) public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
{ {
if (tracked)
{
SignalMemoryTracking(va, (ulong)size, true);
}
if (size == 0) if (size == 0)
{ {
return new WritableRegion(null, va, Memory<byte>.Empty); return new WritableRegion(null, va, Memory<byte>.Empty);
} }
if (tracked)
{
SignalMemoryTracking(va, (ulong)size, true);
}
if (IsContiguousAndMapped(va, size)) if (IsContiguousAndMapped(va, size))
{ {
return new WritableRegion(null, va, _backingMemory.GetMemory(GetPhysicalAddressInternal(va), size)); return new WritableRegion(null, va, _backingMemory.GetMemory(GetPhysicalAddressInternal(va), size));
@ -342,7 +342,7 @@ namespace Ryujinx.Cpu
{ {
Memory<byte> memory = new byte[size]; Memory<byte> memory = new byte[size];
GetSpan(va, size).CopyTo(memory.Span); ReadImpl(va, memory.Span);
return new WritableRegion(this, va, memory); return new WritableRegion(this, va, memory);
} }
@ -849,17 +849,6 @@ namespace Ryujinx.Cpu
} }
} }
private ulong GetPhysicalAddress(ulong va)
{
// We return -1L if the virtual address is invalid or unmapped.
if (!ValidateAddress(va) || !IsMapped(va))
{
return ulong.MaxValue;
}
return GetPhysicalAddressInternal(va);
}
private ulong GetPhysicalAddressInternal(ulong va) private ulong GetPhysicalAddressInternal(ulong va)
{ {
return _pageTable.Read(va) + (va & PageMask); return _pageTable.Read(va) + (va & PageMask);
@ -874,6 +863,6 @@ namespace Ryujinx.Cpu
_memoryEh.Dispose(); _memoryEh.Dispose();
} }
private void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message); private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
} }
} }

View file

@ -17,6 +17,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -555,7 +556,14 @@ namespace Ryujinx.HLE.HOS
Graphics.Gpu.GraphicsConfig.TitleId = TitleIdText; Graphics.Gpu.GraphicsConfig.TitleId = TitleIdText;
_device.Gpu.HostInitalized.Set(); _device.Gpu.HostInitalized.Set();
Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, _device.Configuration.MemoryManagerMode); MemoryManagerMode memoryManagerMode = _device.Configuration.MemoryManagerMode;
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
{
memoryManagerMode = MemoryManagerMode.SoftwarePageTable;
}
Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, memoryManagerMode);
metaData.GetNpdm(out Npdm npdm).ThrowIfFailure(); metaData.GetNpdm(out Npdm npdm).ThrowIfFailure();
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, new ProgramInfo(in npdm), executables: programs); ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, new ProgramInfo(in npdm), executables: programs);

View file

@ -21,6 +21,11 @@ namespace Ryujinx.HLE.HOS
{ {
MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode; MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode;
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
{
mode = MemoryManagerMode.SoftwarePageTable;
}
switch (mode) switch (mode)
{ {
case MemoryManagerMode.SoftwarePageTable: case MemoryManagerMode.SoftwarePageTable:

View file

@ -11,6 +11,7 @@ namespace Ryujinx.Memory
{ {
private readonly bool _usesSharedMemory; private readonly bool _usesSharedMemory;
private readonly bool _isMirror; private readonly bool _isMirror;
private readonly bool _viewCompatible;
private IntPtr _sharedMemory; private IntPtr _sharedMemory;
private IntPtr _pointer; private IntPtr _pointer;
@ -41,7 +42,8 @@ namespace Ryujinx.Memory
} }
else if (flags.HasFlag(MemoryAllocationFlags.Reserve)) else if (flags.HasFlag(MemoryAllocationFlags.Reserve))
{ {
_pointer = MemoryManagement.Reserve(size, flags.HasFlag(MemoryAllocationFlags.ViewCompatible)); _viewCompatible = flags.HasFlag(MemoryAllocationFlags.ViewCompatible);
_pointer = MemoryManagement.Reserve(size, _viewCompatible);
} }
else else
{ {
@ -154,7 +156,7 @@ namespace Ryujinx.Memory
/// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception> /// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception>
public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail = true) public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail = true)
{ {
MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, throwOnFail); MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, _viewCompatible, throwOnFail);
} }
/// <summary> /// <summary>
@ -412,7 +414,27 @@ namespace Ryujinx.Memory
} }
} }
private void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock)); /// <summary>
private void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException(); /// Checks if the specified memory allocation flags are supported on the current platform.
/// </summary>
/// <param name="flags">Flags to be checked</param>
/// <returns>True if the platform supports all the flags, false otherwise</returns>
public static bool SupportsFlags(MemoryAllocationFlags flags)
{
if (flags.HasFlag(MemoryAllocationFlags.ViewCompatible))
{
if (OperatingSystem.IsWindows())
{
return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
}
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
}
return true;
}
private static void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock));
private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
} }
} }

View file

@ -108,7 +108,7 @@ namespace Ryujinx.Memory
} }
} }
public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool throwOnFail) public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool forView, bool throwOnFail)
{ {
bool result; bool result;
@ -116,7 +116,7 @@ namespace Ryujinx.Memory
{ {
IntPtr sizeNint = new IntPtr((long)size); IntPtr sizeNint = new IntPtr((long)size);
result = MemoryManagementWindows.Reprotect(address, sizeNint, permission); result = MemoryManagementWindows.Reprotect(address, sizeNint, permission, forView);
} }
else if (OperatingSystem.IsLinux() || else if (OperatingSystem.IsLinux() ||
OperatingSystem.IsMacOS()) OperatingSystem.IsMacOS())

View file

@ -1,6 +1,5 @@
using Ryujinx.Memory.WindowsShared; using Ryujinx.Memory.WindowsShared;
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
@ -13,11 +12,6 @@ namespace Ryujinx.Memory
private static readonly IntPtr InvalidHandleValue = new IntPtr(-1); private static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
private static readonly IntPtr CurrentProcessHandle = new IntPtr(-1); private static readonly IntPtr CurrentProcessHandle = new IntPtr(-1);
private static bool UseWin10Placeholders;
private static object _emulatedHandleLock = new object();
private static EmulatedSharedMemoryWindows[] _emulatedShared = new EmulatedSharedMemoryWindows[64];
private static List<EmulatedSharedMemoryWindows> _emulatedSharedList = new List<EmulatedSharedMemoryWindows>();
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc( private static extern IntPtr VirtualAlloc(
@ -87,11 +81,6 @@ namespace Ryujinx.Memory
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
private static extern uint GetLastError(); private static extern uint GetLastError();
static MemoryManagementWindows()
{
UseWin10Placeholders = OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
}
public static IntPtr Allocate(IntPtr size) public static IntPtr Allocate(IntPtr size)
{ {
return AllocateInternal(size, AllocationType.Reserve | AllocationType.Commit); return AllocateInternal(size, AllocationType.Reserve | AllocationType.Commit);
@ -186,24 +175,21 @@ namespace Ryujinx.Memory
} }
} }
public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission) public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission, bool forView)
{ {
if (UseWin10Placeholders) if (forView)
{ {
ulong uaddress = (ulong)address; ulong uaddress = (ulong)address;
ulong usize = (ulong)size; ulong usize = (ulong)size;
while (usize > 0) while (usize > 0)
{ {
ulong nextGranular = (uaddress & ~EmulatedSharedMemoryWindows.MappingMask) + EmulatedSharedMemoryWindows.MappingGranularity; if (!VirtualProtect((IntPtr)uaddress, (IntPtr)PageSize, GetProtection(permission), out _))
ulong mapSize = Math.Min(usize, nextGranular - uaddress);
if (!VirtualProtect((IntPtr)uaddress, (IntPtr)mapSize, GetProtection(permission), out _))
{ {
return false; return false;
} }
uaddress = nextGranular; uaddress += PageSize;
usize -= mapSize; usize -= PageSize;
} }
return true; return true;
@ -233,27 +219,6 @@ namespace Ryujinx.Memory
return VirtualFree(address, IntPtr.Zero, AllocationType.Release); return VirtualFree(address, IntPtr.Zero, AllocationType.Release);
} }
private static int GetEmulatedHandle()
{
// Assumes we have the handle lock.
for (int i = 0; i < _emulatedShared.Length; i++)
{
if (_emulatedShared[i] == null)
{
return i + 1;
}
}
throw new InvalidProgramException("Too many shared memory handles were created.");
}
public static bool EmulatedHandleValid(ref int handle)
{
handle--;
return handle >= 0 && handle < _emulatedShared.Length && _emulatedShared[handle] != null;
}
public static IntPtr CreateSharedMemory(IntPtr size, bool reserve) public static IntPtr CreateSharedMemory(IntPtr size, bool reserve)
{ {
var prot = reserve ? FileMapProtection.SectionReserve : FileMapProtection.SectionCommit; var prot = reserve ? FileMapProtection.SectionReserve : FileMapProtection.SectionCommit;