Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
10
src/ARMeilleure/Memory/IJitMemoryAllocator.cs
Normal file
10
src/ARMeilleure/Memory/IJitMemoryAllocator.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace ARMeilleure.Memory
|
||||
{
|
||||
public interface IJitMemoryAllocator
|
||||
{
|
||||
IJitMemoryBlock Allocate(ulong size);
|
||||
IJitMemoryBlock Reserve(ulong size);
|
||||
|
||||
ulong GetPageSize();
|
||||
}
|
||||
}
|
14
src/ARMeilleure/Memory/IJitMemoryBlock.cs
Normal file
14
src/ARMeilleure/Memory/IJitMemoryBlock.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
public interface IJitMemoryBlock : IDisposable
|
||||
{
|
||||
IntPtr Pointer { get; }
|
||||
|
||||
bool Commit(ulong offset, ulong size);
|
||||
|
||||
void MapAsRx(ulong offset, ulong size);
|
||||
void MapAsRwx(ulong offset, ulong size);
|
||||
}
|
||||
}
|
77
src/ARMeilleure/Memory/IMemoryManager.cs
Normal file
77
src/ARMeilleure/Memory/IMemoryManager.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
public interface IMemoryManager
|
||||
{
|
||||
int AddressSpaceBits { get; }
|
||||
|
||||
IntPtr PageTablePointer { get; }
|
||||
|
||||
MemoryManagerType Type { get; }
|
||||
|
||||
event Action<ulong, ulong> UnmapEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from CPU mapped memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data being read</typeparam>
|
||||
/// <param name="va">Virtual address of the data in memory</param>
|
||||
/// <returns>The data</returns>
|
||||
T Read<T>(ulong va) where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from CPU mapped memory, with read tracking
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data being read</typeparam>
|
||||
/// <param name="va">Virtual address of the data in memory</param>
|
||||
/// <returns>The data</returns>
|
||||
T ReadTracked<T>(ulong va) where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Writes data to CPU mapped memory.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the data being written</typeparam>
|
||||
/// <param name="va">Virtual address to write the data into</param>
|
||||
/// <param name="value">Data to be written</param>
|
||||
void Write<T>(ulong va, T value) where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only span of data from CPU mapped memory.
|
||||
/// </summary>
|
||||
/// <param name="va">Virtual address of the data</param>
|
||||
/// <param name="size">Size of the data</param>
|
||||
/// <param name="tracked">True if read tracking is triggered on the span</param>
|
||||
/// <returns>A read-only span of the data</returns>
|
||||
ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference for the given type at the specified virtual memory address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The data must be located at a contiguous memory region.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">Type of the data to get the reference</typeparam>
|
||||
/// <param name="va">Virtual address of the data</param>
|
||||
/// <returns>A reference to the data in memory</returns>
|
||||
ref T GetRef<T>(ulong va) where T : unmanaged;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the page at a given CPU virtual address is mapped.
|
||||
/// </summary>
|
||||
/// <param name="va">Virtual address to check</param>
|
||||
/// <returns>True if the address is mapped, false otherwise</returns>
|
||||
bool IsMapped(ulong va);
|
||||
|
||||
/// <summary>
|
||||
/// Alerts the memory tracking that a given region has been read from or written to.
|
||||
/// This should be called before read/write is performed.
|
||||
/// </summary>
|
||||
/// <param name="va">Virtual address of the region</param>
|
||||
/// <param name="size">Size of the region</param>
|
||||
/// <param name="write">True if the region was written, false if read</param>
|
||||
/// <param name="precise">True if the access is precise, false otherwise</param>
|
||||
/// <param name="exemptId">Optional ID of the handles that should not be signalled</param>
|
||||
void SignalMemoryTracking(ulong va, ulong size, bool write, bool precise = false, int? exemptId = null);
|
||||
}
|
||||
}
|
23
src/ARMeilleure/Memory/InvalidAccessException.cs
Normal file
23
src/ARMeilleure/Memory/InvalidAccessException.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
class InvalidAccessException : Exception
|
||||
{
|
||||
public InvalidAccessException()
|
||||
{
|
||||
}
|
||||
|
||||
public InvalidAccessException(ulong address) : base($"Invalid memory access at virtual address 0x{address:X16}.")
|
||||
{
|
||||
}
|
||||
|
||||
public InvalidAccessException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public InvalidAccessException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
41
src/ARMeilleure/Memory/MemoryManagerType.cs
Normal file
41
src/ARMeilleure/Memory/MemoryManagerType.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
namespace ARMeilleure.Memory
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the type of a memory manager and the method it uses for memory mapping
|
||||
/// and address translation. This controls the code generated for memory accesses on the JIT.
|
||||
/// </summary>
|
||||
public enum MemoryManagerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Complete software MMU implementation, the read/write methods are always called,
|
||||
/// without any attempt to perform faster memory access.
|
||||
/// </summary>
|
||||
SoftwareMmu,
|
||||
|
||||
/// <summary>
|
||||
/// High level implementation using a software flat page table for address translation,
|
||||
/// used to speed up address translation if possible without calling the read/write methods.
|
||||
/// </summary>
|
||||
SoftwarePageTable,
|
||||
|
||||
/// <summary>
|
||||
/// High level implementation with mappings managed by the host OS, effectively using hardware
|
||||
/// page tables. No address translation is performed in software and the memory is just accessed directly.
|
||||
/// </summary>
|
||||
HostMapped,
|
||||
|
||||
/// <summary>
|
||||
/// Same as the host mapped memory manager type, but without masking the address within the address space.
|
||||
/// Allows invalid access from JIT code to the rest of the program, but is faster.
|
||||
/// </summary>
|
||||
HostMappedUnsafe
|
||||
}
|
||||
|
||||
static class MemoryManagerTypeExtensions
|
||||
{
|
||||
public static bool IsHostMapped(this MemoryManagerType type)
|
||||
{
|
||||
return type == MemoryManagerType.HostMapped || type == MemoryManagerType.HostMappedUnsafe;
|
||||
}
|
||||
}
|
||||
}
|
58
src/ARMeilleure/Memory/ReservedRegion.cs
Normal file
58
src/ARMeilleure/Memory/ReservedRegion.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
|
||||
namespace ARMeilleure.Memory
|
||||
{
|
||||
class ReservedRegion
|
||||
{
|
||||
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.
|
||||
|
||||
public IJitMemoryBlock Block { get; }
|
||||
|
||||
public IntPtr Pointer => Block.Pointer;
|
||||
|
||||
private readonly ulong _maxSize;
|
||||
private readonly ulong _sizeGranularity;
|
||||
private ulong _currentSize;
|
||||
|
||||
public ReservedRegion(IJitMemoryAllocator allocator, ulong maxSize, ulong granularity = 0)
|
||||
{
|
||||
if (granularity == 0)
|
||||
{
|
||||
granularity = DefaultGranularity;
|
||||
}
|
||||
|
||||
Block = allocator.Reserve(maxSize);
|
||||
_maxSize = maxSize;
|
||||
_sizeGranularity = granularity;
|
||||
_currentSize = 0;
|
||||
}
|
||||
|
||||
public void ExpandIfNeeded(ulong desiredSize)
|
||||
{
|
||||
if (desiredSize > _maxSize)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
if (desiredSize > _currentSize)
|
||||
{
|
||||
// Lock, and then check again. We only want to commit once.
|
||||
lock (this)
|
||||
{
|
||||
if (desiredSize >= _currentSize)
|
||||
{
|
||||
ulong overflowBytes = desiredSize - _currentSize;
|
||||
ulong moreToCommit = (((_sizeGranularity - 1) + overflowBytes) / _sizeGranularity) * _sizeGranularity; // Round up.
|
||||
Block.Commit(_currentSize, moreToCommit);
|
||||
_currentSize += moreToCommit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Block.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue