aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Cpu/Jit
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-01-17 01:13:24 -0300
committerGitHub <noreply@github.com>2023-01-17 05:13:24 +0100
commit86fd0643c26433362a25acceb4fa1fcee07dd0b2 (patch)
tree8d12fb6b0629c195a0a3c1014f46cfe8f22cd3e6 /Ryujinx.Cpu/Jit
parent43a83a401ea8101bf6d001fe6fe188e1c106245e (diff)
Implement support for page sizes > 4KB (#4252)
* Implement support for page sizes > 4KB * Check and work around more alignment issues * Was not meant to change this * Use MemoryBlock.GetPageSize() value for signal handler code * Do not take the path for private allocations if host supports 4KB pages * Add Flags attribute on MemoryMapFlags * Fix dirty region size with 16kb pages Would accidentally report a size that was too high (generally 16k instead of 4k, uploading 4x as much data) Co-authored-by: riperiperi <rhy3756547@hotmail.com>
Diffstat (limited to 'Ryujinx.Cpu/Jit')
-rw-r--r--Ryujinx.Cpu/Jit/JitMemoryAllocator.cs2
-rw-r--r--Ryujinx.Cpu/Jit/MemoryManager.cs43
-rw-r--r--Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs63
3 files changed, 80 insertions, 28 deletions
diff --git a/Ryujinx.Cpu/Jit/JitMemoryAllocator.cs b/Ryujinx.Cpu/Jit/JitMemoryAllocator.cs
index 0cf35c17..4aa78d06 100644
--- a/Ryujinx.Cpu/Jit/JitMemoryAllocator.cs
+++ b/Ryujinx.Cpu/Jit/JitMemoryAllocator.cs
@@ -7,5 +7,7 @@ namespace Ryujinx.Cpu.Jit
{
public IJitMemoryBlock Allocate(ulong size) => new JitMemoryBlock(size, MemoryAllocationFlags.None);
public IJitMemoryBlock Reserve(ulong size) => new JitMemoryBlock(size, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Jit);
+
+ public ulong GetPageSize() => MemoryBlock.GetPageSize();
}
}
diff --git a/Ryujinx.Cpu/Jit/MemoryManager.cs b/Ryujinx.Cpu/Jit/MemoryManager.cs
index 21c50d51..014d843b 100644
--- a/Ryujinx.Cpu/Jit/MemoryManager.cs
+++ b/Ryujinx.Cpu/Jit/MemoryManager.cs
@@ -28,6 +28,9 @@ namespace Ryujinx.Cpu.Jit
private readonly MemoryBlock _backingMemory;
private readonly InvalidAccessHandler _invalidAccessHandler;
+ /// <inheritdoc/>
+ public bool Supports4KBPages => true;
+
/// <summary>
/// Address space width in bits.
/// </summary>
@@ -76,7 +79,7 @@ namespace Ryujinx.Cpu.Jit
}
/// <inheritdoc/>
- public void Map(ulong va, ulong pa, ulong size)
+ public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
{
AssertValidAddressAndSize(va, size);
@@ -91,10 +94,17 @@ namespace Ryujinx.Cpu.Jit
pa += PageSize;
remainingSize -= PageSize;
}
+
Tracking.Map(oVa, size);
}
/// <inheritdoc/>
+ public void MapForeign(ulong va, nuint hostPointer, ulong size)
+ {
+ throw new NotSupportedException();
+ }
+
+ /// <inheritdoc/>
public void Unmap(ulong va, ulong size)
{
// If size is 0, there's nothing to unmap, just exit early.
@@ -379,6 +389,32 @@ namespace Ryujinx.Cpu.Jit
}
/// <inheritdoc/>
+ public IEnumerable<HostMemoryRange> GetHostRegions(ulong va, ulong size)
+ {
+ if (size == 0)
+ {
+ return Enumerable.Empty<HostMemoryRange>();
+ }
+
+ var guestRegions = GetPhysicalRegionsImpl(va, size);
+ if (guestRegions == null)
+ {
+ return null;
+ }
+
+ var regions = new HostMemoryRange[guestRegions.Count];
+
+ for (int i = 0; i < regions.Length; i++)
+ {
+ var guestRegion = guestRegions[i];
+ IntPtr pointer = _backingMemory.GetPointer(guestRegion.Address, guestRegion.Size);
+ regions[i] = new HostMemoryRange((nuint)(ulong)pointer, guestRegion.Size);
+ }
+
+ return regions;
+ }
+
+ /// <inheritdoc/>
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size)
{
if (size == 0)
@@ -386,6 +422,11 @@ namespace Ryujinx.Cpu.Jit
return Enumerable.Empty<MemoryRange>();
}
+ return GetPhysicalRegionsImpl(va, size);
+ }
+
+ private List<MemoryRange> GetPhysicalRegionsImpl(ulong va, ulong size)
+ {
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
return null;
diff --git a/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs b/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs
index c4e59db9..856b6b9b 100644
--- a/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs
+++ b/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs
@@ -5,6 +5,7 @@ using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
@@ -37,20 +38,21 @@ namespace Ryujinx.Cpu.Jit
private readonly InvalidAccessHandler _invalidAccessHandler;
private readonly bool _unsafeMode;
- private readonly MemoryBlock _addressSpace;
- private readonly MemoryBlock _addressSpaceMirror;
+ private readonly AddressSpace _addressSpace;
private readonly ulong _addressSpaceSize;
- private readonly MemoryBlock _backingMemory;
private readonly PageTable<ulong> _pageTable;
private readonly MemoryEhMeilleure _memoryEh;
private readonly ulong[] _pageBitmap;
+ /// <inheritdoc/>
+ public bool Supports4KBPages => MemoryBlock.GetPageSize() == PageSize;
+
public int AddressSpaceBits { get; }
- public IntPtr PageTablePointer => _addressSpace.Pointer;
+ public IntPtr PageTablePointer => _addressSpace.Base.Pointer;
public MemoryManagerType Type => _unsafeMode ? MemoryManagerType.HostMappedUnsafe : MemoryManagerType.HostMapped;
@@ -67,7 +69,6 @@ namespace Ryujinx.Cpu.Jit
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null)
{
- _backingMemory = backingMemory;
_pageTable = new PageTable<ulong>();
_invalidAccessHandler = invalidAccessHandler;
_unsafeMode = unsafeMode;
@@ -86,13 +87,10 @@ namespace Ryujinx.Cpu.Jit
_pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))];
- MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
+ _addressSpace = new AddressSpace(backingMemory, asSize, Supports4KBPages);
- _addressSpace = new MemoryBlock(asSize, asFlags);
- _addressSpaceMirror = new MemoryBlock(asSize, asFlags);
-
- Tracking = new MemoryTracking(this, PageSize, invalidAccessHandler);
- _memoryEh = new MemoryEhMeilleure(_addressSpace, _addressSpaceMirror, Tracking);
+ Tracking = new MemoryTracking(this, (int)MemoryBlock.GetPageSize(), invalidAccessHandler);
+ _memoryEh = new MemoryEhMeilleure(_addressSpace.Base, _addressSpace.Mirror, Tracking);
}
/// <summary>
@@ -145,12 +143,11 @@ namespace Ryujinx.Cpu.Jit
}
/// <inheritdoc/>
- public void Map(ulong va, ulong pa, ulong size)
+ public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
{
AssertValidAddressAndSize(va, size);
- _addressSpace.MapView(_backingMemory, pa, va, size);
- _addressSpaceMirror.MapView(_backingMemory, pa, va, size);
+ _addressSpace.Map(va, pa, size, flags);
AddMapping(va, size);
PtMap(va, pa, size);
@@ -158,6 +155,12 @@ namespace Ryujinx.Cpu.Jit
}
/// <inheritdoc/>
+ public void MapForeign(ulong va, nuint hostPointer, ulong size)
+ {
+ throw new NotSupportedException();
+ }
+
+ /// <inheritdoc/>
public void Unmap(ulong va, ulong size)
{
AssertValidAddressAndSize(va, size);
@@ -167,8 +170,7 @@ namespace Ryujinx.Cpu.Jit
RemoveMapping(va, size);
PtUnmap(va, size);
- _addressSpace.UnmapView(_backingMemory, va, size);
- _addressSpaceMirror.UnmapView(_backingMemory, va, size);
+ _addressSpace.Unmap(va, size);
}
private void PtMap(ulong va, ulong pa, ulong size)
@@ -201,7 +203,7 @@ namespace Ryujinx.Cpu.Jit
{
AssertMapped(va, (ulong)Unsafe.SizeOf<T>());
- return _addressSpaceMirror.Read<T>(va);
+ return _addressSpace.Mirror.Read<T>(va);
}
catch (InvalidMemoryRegionException)
{
@@ -241,7 +243,7 @@ namespace Ryujinx.Cpu.Jit
{
AssertMapped(va, (ulong)data.Length);
- _addressSpaceMirror.Read(va, data);
+ _addressSpace.Mirror.Read(va, data);
}
catch (InvalidMemoryRegionException)
{
@@ -260,7 +262,7 @@ namespace Ryujinx.Cpu.Jit
{
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), write: true);
- _addressSpaceMirror.Write(va, value);
+ _addressSpace.Mirror.Write(va, value);
}
catch (InvalidMemoryRegionException)
{
@@ -278,7 +280,7 @@ namespace Ryujinx.Cpu.Jit
{
SignalMemoryTracking(va, (ulong)data.Length, write: true);
- _addressSpaceMirror.Write(va, data);
+ _addressSpace.Mirror.Write(va, data);
}
catch (InvalidMemoryRegionException)
{
@@ -296,7 +298,7 @@ namespace Ryujinx.Cpu.Jit
{
AssertMapped(va, (ulong)data.Length);
- _addressSpaceMirror.Write(va, data);
+ _addressSpace.Mirror.Write(va, data);
}
catch (InvalidMemoryRegionException)
{
@@ -314,7 +316,7 @@ namespace Ryujinx.Cpu.Jit
{
SignalMemoryTracking(va, (ulong)data.Length, false);
- Span<byte> target = _addressSpaceMirror.GetSpan(va, data.Length);
+ Span<byte> target = _addressSpace.Mirror.GetSpan(va, data.Length);
bool changed = !data.SequenceEqual(target);
if (changed)
@@ -347,7 +349,7 @@ namespace Ryujinx.Cpu.Jit
AssertMapped(va, (ulong)size);
}
- return _addressSpaceMirror.GetSpan(va, size);
+ return _addressSpace.Mirror.GetSpan(va, size);
}
/// <inheritdoc/>
@@ -362,7 +364,7 @@ namespace Ryujinx.Cpu.Jit
AssertMapped(va, (ulong)size);
}
- return _addressSpaceMirror.GetWritableRegion(va, size);
+ return _addressSpace.Mirror.GetWritableRegion(va, size);
}
/// <inheritdoc/>
@@ -370,7 +372,7 @@ namespace Ryujinx.Cpu.Jit
{
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
- return ref _addressSpaceMirror.GetRef<T>(va);
+ return ref _addressSpace.Mirror.GetRef<T>(va);
}
/// <inheritdoc/>
@@ -455,6 +457,14 @@ namespace Ryujinx.Cpu.Jit
}
/// <inheritdoc/>
+ public IEnumerable<HostMemoryRange> GetHostRegions(ulong va, ulong size)
+ {
+ AssertValidAddressAndSize(va, size);
+
+ return Enumerable.Repeat(new HostMemoryRange((nuint)(ulong)_addressSpace.Mirror.GetPointer(va, size), size), 1);
+ }
+
+ /// <inheritdoc/>
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size)
{
int pages = GetPagesCount(va, (uint)size, out va);
@@ -692,7 +702,7 @@ namespace Ryujinx.Cpu.Jit
_ => MemoryPermission.None
};
- _addressSpace.Reprotect(va, size, protection, false);
+ _addressSpace.Base.Reprotect(va, size, protection, false);
}
/// <inheritdoc/>
@@ -799,7 +809,6 @@ namespace Ryujinx.Cpu.Jit
protected override void Destroy()
{
_addressSpace.Dispose();
- _addressSpaceMirror.Dispose();
_memoryEh.Dispose();
}