mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-03-15 06:10:18 +00:00
Fixes and remove more of the emulated shared memory
This commit is contained in:
parent
335d91a367
commit
02718079a0
6 changed files with 54 additions and 65 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue