From 2ab777885b174edb554ef3df7737f112b82e8b5d Mon Sep 17 00:00:00 2001 From: Mary Date: Sun, 5 Dec 2021 00:23:26 +0100 Subject: [PATCH] kernel: Improve GetInfo readability and update to 13.0.0 (#2900) * kernel: Define InfoTYpe and make it less obscure when reading GetInfo Also map ThreadTickCount to 25 instead of 0xF0000002 like 13.x kernel. * kernel: Implement GetInfo IsApplication * kernel: Implement GetInfo FreeThreadCount --- Ryujinx.HLE/HOS/Horizon.cs | 6 +- Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 2 + .../HOS/Kernel/SupervisorCall/InfoType.cs | 33 ++++++ .../HOS/Kernel/SupervisorCall/Syscall.cs | 100 ++++++++++-------- .../HOS/Kernel/SupervisorCall/Syscall32.cs | 2 +- .../HOS/Kernel/SupervisorCall/Syscall64.cs | 2 +- 6 files changed, 98 insertions(+), 47 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 877bb389..74bdb647 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -404,7 +404,7 @@ namespace Ryujinx.HLE.HOS lock (KernelContext.Processes) { // Terminate application. - foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) + foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.IsApplication)) { process.Terminate(); process.DecrementReferenceCount(); @@ -415,7 +415,7 @@ namespace Ryujinx.HLE.HOS // Terminate HLE services (must be done after the application is already terminated, // otherwise the application will receive errors due to service termination). - foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) + foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.IsApplication)) { process.Terminate(); process.DecrementReferenceCount(); @@ -461,7 +461,7 @@ namespace Ryujinx.HLE.HOS { foreach (KProcess process in KernelContext.Processes.Values) { - if (process.Flags.HasFlag(ProcessCreationFlags.IsApplication)) + if (process.IsApplication) { // Only game process should be paused. process.SetActivity(pause); diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index a3691808..0a74eace 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -60,6 +60,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public KProcessCapabilities Capabilities { get; private set; } public ulong TitleId { get; private set; } + public bool IsApplication { get; private set; } public long Pid { get; private set; } private long _creationTimestamp; @@ -193,6 +194,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _memRegion = memRegion; _contextFactory = contextFactory ?? new ProcessContextFactory(); _customThreadStart = customThreadStart; + IsApplication = creationInfo.Flags.HasFlag(ProcessCreationFlags.IsApplication); ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.SystemResourcePagesCount, memRegion); diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs new file mode 100644 index 00000000..5d6b1c7d --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/InfoType.cs @@ -0,0 +1,33 @@ +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + enum InfoType : uint + { + CoreMask, + PriorityMask, + AliasRegionAddress, + AliasRegionSize, + HeapRegionAddress, + HeapRegionSize, + TotalMemorySize, + UsedMemorySize, + DebuggerAttached, + ResourceLimit, + IdleTickCount, + RandomEntropy, + AslrRegionAddress, + AslrRegionSize, + StackRegionAddress, + StackRegionSize, + SystemResourceSizeTotal, + SystemResourceSizeUsed, + ProgramId, + // NOTE: Added in 4.0.0, removed in 5.0.0. + InitialProcessIdRange, + UserExceptionContextAddress, + TotalNonSystemMemorySize, + UsedNonSystemMemorySize, + IsApplication, + FreeThreadCount, + ThreadTickCount + } +} diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 8d0d8187..59d56b4d 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -1575,30 +1575,32 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall Logger.Warning?.Print(LogClass.KernelSvc, str); } - public KernelResult GetInfo(uint id, int handle, long subId, out long value) + public KernelResult GetInfo(InfoType id, int handle, long subId, out long value) { value = 0; switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 20: - case 21: - case 22: + case InfoType.CoreMask: + case InfoType.PriorityMask: + case InfoType.AliasRegionAddress: + case InfoType.AliasRegionSize: + case InfoType.HeapRegionAddress: + case InfoType.HeapRegionSize: + case InfoType.TotalMemorySize: + case InfoType.UsedMemorySize: + case InfoType.AslrRegionAddress: + case InfoType.AslrRegionSize: + case InfoType.StackRegionAddress: + case InfoType.StackRegionSize: + case InfoType.SystemResourceSizeTotal: + case InfoType.SystemResourceSizeUsed: + case InfoType.ProgramId: + case InfoType.UserExceptionContextAddress: + case InfoType.TotalNonSystemMemorySize: + case InfoType.UsedNonSystemMemorySize: + case InfoType.IsApplication: + case InfoType.FreeThreadCount: { if (subId != 0) { @@ -1616,35 +1618,35 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall switch (id) { - case 0: value = process.Capabilities.AllowedCpuCoresMask; break; - case 1: value = process.Capabilities.AllowedThreadPriosMask; break; + case InfoType.CoreMask: value = process.Capabilities.AllowedCpuCoresMask; break; + case InfoType.PriorityMask: value = process.Capabilities.AllowedThreadPriosMask; break; - case 2: value = (long)process.MemoryManager.AliasRegionStart; break; - case 3: + case InfoType.AliasRegionAddress: value = (long)process.MemoryManager.AliasRegionStart; break; + case InfoType.AliasRegionSize: value = (long)(process.MemoryManager.AliasRegionEnd - process.MemoryManager.AliasRegionStart); break; - case 4: value = (long)process.MemoryManager.HeapRegionStart; break; - case 5: + case InfoType.HeapRegionAddress: value = (long)process.MemoryManager.HeapRegionStart; break; + case InfoType.HeapRegionSize: value = (long)(process.MemoryManager.HeapRegionEnd - process.MemoryManager.HeapRegionStart); break; - case 6: value = (long)process.GetMemoryCapacity(); break; + case InfoType.TotalMemorySize: value = (long)process.GetMemoryCapacity(); break; - case 7: value = (long)process.GetMemoryUsage(); break; + case InfoType.UsedMemorySize: value = (long)process.GetMemoryUsage(); break; - case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; + case InfoType.AslrRegionAddress: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; - case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; + case InfoType.AslrRegionSize: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; - case 14: value = (long)process.MemoryManager.StackRegionStart; break; - case 15: + case InfoType.StackRegionAddress: value = (long)process.MemoryManager.StackRegionStart; break; + case InfoType.StackRegionSize: value = (long)(process.MemoryManager.StackRegionEnd - process.MemoryManager.StackRegionStart); break; - case 16: value = (long)process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; + case InfoType.SystemResourceSizeTotal: value = (long)process.PersonalMmHeapPagesCount * KPageTableBase.PageSize; break; - case 17: + case InfoType.SystemResourceSizeUsed: if (process.PersonalMmHeapPagesCount != 0) { value = process.MemoryManager.GetMmUsedPages() * KPageTableBase.PageSize; @@ -1652,19 +1654,33 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; - case 18: value = (long)process.TitleId; break; + case InfoType.ProgramId: value = (long)process.TitleId; break; - case 20: value = (long)process.UserExceptionContextAddress; break; + case InfoType.UserExceptionContextAddress: value = (long)process.UserExceptionContextAddress; break; - case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; + case InfoType.TotalNonSystemMemorySize: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; - case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; + case InfoType.UsedNonSystemMemorySize: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; + + case InfoType.IsApplication: value = process.IsApplication ? 1 : 0; break; + + case InfoType.FreeThreadCount: + if (process.ResourceLimit != null) + { + value = process.ResourceLimit.GetLimitValue(LimitableResource.Thread) - process.ResourceLimit.GetCurrentValue(LimitableResource.Thread); + } + else + { + value = 0; + } + + break; } break; } - case 8: + case InfoType.DebuggerAttached: { if (handle != 0) { @@ -1681,7 +1697,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; } - case 9: + case InfoType.ResourceLimit: { if (handle != 0) { @@ -1713,7 +1729,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; } - case 10: + case InfoType.IdleTickCount: { if (handle != 0) { @@ -1732,7 +1748,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; } - case 11: + case InfoType.RandomEntropy: { if (handle != 0) { @@ -1751,7 +1767,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall break; } - case 0xf0000002u: + case InfoType.ThreadTickCount: { if (subId < -1 || subId > 3) { diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs index bfecad20..bb1cc8ad 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs @@ -257,7 +257,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall public KernelResult GetInfo32( [R(0)] uint subIdLow, - [R(1)] uint id, + [R(1)] InfoType id, [R(2)] int handle, [R(3)] uint subIdHigh, [R(1)] out uint valueLow, diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs index 0ed11a81..97ded4b5 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs @@ -247,7 +247,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall _syscall.OutputDebugString(strPtr, size); } - public KernelResult GetInfo64([R(1)] uint id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) + public KernelResult GetInfo64([R(1)] InfoType id, [R(2)] int handle, [R(3)] long subId, [R(1)] out long value) { return _syscall.GetInfo(id, handle, subId, out value); }