IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel (#1458)

* IPC refactor part 2: Use ReplyAndReceive on HLE services and remove special handling from kernel

* Fix for applet transfer memory + some nits

* Keep handles if possible to avoid server handle table exhaustion

* Fix IPC ZeroFill bug

* am: Correctly implement CreateManagedDisplayLayer and implement CreateManagedDisplaySeparableLayer

CreateManagedDisplaySeparableLayer is requires since 10.x+ when appletResourceUserId != 0

* Make it exit properly

* Make ServiceNotImplementedException show the full message again

* Allow yielding execution to avoid starving other threads

* Only wait if active

* Merge IVirtualMemoryManager and IAddressSpaceManager

* Fix Ro loading data from the wrong process

Co-authored-by: Thog <me@thog.eu>
This commit is contained in:
gdkchan 2020-12-01 20:23:43 -03:00 committed by GitHub
parent 461c24092a
commit cf6cd71488
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 2356 additions and 1088 deletions

View file

@ -1,7 +1,7 @@
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Diagnostics.Demangler;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.Loaders.Elf;
using Ryujinx.Memory;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -224,7 +224,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
break;
}
if (info.State == MemoryState.CodeStatic && info.Permission == MemoryPermission.ReadAndExecute)
if (info.State == MemoryState.CodeStatic && info.Permission == KMemoryPermission.ReadAndExecute)
{
LoadMod0Symbols(_owner.CpuMemory, info.Address);
}
@ -235,7 +235,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
}
private void LoadMod0Symbols(MemoryManager memory, ulong textOffset)
private void LoadMod0Symbols(IVirtualMemoryManager memory, ulong textOffset)
{
ulong mod0Offset = textOffset + memory.Read<uint>(textOffset + 4);
@ -319,7 +319,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
}
private ElfSymbol GetSymbol64(MemoryManager memory, ulong address, ulong strTblAddr)
private ElfSymbol GetSymbol64(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
{
ElfSymbol64 sym = memory.Read<ElfSymbol64>(address);
@ -335,7 +335,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return new ElfSymbol(name, sym.Info, sym.Other, sym.SectionIndex, sym.ValueAddress, sym.Size);
}
private ElfSymbol GetSymbol32(MemoryManager memory, ulong address, ulong strTblAddr)
private ElfSymbol GetSymbol32(IVirtualMemoryManager memory, ulong address, ulong strTblAddr)
{
ElfSymbol32 sym = memory.Read<ElfSymbol32>(address);

View file

@ -0,0 +1,13 @@
using ARMeilleure.State;
using Ryujinx.Memory;
using System;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
interface IProcessContext : IDisposable
{
IVirtualMemoryManager AddressSpace { get; }
void Execute(ExecutionContext context, ulong codeAddress);
}
}

View file

@ -0,0 +1,10 @@
using Ryujinx.Cpu;
using Ryujinx.Memory;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
interface IProcessContextFactory
{
IProcessContext Create(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler);
}
}

View file

@ -6,6 +6,7 @@ using Ryujinx.HLE.Exceptions;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
@ -15,13 +16,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
class KProcess : KSynchronizationObject
{
public const int KernelVersionMajor = 10;
public const int KernelVersionMinor = 4;
public const int KernelVersionMajor = 10;
public const int KernelVersionMinor = 4;
public const int KernelVersionRevision = 0;
public const int KernelVersionPacked =
(KernelVersionMajor << 19) |
(KernelVersionMinor << 15) |
(KernelVersionMajor << 19) |
(KernelVersionMinor << 15) |
(KernelVersionRevision << 0);
public KMemoryManager MemoryManager { get; private set; }
@ -47,27 +48,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public long[] RandomEntropy { get; private set; }
private bool _signaled;
private bool _useSystemMemBlocks;
public string Name { get; private set; }
private int _threadCount;
public int MmuFlags { get; private set; }
public ProcessCreationFlags Flags { get; private set; }
private MemoryRegion _memRegion;
public KProcessCapabilities Capabilities { get; private set; }
public ulong TitleId { get; private set; }
public long Pid { get; private set; }
public long Pid { get; private set; }
private long _creationTimestamp;
private long _creationTimestamp;
private ulong _entrypoint;
private ThreadStart _customThreadStart;
private ulong _imageSize;
private ulong _mainThreadStackSize;
private ulong _memoryUsageCapacity;
private int _version;
private int _version;
public KHandleTable HandleTable { get; private set; }
@ -77,14 +78,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public bool IsPaused { get; private set; }
public MemoryManager CpuMemory { get; private set; }
public CpuContext CpuContext { get; private set; }
private IProcessContextFactory _contextFactory;
public IProcessContext Context { get; private set; }
public IVirtualMemoryManager CpuMemory => Context.AddressSpace;
public HleProcessDebugger Debugger { get; private set; }
public KProcess(KernelContext context) : base(context)
{
_processLock = new object();
_processLock = new object();
_threadingLock = new object();
AddressArbiter = new KAddressArbiter(context);
@ -96,6 +98,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
RandomEntropy = new long[KScheduler.CpuCoresCount];
// TODO: Remove once we no longer need to initialize it externally.
HandleTable = new KHandleTable(context);
_threads = new LinkedList<KThread>();
Debugger = new HleProcessDebugger(this);
@ -103,25 +108,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KernelResult InitializeKip(
ProcessCreationInfo creationInfo,
int[] caps,
KPageList pageList,
KResourceLimit resourceLimit,
MemoryRegion memRegion)
ReadOnlySpan<int> capabilities,
KPageList pageList,
KResourceLimit resourceLimit,
MemoryRegion memRegion,
IProcessContextFactory contextFactory)
{
ResourceLimit = resourceLimit;
_memRegion = memRegion;
_memRegion = memRegion;
_contextFactory = contextFactory ?? new ProcessContextFactory();
AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
InitializeMemoryManager(addrSpaceType, memRegion);
InitializeMemoryManager(creationInfo.Flags);
bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
ulong codeAddress = creationInfo.CodeAddress;
ulong codeSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
KMemoryBlockAllocator memoryBlockAllocator = (MmuFlags & 0x40) != 0
KMemoryBlockAllocator memoryBlockAllocator = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication)
? KernelContext.LargeMemoryBlockAllocator
: KernelContext.SmallMemoryBlockAllocator;
@ -139,7 +146,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result;
}
if (!ValidateCodeAddressAndSize(codeAddress, codeSize))
if (!MemoryManager.CanContain(codeAddress, codeSize, MemoryState.CodeStatic))
{
return KernelResult.InvalidMemRange;
}
@ -148,14 +155,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
codeAddress,
pageList,
MemoryState.CodeStatic,
MemoryPermission.None);
KMemoryPermission.None);
if (result != KernelResult.Success)
{
return result;
}
result = Capabilities.InitializeForKernel(caps, MemoryManager);
result = Capabilities.InitializeForKernel(capabilities, MemoryManager);
if (result != KernelResult.Success)
{
@ -176,14 +183,17 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KernelResult Initialize(
ProcessCreationInfo creationInfo,
int[] caps,
KResourceLimit resourceLimit,
MemoryRegion memRegion)
ReadOnlySpan<int> capabilities,
KResourceLimit resourceLimit,
MemoryRegion memRegion,
IProcessContextFactory contextFactory,
ThreadStart customThreadStart = null)
{
ResourceLimit = resourceLimit;
_memRegion = memRegion;
_memRegion = memRegion;
_contextFactory = contextFactory ?? new ProcessContextFactory();
ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.PersonalMmHeapPagesCount, memRegion);
ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.SystemResourcePagesCount, memRegion);
ulong codePagesCount = (ulong)creationInfo.CodePagesCount;
@ -205,7 +215,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
}
PersonalMmHeapPagesCount = (ulong)creationInfo.PersonalMmHeapPagesCount;
PersonalMmHeapPagesCount = (ulong)creationInfo.SystemResourcePagesCount;
KMemoryBlockAllocator memoryBlockAllocator;
@ -215,16 +225,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
else
{
memoryBlockAllocator = (MmuFlags & 0x40) != 0
memoryBlockAllocator = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication)
? KernelContext.LargeMemoryBlockAllocator
: KernelContext.SmallMemoryBlockAllocator;
}
AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);
AddressSpaceType addrSpaceType = (AddressSpaceType)((int)(creationInfo.Flags & ProcessCreationFlags.AddressSpaceMask) >> (int)ProcessCreationFlags.AddressSpaceShift);
InitializeMemoryManager(addrSpaceType, memRegion);
InitializeMemoryManager(creationInfo.Flags);
bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;
bool aslrEnabled = creationInfo.Flags.HasFlag(ProcessCreationFlags.EnableAslr);
ulong codeAddress = creationInfo.CodeAddress;
@ -246,7 +256,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result;
}
if (!ValidateCodeAddressAndSize(codeAddress, codeSize))
if (!MemoryManager.CanContain(codeAddress, codeSize, MemoryState.CodeStatic))
{
CleanUpForError();
@ -257,7 +267,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
codeAddress,
codePagesCount,
MemoryState.CodeStatic,
MemoryPermission.None);
KMemoryPermission.None);
if (result != KernelResult.Success)
{
@ -266,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result;
}
result = Capabilities.InitializeForUser(caps, MemoryManager);
result = Capabilities.InitializeForUser(capabilities, MemoryManager);
if (result != KernelResult.Success)
{
@ -289,57 +299,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
CleanUpForError();
}
_customThreadStart = customThreadStart;
return result;
}
private bool ValidateCodeAddressAndSize(ulong address, ulong size)
{
ulong codeRegionStart;
ulong codeRegionSize;
switch (MemoryManager.AddrSpaceWidth)
{
case 32:
codeRegionStart = 0x200000;
codeRegionSize = 0x3fe00000;
break;
case 36:
codeRegionStart = 0x8000000;
codeRegionSize = 0x78000000;
break;
case 39:
codeRegionStart = 0x8000000;
codeRegionSize = 0x7ff8000000;
break;
default: throw new InvalidOperationException("Invalid address space width on memory manager.");
}
ulong endAddr = address + size;
ulong codeRegionEnd = codeRegionStart + codeRegionSize;
if (endAddr <= address ||
endAddr - 1 > codeRegionEnd - 1)
{
return false;
}
if (MemoryManager.InsideHeapRegion (address, size) ||
MemoryManager.InsideAliasRegion(address, size))
{
return false;
}
return true;
}
private KernelResult ParseProcessInfo(ProcessCreationInfo creationInfo)
{
// Ensure that the current kernel version is equal or above to the minimum required.
uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19;
uint requiredKernelVersionMajor = (uint)Capabilities.KernelReleaseVersion >> 19;
uint requiredKernelVersionMinor = ((uint)Capabilities.KernelReleaseVersion >> 15) & 0xf;
if (KernelContext.EnableVersionChecks)
@ -377,31 +345,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
_creationTimestamp = PerformanceCounter.ElapsedMilliseconds;
MmuFlags = creationInfo.MmuFlags;
_version = creationInfo.Version;
TitleId = creationInfo.TitleId;
Flags = creationInfo.Flags;
_version = creationInfo.Version;
TitleId = creationInfo.TitleId;
_entrypoint = creationInfo.CodeAddress;
_imageSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
_imageSize = (ulong)creationInfo.CodePagesCount * KMemoryManager.PageSize;
_useSystemMemBlocks = ((MmuFlags >> 6) & 1) != 0;
switch ((AddressSpaceType)((MmuFlags >> 1) & 7))
switch (Flags & ProcessCreationFlags.AddressSpaceMask)
{
case AddressSpaceType.Addr32Bits:
case AddressSpaceType.Addr36Bits:
case AddressSpaceType.Addr39Bits:
case ProcessCreationFlags.AddressSpace32Bit:
case ProcessCreationFlags.AddressSpace64BitDeprecated:
case ProcessCreationFlags.AddressSpace64Bit:
_memoryUsageCapacity = MemoryManager.HeapRegionEnd -
MemoryManager.HeapRegionStart;
break;
case AddressSpaceType.Addr32BitsNoMap:
case ProcessCreationFlags.AddressSpace32BitWithoutAlias:
_memoryUsageCapacity = MemoryManager.HeapRegionEnd -
MemoryManager.HeapRegionStart +
MemoryManager.AliasRegionEnd -
MemoryManager.AliasRegionStart;
break;
default: throw new InvalidOperationException($"Invalid MMU flags value 0x{MmuFlags:x2}.");
default: throw new InvalidOperationException($"Invalid MMU flags value 0x{Flags:x2}.");
}
GenerateRandomEntropy();
@ -469,7 +435,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
ulong regionStart = MemoryManager.TlsIoRegionStart;
ulong regionSize = MemoryManager.TlsIoRegionEnd - regionStart;
ulong regionSize = MemoryManager.TlsIoRegionEnd - regionStart;
ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
@ -481,7 +447,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionStart,
regionPagesCount,
MemoryState.ThreadLocal,
MemoryPermission.ReadAndWrite,
KMemoryPermission.ReadAndWrite,
out ulong tlsPageVa);
if (result != KernelResult.Success)
@ -506,7 +472,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
KernelResult result = KernelResult.Success;
KTlsPageInfo pageInfo = null;
KTlsPageInfo pageInfo;
if (_fullTlsPages.TryGetValue(tlsPageAddr, out pageInfo))
{
@ -594,8 +560,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
// Check if the needed size for the code and the stack will fit on the
// memory usage capacity of this Process. Also check for possible overflow
// on the above addition.
if (neededSize > _memoryUsageCapacity ||
neededSize < stackSizeRounded)
if (neededSize > _memoryUsageCapacity || neededSize < stackSizeRounded)
{
threadResourceLimit?.Release(LimitableResource.Thread, 1);
@ -646,7 +611,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
ulong stackPagesCount = stackSizeRounded / KMemoryManager.PageSize;
ulong regionStart = MemoryManager.StackRegionStart;
ulong regionSize = MemoryManager.StackRegionEnd - regionStart;
ulong regionSize = MemoryManager.StackRegionEnd - regionStart;
ulong regionPagesCount = regionSize / KMemoryManager.PageSize;
@ -658,7 +623,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
regionStart,
regionPagesCount,
MemoryState.Stack,
MemoryPermission.ReadAndWrite,
KMemoryPermission.ReadAndWrite,
out ulong stackBottom);
if (result != KernelResult.Success)
@ -703,7 +668,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
stackTop,
mainThreadPriority,
DefaultCpuCore,
this);
this,
ThreadType.User,
_customThreadStart);
if (result != KernelResult.Success)
{
@ -730,20 +697,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
SetState(newState);
// TODO: We can't call KThread.Start from a non-guest thread.
// We will need to make some changes to allow the creation of
// dummy threads that will be used to initialize the current
// thread on KCoreContext so that GetCurrentThread doesn't fail.
/* Result = MainThread.Start();
result = mainThread.Start();
if (Result != KernelResult.Success)
if (result != KernelResult.Success)
{
SetState(OldState);
SetState(oldState);
CleanUpForError();
} */
mainThread.Reschedule(ThreadSchedState.Running);
}
if (result == KernelResult.Success)
{
@ -760,7 +721,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
if (State != newState)
{
State = newState;
State = newState;
_signaled = true;
Signal();
@ -769,23 +730,23 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
public KernelResult InitializeThread(
KThread thread,
ulong entrypoint,
ulong argsPtr,
ulong stackTop,
int priority,
int cpuCore)
ulong entrypoint,
ulong argsPtr,
ulong stackTop,
int priority,
int cpuCore)
{
lock (_processLock)
{
return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this);
return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, null);
}
}
public void SubscribeThreadEventHandlers(ARMeilleure.State.ExecutionContext context)
{
context.Interrupt += InterruptHandler;
context.Interrupt += InterruptHandler;
context.SupervisorCall += KernelContext.SyscallHandler.SvcCall;
context.Undefined += UndefinedInstructionHandler;
context.Undefined += UndefinedInstructionHandler;
}
private void InterruptHandler(object sender, EventArgs e)
@ -910,8 +871,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
if (State >= ProcessState.Started)
{
if (State == ProcessState.Started ||
State == ProcessState.Crashed ||
if (State == ProcessState.Started ||
State == ProcessState.Crashed ||
State == ProcessState.Attached ||
State == ProcessState.DebugSuspended)
{
@ -1072,23 +1033,25 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result;
}
private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion)
private void InitializeMemoryManager(ProcessCreationFlags flags)
{
int addrSpaceBits = addrSpaceType switch
int addrSpaceBits = (flags & ProcessCreationFlags.AddressSpaceMask) switch
{
AddressSpaceType.Addr32Bits => 32,
AddressSpaceType.Addr36Bits => 36,
AddressSpaceType.Addr32BitsNoMap => 32,
AddressSpaceType.Addr39Bits => 39,
_ => throw new ArgumentException(nameof(addrSpaceType))
ProcessCreationFlags.AddressSpace32Bit => 32,
ProcessCreationFlags.AddressSpace64BitDeprecated => 36,
ProcessCreationFlags.AddressSpace32BitWithoutAlias => 32,
ProcessCreationFlags.AddressSpace64Bit => 39,
_ => 39
};
CpuMemory = new MemoryManager(KernelContext.Memory, 1UL << addrSpaceBits, InvalidAccessHandler);
CpuContext = new CpuContext(CpuMemory);
Context = _contextFactory.Create(KernelContext.Memory, 1UL << addrSpaceBits, InvalidAccessHandler);
// TODO: This should eventually be removed.
// The GPU shouldn't depend on the CPU memory manager at all.
KernelContext.Device.Gpu.SetVmm(CpuMemory);
if (flags.HasFlag(ProcessCreationFlags.IsApplication))
{
KernelContext.Device.Gpu.SetVmm((MemoryManager)CpuMemory);
}
MemoryManager = new KMemoryManager(KernelContext, CpuMemory);
}
@ -1109,9 +1072,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
throw new UndefinedInstructionException(e.Address, e.OpCode);
}
protected override void Destroy()
{
CpuMemory.Dispose();
}
protected override void Destroy() => Context.Dispose();
}
}

View file

@ -2,6 +2,7 @@ using Ryujinx.Common;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Threading;
using System;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
@ -24,29 +25,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
IrqAccessMask = new byte[0x80];
}
public KernelResult InitializeForKernel(int[] caps, KMemoryManager memoryManager)
public KernelResult InitializeForKernel(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
{
AllowedCpuCoresMask = 0xf;
AllowedThreadPriosMask = -1;
DebuggingFlags &= ~3;
KernelReleaseVersion = KProcess.KernelVersionPacked;
return Parse(caps, memoryManager);
return Parse(capabilities, memoryManager);
}
public KernelResult InitializeForUser(int[] caps, KMemoryManager memoryManager)
public KernelResult InitializeForUser(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
{
return Parse(caps, memoryManager);
return Parse(capabilities, memoryManager);
}
private KernelResult Parse(int[] caps, KMemoryManager memoryManager)
private KernelResult Parse(ReadOnlySpan<int> capabilities, KMemoryManager memoryManager)
{
int mask0 = 0;
int mask1 = 0;
for (int index = 0; index < caps.Length; index++)
for (int index = 0; index < capabilities.Length; index++)
{
int cap = caps[index];
int cap = capabilities[index];
if (((cap + 1) & ~cap) != 0x40)
{
@ -59,14 +60,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
}
else
{
if ((uint)index + 1 >= caps.Length)
if ((uint)index + 1 >= capabilities.Length)
{
return KernelResult.InvalidCombination;
}
int prevCap = cap;
cap = caps[++index];
cap = capabilities[++index];
if (((cap + 1) & ~cap) != 0x40)
{
@ -91,9 +92,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return KernelResult.InvalidAddress;
}
MemoryPermission perm = (prevCap >> 31) != 0
? MemoryPermission.Read
: MemoryPermission.ReadAndWrite;
KMemoryPermission perm = (prevCap >> 31) != 0
? KMemoryPermission.Read
: KMemoryPermission.ReadAndWrite;
KernelResult result;
@ -216,7 +217,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
long address = ((long)(uint)cap << 4) & 0xffffff000;
memoryManager.MapIoMemory(address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite);
memoryManager.MapIoMemory(address, KMemoryManager.PageSize, KMemoryPermission.ReadAndWrite);
break;
}

View file

@ -0,0 +1,25 @@
using ARMeilleure.State;
using Ryujinx.Memory;
using System;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
class ProcessContext : IProcessContext
{
public IVirtualMemoryManager AddressSpace { get; }
public ProcessContext(IVirtualMemoryManager asManager)
{
AddressSpace = asManager;
}
public void Execute(ExecutionContext context, ulong codeAddress)
{
throw new NotSupportedException();
}
public void Dispose()
{
}
}
}

View file

@ -0,0 +1,13 @@
using Ryujinx.Cpu;
using Ryujinx.Memory;
namespace Ryujinx.HLE.HOS.Kernel.Process
{
class ProcessContextFactory : IProcessContextFactory
{
public IProcessContext Create(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler)
{
return new ProcessContext(new AddressSpaceManager(backingMemory, addressSpaceSize));
}
}
}

View file

@ -0,0 +1,38 @@
namespace Ryujinx.HLE.HOS.Kernel.Process
{
enum ProcessCreationFlags
{
Is64Bit = 1 << 0,
AddressSpaceShift = 1,
AddressSpace32Bit = 0 << AddressSpaceShift,
AddressSpace64BitDeprecated = 1 << AddressSpaceShift,
AddressSpace32BitWithoutAlias = 2 << AddressSpaceShift,
AddressSpace64Bit = 3 << AddressSpaceShift,
AddressSpaceMask = 7 << AddressSpaceShift,
EnableDebug = 1 << 4,
EnableAslr = 1 << 5,
IsApplication = 1 << 6,
DeprecatedUseSecureMemory = 1 << 7,
PoolPartitionShift = 7,
PoolPartitionApplication = 0 << PoolPartitionShift,
PoolPartitionApplet = 1 << PoolPartitionShift,
PoolPartitionSystem = 2 << PoolPartitionShift,
PoolPartitionSystemNonSecure = 3 << PoolPartitionShift,
PoolPartitionMask = 0xf << PoolPartitionShift,
OptimizeMemoryAllocation = 1 << 11,
All =
Is64Bit |
AddressSpaceMask |
EnableDebug |
EnableAslr |
IsApplication |
DeprecatedUseSecureMemory |
PoolPartitionMask |
OptimizeMemoryAllocation
}
}

View file

@ -2,36 +2,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{
struct ProcessCreationInfo
{
public string Name { get; private set; }
public string Name { get; }
public int Version { get; private set; }
public ulong TitleId { get; private set; }
public int Version { get; }
public ulong TitleId { get; }
public ulong CodeAddress { get; private set; }
public int CodePagesCount { get; private set; }
public ulong CodeAddress { get; }
public int CodePagesCount { get; }
public int MmuFlags { get; private set; }
public int ResourceLimitHandle { get; private set; }
public int PersonalMmHeapPagesCount { get; private set; }
public ProcessCreationFlags Flags { get; }
public int ResourceLimitHandle { get; }
public int SystemResourcePagesCount { get; }
public ProcessCreationInfo(
string name,
int category,
ulong titleId,
ulong codeAddress,
int codePagesCount,
int mmuFlags,
int resourceLimitHandle,
int personalMmHeapPagesCount)
int version,
ulong titleId,
ulong codeAddress,
int codePagesCount,
ProcessCreationFlags flags,
int resourceLimitHandle,
int systemResourcePagesCount)
{
Name = name;
Version = category;
TitleId = titleId;
CodeAddress = codeAddress;
CodePagesCount = codePagesCount;
MmuFlags = mmuFlags;
ResourceLimitHandle = resourceLimitHandle;
PersonalMmHeapPagesCount = personalMmHeapPagesCount;
Name = name;
Version = version;
TitleId = titleId;
CodeAddress = codeAddress;
CodePagesCount = codePagesCount;
Flags = flags;
ResourceLimitHandle = resourceLimitHandle;
SystemResourcePagesCount = systemResourcePagesCount;
}
}
}