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/>
public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
{
if (tracked)
{
SignalMemoryTracking(va, (ulong)size, true);
}
if (size == 0)
{
return new WritableRegion(null, va, Memory<byte>.Empty);
}
if (tracked)
{
SignalMemoryTracking(va, (ulong)size, true);
}
if (IsContiguousAndMapped(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];
GetSpan(va, size).CopyTo(memory.Span);
ReadImpl(va, memory.Span);
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)
{
return _pageTable.Read(va) + (va & PageMask);
@ -874,6 +863,6 @@ namespace Ryujinx.Cpu
_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.HOS.Kernel.Process;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -555,7 +556,14 @@ namespace Ryujinx.HLE.HOS
Graphics.Gpu.GraphicsConfig.TitleId = TitleIdText;
_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();
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;
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
{
mode = MemoryManagerMode.SoftwarePageTable;
}
switch (mode)
{
case MemoryManagerMode.SoftwarePageTable:

View file

@ -11,6 +11,7 @@ namespace Ryujinx.Memory
{
private readonly bool _usesSharedMemory;
private readonly bool _isMirror;
private readonly bool _viewCompatible;
private IntPtr _sharedMemory;
private IntPtr _pointer;
@ -41,7 +42,8 @@ namespace Ryujinx.Memory
}
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
{
@ -154,7 +156,7 @@ namespace Ryujinx.Memory
/// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception>
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>
@ -412,7 +414,27 @@ namespace Ryujinx.Memory
}
}
private void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock));
private void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
/// <summary>
/// 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;
@ -116,7 +116,7 @@ namespace Ryujinx.Memory
{
IntPtr sizeNint = new IntPtr((long)size);
result = MemoryManagementWindows.Reprotect(address, sizeNint, permission);
result = MemoryManagementWindows.Reprotect(address, sizeNint, permission, forView);
}
else if (OperatingSystem.IsLinux() ||
OperatingSystem.IsMacOS())

View file

@ -1,6 +1,5 @@
using Ryujinx.Memory.WindowsShared;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@ -13,11 +12,6 @@ namespace Ryujinx.Memory
private static readonly IntPtr InvalidHandleValue = 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)]
private static extern IntPtr VirtualAlloc(
@ -87,11 +81,6 @@ namespace Ryujinx.Memory
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
static MemoryManagementWindows()
{
UseWin10Placeholders = OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
}
public static IntPtr Allocate(IntPtr size)
{
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 usize = (ulong)size;
while (usize > 0)
{
ulong nextGranular = (uaddress & ~EmulatedSharedMemoryWindows.MappingMask) + EmulatedSharedMemoryWindows.MappingGranularity;
ulong mapSize = Math.Min(usize, nextGranular - uaddress);
if (!VirtualProtect((IntPtr)uaddress, (IntPtr)mapSize, GetProtection(permission), out _))
if (!VirtualProtect((IntPtr)uaddress, (IntPtr)PageSize, GetProtection(permission), out _))
{
return false;
}
uaddress = nextGranular;
usize -= mapSize;
uaddress += PageSize;
usize -= PageSize;
}
return true;
@ -233,27 +219,6 @@ namespace Ryujinx.Memory
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)
{
var prot = reserve ? FileMapProtection.SectionReserve : FileMapProtection.SectionCommit;