kernel: Add resource limit related syscalls (#2773)
* kernel: Add resource limit related syscalls This commit implements all resource limit related syscalls. * Fix register mapping being wrong for SetResourceLimitLimitValue * Address gdkchan's comment
This commit is contained in:
parent
c94d47cc40
commit
dc837c0042
5 changed files with 206 additions and 2 deletions
|
@ -11,6 +11,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
private readonly long[] _current;
|
private readonly long[] _current;
|
||||||
private readonly long[] _limit;
|
private readonly long[] _limit;
|
||||||
private readonly long[] _current2;
|
private readonly long[] _current2;
|
||||||
|
private readonly long[] _peak;
|
||||||
|
|
||||||
private readonly object _lock;
|
private readonly object _lock;
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
_current = new long[(int)LimitableResource.Count];
|
_current = new long[(int)LimitableResource.Count];
|
||||||
_limit = new long[(int)LimitableResource.Count];
|
_limit = new long[(int)LimitableResource.Count];
|
||||||
_current2 = new long[(int)LimitableResource.Count];
|
_current2 = new long[(int)LimitableResource.Count];
|
||||||
|
_peak = new long[(int)LimitableResource.Count];
|
||||||
|
|
||||||
_lock = new object();
|
_lock = new object();
|
||||||
|
|
||||||
|
@ -79,6 +81,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
_current[index] = newCurrent;
|
_current[index] = newCurrent;
|
||||||
_current2[index] += amount;
|
_current2[index] += amount;
|
||||||
|
|
||||||
|
if (_current[index] > _peak[index])
|
||||||
|
{
|
||||||
|
_peak[index] = _current[index];
|
||||||
|
}
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +129,36 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long GetCurrentValue(LimitableResource resource)
|
||||||
|
{
|
||||||
|
int index = GetIndex(resource);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _current[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetLimitValue(LimitableResource resource)
|
||||||
|
{
|
||||||
|
int index = GetIndex(resource);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _limit[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long GetPeakValue(LimitableResource resource)
|
||||||
|
{
|
||||||
|
int index = GetIndex(resource);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
return _peak[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public KernelResult SetLimitValue(LimitableResource resource, long limit)
|
public KernelResult SetLimitValue(LimitableResource resource, long limit)
|
||||||
{
|
{
|
||||||
int index = GetIndex(resource);
|
int index = GetIndex(resource);
|
||||||
|
@ -131,6 +168,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
|
||||||
if (_current[index] <= limit)
|
if (_current[index] <= limit)
|
||||||
{
|
{
|
||||||
_limit[index] = limit;
|
_limit[index] = limit;
|
||||||
|
_peak[index] = _current[index];
|
||||||
|
|
||||||
return KernelResult.Success;
|
return KernelResult.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1918,6 +1918,95 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
return KernelResult.Success;
|
return KernelResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitLimitValue(int handle, LimitableResource resource, out long limitValue)
|
||||||
|
{
|
||||||
|
limitValue = 0;
|
||||||
|
|
||||||
|
if (resource >= LimitableResource.Count)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidEnumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle);
|
||||||
|
|
||||||
|
if (resourceLimit == null)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
limitValue = resourceLimit.GetLimitValue(resource);
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitCurrentValue(int handle, LimitableResource resource, out long limitValue)
|
||||||
|
{
|
||||||
|
limitValue = 0;
|
||||||
|
|
||||||
|
if (resource >= LimitableResource.Count)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidEnumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle);
|
||||||
|
|
||||||
|
if (resourceLimit == null)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
limitValue = resourceLimit.GetCurrentValue(resource);
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitPeakValue(int handle, LimitableResource resource, out long peak)
|
||||||
|
{
|
||||||
|
peak = 0;
|
||||||
|
|
||||||
|
if (resource >= LimitableResource.Count)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidEnumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle);
|
||||||
|
|
||||||
|
if (resourceLimit == null)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
peak = resourceLimit.GetPeakValue(resource);
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult CreateResourceLimit(out int handle)
|
||||||
|
{
|
||||||
|
KResourceLimit limit = new KResourceLimit(_context);
|
||||||
|
|
||||||
|
KProcess process = KernelStatic.GetCurrentProcess();
|
||||||
|
|
||||||
|
return process.HandleTable.GenerateHandle(limit, out handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult SetResourceLimitLimitValue(int handle, LimitableResource resource, long limitValue)
|
||||||
|
{
|
||||||
|
if (resource >= LimitableResource.Count)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidEnumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit resourceLimit = KernelStatic.GetCurrentProcess().HandleTable.GetObject<KResourceLimit>(handle);
|
||||||
|
|
||||||
|
if (resourceLimit == null)
|
||||||
|
{
|
||||||
|
return KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceLimit.SetLimitValue(resource, limitValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
|
||||||
public KernelResult CreateThread(
|
public KernelResult CreateThread(
|
||||||
|
|
|
@ -295,6 +295,48 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitLimitValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int limitValueLow, [R(2)] out int limitValueHigh)
|
||||||
|
{
|
||||||
|
KernelResult result = _syscall.GetResourceLimitLimitValue(handle, resource, out long limitValue);
|
||||||
|
|
||||||
|
limitValueHigh = (int)(limitValue >> 32);
|
||||||
|
limitValueLow = (int)(limitValue & uint.MaxValue);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitCurrentValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int limitValueLow, [R(2)] out int limitValueHigh)
|
||||||
|
{
|
||||||
|
KernelResult result = _syscall.GetResourceLimitCurrentValue(handle, resource, out long limitValue);
|
||||||
|
|
||||||
|
limitValueHigh = (int)(limitValue >> 32);
|
||||||
|
limitValueLow = (int)(limitValue & uint.MaxValue);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitPeakValue32([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out int peakLow, [R(2)] out int peakHigh)
|
||||||
|
{
|
||||||
|
KernelResult result = _syscall.GetResourceLimitPeakValue(handle, resource, out long peak);
|
||||||
|
|
||||||
|
peakHigh = (int)(peak >> 32);
|
||||||
|
peakLow = (int)(peak & uint.MaxValue);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult CreateResourceLimit32([R(1)] out int handle)
|
||||||
|
{
|
||||||
|
return _syscall.CreateResourceLimit(out handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult SetResourceLimitLimitValue32([R(0)] int handle, [R(1)] LimitableResource resource, [R(2)] uint limitValueLow, [R(3)] uint limitValueHigh)
|
||||||
|
{
|
||||||
|
long limitValue = (long)(limitValueLow | ((ulong)limitValueHigh << 32));
|
||||||
|
|
||||||
|
return _syscall.SetResourceLimitLimitValue(handle, resource, limitValue);
|
||||||
|
}
|
||||||
|
|
||||||
public KernelResult FlushProcessDataCache32(
|
public KernelResult FlushProcessDataCache32(
|
||||||
[R(0)] uint processHandle,
|
[R(0)] uint processHandle,
|
||||||
[R(2)] uint addressLow,
|
[R(2)] uint addressLow,
|
||||||
|
|
|
@ -267,6 +267,31 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
return _syscall.GetSystemInfo(id, handle, subId, out value);
|
return _syscall.GetSystemInfo(id, handle, subId, out value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitLimitValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long limitValue)
|
||||||
|
{
|
||||||
|
return _syscall.GetResourceLimitLimitValue(handle, resource, out limitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitCurrentValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long limitValue)
|
||||||
|
{
|
||||||
|
return _syscall.GetResourceLimitCurrentValue(handle, resource, out limitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult GetResourceLimitPeakValue64([R(1)] int handle, [R(2)] LimitableResource resource, [R(1)] out long peak)
|
||||||
|
{
|
||||||
|
return _syscall.GetResourceLimitPeakValue(handle, resource, out peak);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult CreateResourceLimit64([R(1)] out int handle)
|
||||||
|
{
|
||||||
|
return _syscall.CreateResourceLimit(out handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult SetResourceLimitLimitValue64([R(0)] int handle, [R(1)] LimitableResource resource, [R(2)] long limitValue)
|
||||||
|
{
|
||||||
|
return _syscall.SetResourceLimitLimitValue(handle, resource, limitValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
|
||||||
public KernelResult CreateThread64(
|
public KernelResult CreateThread64(
|
||||||
|
|
|
@ -65,10 +65,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
{ 0x29, nameof(Syscall64.GetInfo64) },
|
{ 0x29, nameof(Syscall64.GetInfo64) },
|
||||||
{ 0x2c, nameof(Syscall64.MapPhysicalMemory64) },
|
{ 0x2c, nameof(Syscall64.MapPhysicalMemory64) },
|
||||||
{ 0x2d, nameof(Syscall64.UnmapPhysicalMemory64) },
|
{ 0x2d, nameof(Syscall64.UnmapPhysicalMemory64) },
|
||||||
|
{ 0x30, nameof(Syscall64.GetResourceLimitLimitValue64) },
|
||||||
|
{ 0x31, nameof(Syscall64.GetResourceLimitCurrentValue64) },
|
||||||
{ 0x32, nameof(Syscall64.SetThreadActivity64) },
|
{ 0x32, nameof(Syscall64.SetThreadActivity64) },
|
||||||
{ 0x33, nameof(Syscall64.GetThreadContext364) },
|
{ 0x33, nameof(Syscall64.GetThreadContext364) },
|
||||||
{ 0x34, nameof(Syscall64.WaitForAddress64) },
|
{ 0x34, nameof(Syscall64.WaitForAddress64) },
|
||||||
{ 0x35, nameof(Syscall64.SignalToAddress64) },
|
{ 0x35, nameof(Syscall64.SignalToAddress64) },
|
||||||
|
{ 0x37, nameof(Syscall64.GetResourceLimitPeakValue64) },
|
||||||
{ 0x40, nameof(Syscall64.CreateSession64) },
|
{ 0x40, nameof(Syscall64.CreateSession64) },
|
||||||
{ 0x41, nameof(Syscall64.AcceptSession64) },
|
{ 0x41, nameof(Syscall64.AcceptSession64) },
|
||||||
{ 0x43, nameof(Syscall64.ReplyAndReceive64) },
|
{ 0x43, nameof(Syscall64.ReplyAndReceive64) },
|
||||||
|
@ -84,7 +87,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
{ 0x73, nameof(Syscall64.SetProcessMemoryPermission64) },
|
{ 0x73, nameof(Syscall64.SetProcessMemoryPermission64) },
|
||||||
{ 0x77, nameof(Syscall64.MapProcessCodeMemory64) },
|
{ 0x77, nameof(Syscall64.MapProcessCodeMemory64) },
|
||||||
{ 0x78, nameof(Syscall64.UnmapProcessCodeMemory64) },
|
{ 0x78, nameof(Syscall64.UnmapProcessCodeMemory64) },
|
||||||
{ 0x7B, nameof(Syscall64.TerminateProcess64) }
|
{ 0x7B, nameof(Syscall64.TerminateProcess64) },
|
||||||
|
{ 0x7D, nameof(Syscall64.CreateResourceLimit64) },
|
||||||
|
{ 0x7E, nameof(Syscall64.SetResourceLimitLimitValue64) }
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (KeyValuePair<int, string> value in svcFuncs64)
|
foreach (KeyValuePair<int, string> value in svcFuncs64)
|
||||||
|
@ -134,10 +139,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
{ 0x29, nameof(Syscall32.GetInfo32) },
|
{ 0x29, nameof(Syscall32.GetInfo32) },
|
||||||
{ 0x2c, nameof(Syscall32.MapPhysicalMemory32) },
|
{ 0x2c, nameof(Syscall32.MapPhysicalMemory32) },
|
||||||
{ 0x2d, nameof(Syscall32.UnmapPhysicalMemory32) },
|
{ 0x2d, nameof(Syscall32.UnmapPhysicalMemory32) },
|
||||||
|
{ 0x30, nameof(Syscall32.GetResourceLimitLimitValue32) },
|
||||||
|
{ 0x31, nameof(Syscall32.GetResourceLimitCurrentValue32) },
|
||||||
{ 0x32, nameof(Syscall32.SetThreadActivity32) },
|
{ 0x32, nameof(Syscall32.SetThreadActivity32) },
|
||||||
{ 0x33, nameof(Syscall32.GetThreadContext332) },
|
{ 0x33, nameof(Syscall32.GetThreadContext332) },
|
||||||
{ 0x34, nameof(Syscall32.WaitForAddress32) },
|
{ 0x34, nameof(Syscall32.WaitForAddress32) },
|
||||||
{ 0x35, nameof(Syscall32.SignalToAddress32) },
|
{ 0x35, nameof(Syscall32.SignalToAddress32) },
|
||||||
|
{ 0x37, nameof(Syscall32.GetResourceLimitPeakValue32) },
|
||||||
{ 0x40, nameof(Syscall32.CreateSession32) },
|
{ 0x40, nameof(Syscall32.CreateSession32) },
|
||||||
{ 0x41, nameof(Syscall32.AcceptSession32) },
|
{ 0x41, nameof(Syscall32.AcceptSession32) },
|
||||||
{ 0x43, nameof(Syscall32.ReplyAndReceive32) },
|
{ 0x43, nameof(Syscall32.ReplyAndReceive32) },
|
||||||
|
@ -153,7 +161,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
{ 0x73, nameof(Syscall32.SetProcessMemoryPermission32) },
|
{ 0x73, nameof(Syscall32.SetProcessMemoryPermission32) },
|
||||||
{ 0x77, nameof(Syscall32.MapProcessCodeMemory32) },
|
{ 0x77, nameof(Syscall32.MapProcessCodeMemory32) },
|
||||||
{ 0x78, nameof(Syscall32.UnmapProcessCodeMemory32) },
|
{ 0x78, nameof(Syscall32.UnmapProcessCodeMemory32) },
|
||||||
{ 0x7B, nameof(Syscall32.TerminateProcess32) }
|
{ 0x7B, nameof(Syscall32.TerminateProcess32) },
|
||||||
|
{ 0x7D, nameof(Syscall32.CreateResourceLimit32) },
|
||||||
|
{ 0x7E, nameof(Syscall32.SetResourceLimitLimitValue32) }
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (KeyValuePair<int, string> value in svcFuncs32)
|
foreach (KeyValuePair<int, string> value in svcFuncs32)
|
||||||
|
|
Reference in a new issue