mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-07-22 14:47:10 +02:00
Add NCE code
This commit is contained in:
parent
a1e34041fa
commit
0970972f0d
40 changed files with 2702 additions and 40 deletions
|
@ -16,13 +16,15 @@ namespace Ryujinx.HLE.HOS
|
|||
ulong codeSize);
|
||||
}
|
||||
|
||||
class ArmProcessContext<T> : IArmProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager
|
||||
class ArmProcessContext<T> : IArmProcessContext where T : class, IVirtualMemoryManagerTracked, ICpuMemoryManager
|
||||
{
|
||||
private readonly ulong _pid;
|
||||
private readonly GpuContext _gpuContext;
|
||||
private readonly ICpuContext _cpuContext;
|
||||
private T _memoryManager;
|
||||
|
||||
public ulong ReservedSize { get; }
|
||||
|
||||
public IVirtualMemoryManager AddressSpace => _memoryManager;
|
||||
|
||||
public ulong AddressSpaceSize { get; }
|
||||
|
@ -33,7 +35,8 @@ namespace Ryujinx.HLE.HOS
|
|||
GpuContext gpuContext,
|
||||
T memoryManager,
|
||||
ulong addressSpaceSize,
|
||||
bool for64Bit)
|
||||
bool for64Bit,
|
||||
ulong reservedSize = 0UL)
|
||||
{
|
||||
if (memoryManager is IRefCounted rc)
|
||||
{
|
||||
|
@ -46,8 +49,8 @@ namespace Ryujinx.HLE.HOS
|
|||
_gpuContext = gpuContext;
|
||||
_cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit);
|
||||
_memoryManager = memoryManager;
|
||||
|
||||
AddressSpaceSize = addressSpaceSize;
|
||||
ReservedSize = reservedSize;
|
||||
}
|
||||
|
||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
||||
|
@ -78,6 +81,11 @@ namespace Ryujinx.HLE.HOS
|
|||
_cpuContext.InvalidateCacheRegion(address, size);
|
||||
}
|
||||
|
||||
public void PatchCodeForNce(ulong textAddress, ulong textSize, ulong patchRegionAddress, ulong patchRegionSize)
|
||||
{
|
||||
_cpuContext.PatchCodeForNce(textAddress, textSize, patchRegionAddress, patchRegionSize);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_memoryManager is IRefCounted rc)
|
||||
|
|
|
@ -4,6 +4,7 @@ using Ryujinx.Cpu;
|
|||
using Ryujinx.Cpu.AppleHv;
|
||||
using Ryujinx.Cpu.Jit;
|
||||
using Ryujinx.Cpu.LightningJit;
|
||||
using Ryujinx.Cpu.Nce;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
using Ryujinx.HLE.HOS.Kernel;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
|
@ -46,14 +47,31 @@ namespace Ryujinx.HLE.HOS
|
|||
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
|
||||
{
|
||||
IArmProcessContext processContext;
|
||||
AddressSpace addressSpace = null;
|
||||
|
||||
bool isArm64Host = RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
||||
|
||||
if (OperatingSystem.IsMacOS() && isArm64Host && for64Bit && context.Device.Configuration.UseHypervisor)
|
||||
{
|
||||
var cpuEngine = new HvEngine(_tickSource);
|
||||
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
var cpuEngine = new HvEngine(_tickSource);
|
||||
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!AddressSpace.TryCreate(context.Memory, addressSpaceSize, MemoryBlock.GetPageSize() == MemoryManagerHostMapped.PageSize, out addressSpace))
|
||||
{
|
||||
throw new Exception("Address space creation failed");
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu, $"NCE Base AS Address: 0x{addressSpace.Base.Pointer.ToInt64():X} Size: 0x{addressSpace.AddressSpaceSize:X}");
|
||||
|
||||
var cpuEngine = new NceEngine(_tickSource);
|
||||
var memoryManager = new MemoryManagerNative(addressSpace, context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||
processContext = new ArmProcessContext<MemoryManagerNative>(pid, cpuEngine, _gpu, memoryManager, addressSpace.AddressSpaceSize, for64Bit, memoryManager.ReservedSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -70,8 +88,6 @@ namespace Ryujinx.HLE.HOS
|
|||
? new LightningJitEngine(_tickSource)
|
||||
: new JitEngine(_tickSource);
|
||||
|
||||
AddressSpace addressSpace = null;
|
||||
|
||||
if (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe)
|
||||
{
|
||||
if (!AddressSpace.TryCreate(context.Memory, addressSpaceSize, MemoryBlock.GetPageSize() == MemoryManagerHostMapped.PageSize, out addressSpace))
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
MemoryRegion memRegion,
|
||||
ulong address,
|
||||
ulong size,
|
||||
ulong reservedSize,
|
||||
KMemoryBlockSlabManager slabManager)
|
||||
{
|
||||
if ((uint)addrSpaceType > (uint)AddressSpaceType.Addr39Bits)
|
||||
|
@ -128,6 +129,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
memRegion,
|
||||
address,
|
||||
size,
|
||||
reservedSize,
|
||||
slabManager);
|
||||
|
||||
if (result != Result.Success)
|
||||
|
@ -155,6 +157,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
MemoryRegion memRegion,
|
||||
ulong address,
|
||||
ulong size,
|
||||
ulong reservedSize,
|
||||
KMemoryBlockSlabManager slabManager)
|
||||
{
|
||||
ulong endAddr = address + size;
|
||||
|
@ -178,7 +181,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
CodeRegionStart = 0x200000;
|
||||
codeRegionSize = 0x3fe00000;
|
||||
AslrRegionStart = 0x200000;
|
||||
AslrRegionEnd = AslrRegionStart + 0xffe00000;
|
||||
AslrRegionEnd = 0x100000000;
|
||||
stackAndTlsIoStart = 0x200000;
|
||||
stackAndTlsIoEnd = 0x40000000;
|
||||
break;
|
||||
|
@ -191,7 +194,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
CodeRegionStart = 0x8000000;
|
||||
codeRegionSize = 0x78000000;
|
||||
AslrRegionStart = 0x8000000;
|
||||
AslrRegionEnd = AslrRegionStart + 0xff8000000;
|
||||
AslrRegionEnd = 0x1000000000;
|
||||
stackAndTlsIoStart = 0x8000000;
|
||||
stackAndTlsIoEnd = 0x80000000;
|
||||
break;
|
||||
|
@ -204,7 +207,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
CodeRegionStart = 0x200000;
|
||||
codeRegionSize = 0x3fe00000;
|
||||
AslrRegionStart = 0x200000;
|
||||
AslrRegionEnd = AslrRegionStart + 0xffe00000;
|
||||
AslrRegionEnd = 0x100000000;
|
||||
stackAndTlsIoStart = 0x200000;
|
||||
stackAndTlsIoEnd = 0x40000000;
|
||||
break;
|
||||
|
@ -222,8 +225,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
codeRegionSize = BitUtils.AlignUp<ulong>(endAddr, RegionAlignment) - CodeRegionStart;
|
||||
stackAndTlsIoStart = 0;
|
||||
stackAndTlsIoEnd = 0;
|
||||
AslrRegionStart = 0x8000000;
|
||||
addrSpaceEnd = 1UL << addressSpaceWidth;
|
||||
AslrRegionStart = reservedSize + 0x8000000;
|
||||
addrSpaceEnd = reservedSize + (1UL << addressSpaceWidth);
|
||||
AslrRegionEnd = addrSpaceEnd;
|
||||
}
|
||||
else
|
||||
|
@ -234,8 +237,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
|||
tlsIoRegion.Size = 0x1000000000;
|
||||
CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment);
|
||||
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
||||
AslrRegionStart = 0x8000000;
|
||||
AslrRegionEnd = AslrRegionStart + 0x7ff8000000;
|
||||
AslrRegionStart = reservedSize + 0x8000000;
|
||||
AslrRegionEnd = 0x8000000000;
|
||||
stackAndTlsIoStart = 0;
|
||||
stackAndTlsIoEnd = 0;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
interface IProcessContext : IDisposable
|
||||
{
|
||||
IVirtualMemoryManager AddressSpace { get; }
|
||||
ulong ReservedSize { get; }
|
||||
|
||||
ulong AddressSpaceSize { get; }
|
||||
|
||||
IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks);
|
||||
void Execute(IExecutionContext context, ulong codeAddress);
|
||||
void InvalidateCacheRegion(ulong address, ulong size);
|
||||
void PatchCodeForNce(ulong textAddress, ulong textSize, ulong patchRegionAddress, ulong patchRegionSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
|
||||
|
||||
ulong codeAddress = creationInfo.CodeAddress;
|
||||
ulong codeAddress = creationInfo.CodeAddress + Context.ReservedSize;
|
||||
|
||||
ulong codeSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
||||
|
||||
|
@ -154,6 +154,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
memRegion,
|
||||
codeAddress,
|
||||
codeSize,
|
||||
Context.ReservedSize,
|
||||
slabManager);
|
||||
|
||||
if (result != Result.Success)
|
||||
|
@ -189,7 +190,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
KResourceLimit resourceLimit,
|
||||
MemoryRegion memRegion,
|
||||
IProcessContextFactory contextFactory,
|
||||
ThreadStart customThreadStart = null)
|
||||
ThreadStart customThreadStart = null,
|
||||
ulong entrypointOffset = 0UL)
|
||||
{
|
||||
ResourceLimit = resourceLimit;
|
||||
_memRegion = memRegion;
|
||||
|
@ -247,7 +249,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
|
||||
|
||||
ulong codeAddress = creationInfo.CodeAddress;
|
||||
ulong codeAddress = creationInfo.CodeAddress + Context.ReservedSize;
|
||||
|
||||
ulong codeSize = codePagesCount * KPageTableBase.PageSize;
|
||||
|
||||
|
@ -258,6 +260,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
memRegion,
|
||||
codeAddress,
|
||||
codeSize,
|
||||
Context.ReservedSize,
|
||||
slabManager);
|
||||
|
||||
if (result != Result.Success)
|
||||
|
@ -303,6 +306,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
CleanUpForError();
|
||||
}
|
||||
|
||||
_entrypoint += entrypointOffset;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -347,7 +352,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
Flags = creationInfo.Flags;
|
||||
TitleId = creationInfo.TitleId;
|
||||
_entrypoint = creationInfo.CodeAddress;
|
||||
_entrypoint = creationInfo.CodeAddress + Context.ReservedSize;
|
||||
_imageSize = (ulong)creationInfo.CodePagesCount * KPageTableBase.PageSize;
|
||||
|
||||
switch (Flags & ProcessCreationFlags.AddressSpaceMask)
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
class ProcessContext : IProcessContext
|
||||
{
|
||||
public IVirtualMemoryManager AddressSpace { get; }
|
||||
public ulong ReservedSize => 0UL;
|
||||
|
||||
public ulong AddressSpaceSize { get; }
|
||||
|
||||
|
@ -30,6 +31,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
{
|
||||
}
|
||||
|
||||
public void PatchCodeForNce(ulong textAddress, ulong textSize, ulong patchRegionAddress, ulong patchRegionSize)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -133,6 +133,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
return resultCode;
|
||||
}
|
||||
|
||||
private const int ReservedPatchSize = 0x100000;
|
||||
|
||||
public static bool LoadKip(KernelContext context, KipExecutable kip)
|
||||
{
|
||||
uint endOffset = kip.DataOffset + (uint)kip.Data.Length;
|
||||
|
@ -197,7 +199,9 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
return false;
|
||||
}
|
||||
|
||||
result = LoadIntoMemory(process, kip, codeBaseAddress);
|
||||
// TODO: Support NCE of KIPs too.
|
||||
result = LoadIntoMemory(process, kip, codeBaseAddress, 0UL);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||
|
@ -257,6 +261,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
_ => "",
|
||||
}).ToUpper());
|
||||
|
||||
ulong[] nsoPatch = new ulong[executables.Length];
|
||||
ulong[] nsoBase = new ulong[executables.Length];
|
||||
|
||||
for (int index = 0; index < executables.Length; index++)
|
||||
|
@ -281,6 +286,10 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
|
||||
nsoSize = BitUtils.AlignUp<uint>(nsoSize, KPageTableBase.PageSize);
|
||||
|
||||
nsoPatch[index] = codeStart + codeSize;
|
||||
|
||||
codeSize += ReservedPatchSize;
|
||||
|
||||
nsoBase[index] = codeStart + codeSize;
|
||||
|
||||
codeSize += nsoSize;
|
||||
|
@ -304,7 +313,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
programId,
|
||||
codeStart,
|
||||
codePagesCount,
|
||||
(ProcessCreationFlags)meta.Flags | ProcessCreationFlags.IsApplication,
|
||||
(ProcessCreationFlags)meta.Flags,
|
||||
0,
|
||||
personalMmHeapPagesCount);
|
||||
|
||||
|
@ -381,7 +390,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
MemoryMarshal.Cast<byte, uint>(npdm.KernelCapabilityData),
|
||||
resourceLimit,
|
||||
memoryRegion,
|
||||
processContextFactory);
|
||||
processContextFactory,
|
||||
entrypointOffset: ReservedPatchSize);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
|
@ -392,9 +402,13 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
|
||||
for (int index = 0; index < executables.Length; index++)
|
||||
{
|
||||
Logger.Info?.Print(LogClass.Loader, $"Loading image {index} at 0x{nsoBase[index]:x16}...");
|
||||
ulong nsoPatchAddress = process.Context.ReservedSize + nsoPatch[index];
|
||||
ulong nsoBaseAddress = process.Context.ReservedSize + nsoBase[index];
|
||||
|
||||
Logger.Info?.Print(LogClass.Loader, $"Loading image {index} at 0x{nsoBaseAddress:x16}...");
|
||||
|
||||
result = LoadIntoMemory(process, executables[index], nsoBaseAddress, nsoPatchAddress);
|
||||
|
||||
result = LoadIntoMemory(process, executables[index], nsoBase[index]);
|
||||
if (result != Result.Success)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");
|
||||
|
@ -433,7 +447,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
device.System.State.DesiredTitleLanguage);
|
||||
}
|
||||
|
||||
public static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress)
|
||||
private static Result LoadIntoMemory(KProcess process, IExecutable image, ulong baseAddress, ulong patchAddress)
|
||||
{
|
||||
ulong textStart = baseAddress + image.TextOffset;
|
||||
ulong roStart = baseAddress + image.RoOffset;
|
||||
|
@ -453,6 +467,8 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
|
||||
process.CpuMemory.Fill(bssStart, image.BssSize, 0);
|
||||
|
||||
process.Context.PatchCodeForNce(textStart, (ulong)image.Text.Length, patchAddress, ReservedPatchSize);
|
||||
|
||||
Result SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
|
||||
{
|
||||
if (size == 0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue