diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs index 270c4ff32..201e390c0 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryRegionManager.cs @@ -1,4 +1,5 @@ using Ryujinx.Horizon.Common; +using System.Collections.Generic; using System.Diagnostics; namespace Ryujinx.HLE.HOS.Kernel.Memory @@ -12,6 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory public ulong EndAddr => Address + Size; private readonly ushort[] _pageReferenceCounts; + public Dictionary> Regions { get; } = new Dictionary>(); public KMemoryRegionManager(ulong address, ulong size, ulong endAddr) { @@ -25,7 +27,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory _pageHeap.UpdateUsedSize(); } - public Result AllocatePages(out KPageList pageList, ulong pagesCount) + public Result AllocatePages(out KPageList pageList, ulong pagesCount, ulong pid) { if (pagesCount == 0) { @@ -36,7 +38,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory lock (_pageHeap) { - Result result = AllocatePagesImpl(out pageList, pagesCount, false); + Result result = AllocatePagesImpl(out pageList, pagesCount, false, pid); if (result == Result.Success) { @@ -71,7 +73,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } - private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random) + private Result AllocatePagesImpl(out KPageList pageList, ulong pagesCount, bool random, ulong pid) { pageList = new KPageList(); @@ -109,6 +111,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } + if (Regions.ContainsKey(pid)) + { + Regions[pid].Add(pageList); + } + else + { + Regions.Add(pid, new List() { pageList }); + } + if (pagesCount != 0) { FreePages(pageList); @@ -116,9 +127,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return KernelResult.OutOfMemory; } + return Result.Success; } + public void ClearFromPid(ulong pid) + { + if (Regions.TryGetValue(pid, out List pageLists)) + { + foreach (KPageList pageList in pageLists) + { + FreePages(pageList); + } + Regions.Remove(pid); + } + } + private ulong AllocatePagesContiguousImpl(ulong pagesCount, ulong alignPages, bool random) { int heapIndex = KPageHeap.GetAlignedBlockIndex(pagesCount, alignPages); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index db190e6a9..4b18af70c 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -523,7 +523,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory ulong regionPagesCount, MemoryState state, KMemoryPermission permission, - out ulong address) + out ulong address, ulong pid) { address = 0; @@ -561,7 +561,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } else { - result = AllocateAndMapPages(address, pagesCount, permission); + result = AllocateAndMapPages(address, pagesCount, permission, pid); } if (result != Result.Success) @@ -575,7 +575,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return Result.Success; } - public Result MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission) + public Result MapPages(ulong address, ulong pagesCount, MemoryState state, KMemoryPermission permission, ulong pid) { ulong size = pagesCount * PageSize; @@ -596,7 +596,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return KernelResult.OutOfResource; } - Result result = AllocateAndMapPages(address, pagesCount, permission); + Result result = AllocateAndMapPages(address, pagesCount, permission,pid); if (result == Result.Success) { @@ -607,11 +607,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } - private Result AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission) + private Result AllocateAndMapPages(ulong address, ulong pagesCount, KMemoryPermission permission, ulong pid) { KMemoryRegionManager region = GetMemoryRegionManager(); - Result result = region.AllocatePages(out KPageList pageList, pagesCount); + Result result = region.AllocatePages(out KPageList pageList, pagesCount,pid); if (result != Result.Success) { @@ -738,7 +738,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } - public Result SetHeapSize(ulong size, out ulong address) + public Result SetHeapSize(ulong size, out ulong address, ulong pid) { address = 0; @@ -768,7 +768,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory KMemoryRegionManager region = GetMemoryRegionManager(); - Result result = region.AllocatePages(out KPageList pageList, pagesCount); + Result result = region.AllocatePages(out KPageList pageList, pagesCount, pid); using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager)); @@ -1305,7 +1305,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } - public Result MapPhysicalMemory(ulong address, ulong size) + public Result MapPhysicalMemory(ulong address, ulong size, ulong pid) { ulong endAddr = address + size; @@ -1340,7 +1340,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory KMemoryRegionManager region = GetMemoryRegionManager(); - Result result = region.AllocatePages(out KPageList pageList, remainingPages); + Result result = region.AllocatePages(out KPageList pageList, remainingPages, pid); using OnScopeExit _ = new(() => pageList.DecrementPagesReferenceCount(Context.MemoryManager)); @@ -2884,7 +2884,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return pa - DramMemoryMap.DramBase; } - protected KMemoryRegionManager GetMemoryRegionManager() + public KMemoryRegionManager GetMemoryRegionManager() { return Context.MemoryManager.MemoryRegions[(int)_memRegion]; } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index b74b23849..bff9429c8 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -268,7 +268,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process codeAddress, codePagesCount, MemoryState.CodeStatic, - KMemoryPermission.None); + KMemoryPermission.None, Pid); if (result != Result.Success) { @@ -437,7 +437,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process regionPagesCount, MemoryState.ThreadLocal, KMemoryPermission.ReadAndWrite, - out ulong tlsPageVa); + out ulong tlsPageVa,Pid); if (result != Result.Success) { @@ -607,7 +607,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process regionPagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite, - out ulong stackBottom); + out ulong stackBottom,Pid); if (result != Result.Success) { @@ -872,6 +872,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public Result Terminate() { + if (Switch.Shared.System.WindowSystem.GetByAruId(Pid) != null) + { + Logger.Info?.Print(LogClass.Service, $"Attempting to terminate a running application window system for PID {Pid}"); + MemoryManager.GetMemoryRegionManager().ClearFromPid(Pid); + } Result result; bool shallTerminate = false; diff --git a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 9bcaf9538..9281fa078 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -897,7 +897,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall KProcess process = KernelStatic.GetCurrentProcess(); - return process.MemoryManager.SetHeapSize(size, out address); + return process.MemoryManager.SetHeapSize(size, out address, process.Pid); } [Svc(2)] @@ -1364,7 +1364,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall KProcess process = KernelStatic.GetCurrentProcess(); - return process.MemoryManager.MapPhysicalMemory(address, size); + return process.MemoryManager.MapPhysicalMemory(address, size, process.Pid); } [Svc(0x2d)] diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index 8a52e0ca3..8d151e9c4 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -169,7 +169,7 @@ namespace Ryujinx.HLE.Loaders.Processes MemoryRegion memoryRegion = kip.UsesSecureMemory ? MemoryRegion.Service : MemoryRegion.Application; KMemoryRegionManager region = context.MemoryManager.MemoryRegions[(int)memoryRegion]; - Result result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount); + Result result = region.AllocatePages(out KPageList pageList, (ulong)codePagesCount, 0); if (result != Result.Success) { Logger.Error?.Print(LogClass.Loader, $"Process initialization returned error \"{result}\".");