Add a new JIT compiler for CPU code (#693)
* Start of the ARMeilleure project
* Refactoring around the old IRAdapter, now renamed to PreAllocator
* Optimize the LowestBitSet method
* Add CLZ support and fix CLS implementation
* Add missing Equals and GetHashCode overrides on some structs, misc small tweaks
* Implement the ByteSwap IR instruction, and some refactoring on the assembler
* Implement the DivideUI IR instruction and fix 64-bits IDIV
* Correct constant operand type on CSINC
* Move division instructions implementation to InstEmitDiv
* Fix destination type for the ConditionalSelect IR instruction
* Implement UMULH and SMULH, with new IR instructions
* Fix some issues with shift instructions
* Fix constant types for BFM instructions
* Fix up new tests using the new V128 struct
* Update tests
* Move DIV tests to a separate file
* Add support for calls, and some instructions that depends on them
* Start adding support for SIMD & FP types, along with some of the related ARM instructions
* Fix some typos and the divide instruction with FP operands
* Fix wrong method call on Clz_V
* Implement ARM FP & SIMD move instructions, Saddlv_V, and misc. fixes
* Implement SIMD logical instructions and more misc. fixes
* Fix PSRAD x86 instruction encoding, TRN, UABD and UABDL implementations
* Implement float conversion instruction, merge in LDj3SNuD fixes, and some other misc. fixes
* Implement SIMD shift instruction and fix Dup_V
* Add SCVTF and UCVTF (vector, fixed-point) variants to the opcode table
* Fix check with tolerance on tester
* Implement FP & SIMD comparison instructions, and some fixes
* Update FCVT (Scalar) encoding on the table to support the Half-float variants
* Support passing V128 structs, some cleanup on the register allocator, merge LDj3SNuD fixes
* Use old memory access methods, made a start on SIMD memory insts support, some fixes
* Fix float constant passed to functions, save and restore non-volatile XMM registers, other fixes
* Fix arguments count with struct return values, other fixes
* More instructions
* Misc. fixes and integrate LDj3SNuD fixes
* Update tests
* Add a faster linear scan allocator, unwinding support on windows, and other changes
* Update Ryujinx.HLE
* Update Ryujinx.Graphics
* Fix V128 return pointer passing, RCX is clobbered
* Update Ryujinx.Tests
* Update ITimeZoneService
* Stop using GetFunctionPointer as that can't be called from native code, misc. fixes and tweaks
* Use generic GetFunctionPointerForDelegate method and other tweaks
* Some refactoring on the code generator, assert on invalid operations and use a separate enum for intrinsics
* Remove some unused code on the assembler
* Fix REX.W prefix regression on float conversion instructions, add some sort of profiler
* Add hardware capability detection
* Fix regression on Sha1h and revert Fcm** changes
* Add SSE2-only paths on vector extract and insert, some refactoring on the pre-allocator
* Fix silly mistake introduced on last commit on CpuId
* Generate inline stack probes when the stack allocation is too large
* Initial support for the System-V ABI
* Support multiple destination operands
* Fix SSE2 VectorInsert8 path, and other fixes
* Change placement of XMM callee save and restore code to match other compilers
* Rename Dest to Destination and Inst to Instruction
* Fix a regression related to calls and the V128 type
* Add an extra space on comments to match code style
* Some refactoring
* Fix vector insert FP32 SSE2 path
* Port over the ARM32 instructions
* Avoid memory protection races on JIT Cache
* Another fix on VectorInsert FP32 (thanks to LDj3SNuD
* Float operands don't need to use the same register when VEX is supported
* Add a new register allocator, higher quality code for hot code (tier up), and other tweaks
* Some nits, small improvements on the pre allocator
* CpuThreadState is gone
* Allow changing CPU emulators with a config entry
* Add runtime identifiers on the ARMeilleure project
* Allow switching between CPUs through a config entry (pt. 2)
* Change win10-x64 to win-x64 on projects
* Update the Ryujinx project to use ARMeilleure
* Ensure that the selected register is valid on the hybrid allocator
* Allow exiting on returns to 0 (should fix test regression)
* Remove register assignments for most used variables on the hybrid allocator
* Do not use fixed registers as spill temp
* Add missing namespace and remove unneeded using
* Address PR feedback
* Fix types, etc
* Enable AssumeStrictAbiCompliance by default
* Ensure that Spill and Fill don't load or store any more than necessary
2019-08-08 20:56:22 +02:00
|
|
|
using ARMeilleure.Memory;
|
2018-11-28 23:18:09 +01:00
|
|
|
using Ryujinx.Common;
|
2018-10-17 19:15:50 +02:00
|
|
|
using Ryujinx.Common.Logging;
|
2018-08-17 01:47:36 +02:00
|
|
|
using Ryujinx.HLE.Exceptions;
|
2018-12-18 06:33:36 +01:00
|
|
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
|
|
|
partial class SvcHandler
|
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
public void ExitProcess64()
|
|
|
|
{
|
|
|
|
ExitProcess();
|
|
|
|
}
|
|
|
|
|
2019-12-26 02:50:17 +01:00
|
|
|
public KernelResult TerminateProcess64(int handle)
|
|
|
|
{
|
|
|
|
return TerminateProcess(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
private KernelResult TerminateProcess(int handle)
|
|
|
|
{
|
|
|
|
KProcess process = _process.HandleTable.GetObject<KProcess>(handle);
|
|
|
|
|
|
|
|
KernelResult result;
|
|
|
|
|
|
|
|
if (process != null)
|
|
|
|
{
|
|
|
|
if (process == _system.Scheduler.GetCurrentProcess())
|
|
|
|
{
|
|
|
|
result = KernelResult.Success;
|
|
|
|
process.DecrementToZeroWhileTerminatingCurrent();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = process.Terminate();
|
|
|
|
process.DecrementReferenceCount();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
private void ExitProcess()
|
2018-02-28 00:45:07 +01:00
|
|
|
{
|
2019-12-26 02:50:17 +01:00
|
|
|
_system.Scheduler.GetCurrentProcess().TerminateCurrentProcess();
|
2018-02-28 00:45:07 +01:00
|
|
|
}
|
2018-02-15 13:16:16 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult SignalEvent64(int handle)
|
2018-03-05 16:58:19 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return SignalEvent(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
2018-03-05 16:58:19 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult SignalEvent(int handle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KWritableEvent writableEvent = _process.HandleTable.GetObject<KWritableEvent>(handle);
|
2018-03-05 16:58:19 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KernelResult result;
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (writableEvent != null)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
writableEvent.Signal();
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
result = KernelResult.Success;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = KernelResult.InvalidHandle;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return result;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult ClearEvent64(int handle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return ClearEvent(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult ClearEvent(int handle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KernelResult result;
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KWritableEvent writableEvent = _process.HandleTable.GetObject<KWritableEvent>(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (writableEvent == null)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KReadableEvent readableEvent = _process.HandleTable.GetObject<KReadableEvent>(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
result = readableEvent?.Clear() ?? KernelResult.InvalidHandle;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = writableEvent.Clear();
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return result;
|
2018-03-05 16:58:19 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult CloseHandle64(int handle)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return CloseHandle(handle);
|
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
private KernelResult CloseHandle(int handle)
|
|
|
|
{
|
2019-01-18 23:26:39 +01:00
|
|
|
KAutoObject obj = _process.HandleTable.GetObject<KAutoObject>(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
_process.HandleTable.CloseHandle(handle);
|
2018-03-19 19:58:46 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (obj == null)
|
2018-03-19 19:58:46 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return KernelResult.InvalidHandle;
|
2018-03-19 19:58:46 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (obj is KSession session)
|
2018-03-19 19:58:46 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
session.Dispose();
|
2018-03-19 19:58:46 +01:00
|
|
|
}
|
2018-12-06 12:16:24 +01:00
|
|
|
else if (obj is KTransferMemory transferMemory)
|
2018-03-19 19:58:46 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
_process.MemoryManager.ResetTransferMemory(
|
|
|
|
transferMemory.Address,
|
|
|
|
transferMemory.Size);
|
2018-03-19 19:58:46 +01:00
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
return KernelResult.Success;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult ResetSignal64(int handle)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return ResetSignal(handle);
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult ResetSignal(int handle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KReadableEvent readableEvent = currentProcess.HandleTable.GetObject<KReadableEvent>(handle);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KernelResult result;
|
2018-03-19 19:58:46 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (readableEvent != null)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = readableEvent.ClearIfSignaled();
|
2018-03-19 19:58:46 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess process = currentProcess.HandleTable.GetKProcess(handle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (process != null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = process.ClearIfNotExited();
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = KernelResult.InvalidHandle;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
2018-03-19 19:58:46 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return result;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public ulong GetSystemTick64()
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
Add a new JIT compiler for CPU code (#693)
* Start of the ARMeilleure project
* Refactoring around the old IRAdapter, now renamed to PreAllocator
* Optimize the LowestBitSet method
* Add CLZ support and fix CLS implementation
* Add missing Equals and GetHashCode overrides on some structs, misc small tweaks
* Implement the ByteSwap IR instruction, and some refactoring on the assembler
* Implement the DivideUI IR instruction and fix 64-bits IDIV
* Correct constant operand type on CSINC
* Move division instructions implementation to InstEmitDiv
* Fix destination type for the ConditionalSelect IR instruction
* Implement UMULH and SMULH, with new IR instructions
* Fix some issues with shift instructions
* Fix constant types for BFM instructions
* Fix up new tests using the new V128 struct
* Update tests
* Move DIV tests to a separate file
* Add support for calls, and some instructions that depends on them
* Start adding support for SIMD & FP types, along with some of the related ARM instructions
* Fix some typos and the divide instruction with FP operands
* Fix wrong method call on Clz_V
* Implement ARM FP & SIMD move instructions, Saddlv_V, and misc. fixes
* Implement SIMD logical instructions and more misc. fixes
* Fix PSRAD x86 instruction encoding, TRN, UABD and UABDL implementations
* Implement float conversion instruction, merge in LDj3SNuD fixes, and some other misc. fixes
* Implement SIMD shift instruction and fix Dup_V
* Add SCVTF and UCVTF (vector, fixed-point) variants to the opcode table
* Fix check with tolerance on tester
* Implement FP & SIMD comparison instructions, and some fixes
* Update FCVT (Scalar) encoding on the table to support the Half-float variants
* Support passing V128 structs, some cleanup on the register allocator, merge LDj3SNuD fixes
* Use old memory access methods, made a start on SIMD memory insts support, some fixes
* Fix float constant passed to functions, save and restore non-volatile XMM registers, other fixes
* Fix arguments count with struct return values, other fixes
* More instructions
* Misc. fixes and integrate LDj3SNuD fixes
* Update tests
* Add a faster linear scan allocator, unwinding support on windows, and other changes
* Update Ryujinx.HLE
* Update Ryujinx.Graphics
* Fix V128 return pointer passing, RCX is clobbered
* Update Ryujinx.Tests
* Update ITimeZoneService
* Stop using GetFunctionPointer as that can't be called from native code, misc. fixes and tweaks
* Use generic GetFunctionPointerForDelegate method and other tweaks
* Some refactoring on the code generator, assert on invalid operations and use a separate enum for intrinsics
* Remove some unused code on the assembler
* Fix REX.W prefix regression on float conversion instructions, add some sort of profiler
* Add hardware capability detection
* Fix regression on Sha1h and revert Fcm** changes
* Add SSE2-only paths on vector extract and insert, some refactoring on the pre-allocator
* Fix silly mistake introduced on last commit on CpuId
* Generate inline stack probes when the stack allocation is too large
* Initial support for the System-V ABI
* Support multiple destination operands
* Fix SSE2 VectorInsert8 path, and other fixes
* Change placement of XMM callee save and restore code to match other compilers
* Rename Dest to Destination and Inst to Instruction
* Fix a regression related to calls and the V128 type
* Add an extra space on comments to match code style
* Some refactoring
* Fix vector insert FP32 SSE2 path
* Port over the ARM32 instructions
* Avoid memory protection races on JIT Cache
* Another fix on VectorInsert FP32 (thanks to LDj3SNuD
* Float operands don't need to use the same register when VEX is supported
* Add a new register allocator, higher quality code for hot code (tier up), and other tweaks
* Some nits, small improvements on the pre allocator
* CpuThreadState is gone
* Allow changing CPU emulators with a config entry
* Add runtime identifiers on the ARMeilleure project
* Allow switching between CPUs through a config entry (pt. 2)
* Change win10-x64 to win-x64 on projects
* Update the Ryujinx project to use ARMeilleure
* Ensure that the selected register is valid on the hybrid allocator
* Allow exiting on returns to 0 (should fix test regression)
* Remove register assignments for most used variables on the hybrid allocator
* Do not use fixed registers as spill temp
* Add missing namespace and remove unneeded using
* Address PR feedback
* Fix types, etc
* Enable AssumeStrictAbiCompliance by default
* Ensure that Spill and Fill don't load or store any more than necessary
2019-08-08 20:56:22 +02:00
|
|
|
return _system.Scheduler.GetCurrentThread().Context.CntpctEl0;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult GetProcessId64(int handle, out long pid)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return GetProcessId(handle, out pid);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult GetProcessId(int handle, out long pid)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess process = currentProcess.HandleTable.GetKProcess(handle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (process == null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KThread thread = currentProcess.HandleTable.GetKThread(handle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (thread != null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
process = thread.Owner;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2019-07-02 04:39:22 +02:00
|
|
|
// TODO: KDebugEvent.
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
pid = process?.Pid ?? 0;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return process != null
|
2018-11-28 23:18:09 +01:00
|
|
|
? KernelResult.Success
|
|
|
|
: KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public void Break64(ulong reason, ulong x1, ulong info)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
Break(reason);
|
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
private void Break(ulong reason)
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KThread currentThread = _system.Scheduler.GetCurrentThread();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
if ((reason & (1UL << 31)) == 0)
|
2018-10-08 20:53:08 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
currentThread.PrintGuestStackTrace();
|
2018-04-22 07:48:17 +02:00
|
|
|
|
2019-12-26 02:50:17 +01:00
|
|
|
// As the process is exiting, this is probably caused by emulation termination.
|
|
|
|
if (currentThread.Owner.State == ProcessState.Exiting)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Debug events.
|
|
|
|
currentThread.Owner.TerminateCurrentProcess();
|
|
|
|
|
2018-10-08 20:53:08 +02:00
|
|
|
throw new GuestBrokeExecutionException();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-11-28 23:18:09 +01:00
|
|
|
Logger.PrintInfo(LogClass.KernelSvc, "Debugger triggered.");
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
currentThread.PrintGuestStackTrace();
|
2018-10-08 20:53:08 +02:00
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public void OutputDebugString64(ulong strPtr, ulong size)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
OutputDebugString(strPtr, size);
|
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
private void OutputDebugString(ulong strPtr, ulong size)
|
|
|
|
{
|
2019-02-24 08:24:35 +01:00
|
|
|
string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size);
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
Logger.PrintWarning(LogClass.KernelSvc, str);
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult GetInfo64(uint id, int handle, long subId, out long value)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return GetInfo(id, handle, subId, out value);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult GetInfo(uint id, int handle, long subId, out long value)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
value = 0;
|
2018-02-07 00:28:32 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
switch (id)
|
2018-02-05 00:08:20 +01:00
|
|
|
{
|
2018-02-28 00:45:07 +01:00
|
|
|
case 0:
|
2018-11-28 23:18:09 +01:00
|
|
|
case 1:
|
2018-02-28 00:45:07 +01:00
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
case 6:
|
|
|
|
case 7:
|
2018-11-28 23:18:09 +01:00
|
|
|
case 12:
|
|
|
|
case 13:
|
|
|
|
case 14:
|
|
|
|
case 15:
|
|
|
|
case 16:
|
|
|
|
case 17:
|
|
|
|
case 18:
|
|
|
|
case 20:
|
|
|
|
case 21:
|
|
|
|
case 22:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess process = currentProcess.HandleTable.GetKProcess(handle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (process == null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
switch (id)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
case 0: value = process.Capabilities.AllowedCpuCoresMask; break;
|
|
|
|
case 1: value = process.Capabilities.AllowedThreadPriosMask; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 2: value = (long)process.MemoryManager.AliasRegionStart; break;
|
|
|
|
case 3: value = (long)(process.MemoryManager.AliasRegionEnd -
|
|
|
|
process.MemoryManager.AliasRegionStart); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 4: value = (long)process.MemoryManager.HeapRegionStart; break;
|
|
|
|
case 5: value = (long)(process.MemoryManager.HeapRegionEnd -
|
|
|
|
process.MemoryManager.HeapRegionStart); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 6: value = (long)process.GetMemoryCapacity(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 7: value = (long)process.GetMemoryUsage(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 14: value = (long)process.MemoryManager.StackRegionStart; break;
|
|
|
|
case 15: value = (long)(process.MemoryManager.StackRegionEnd -
|
|
|
|
process.MemoryManager.StackRegionStart); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
|
|
|
case 17:
|
2018-12-06 12:16:24 +01:00
|
|
|
if (process.PersonalMmHeapPagesCount != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2019-09-02 18:03:57 +02:00
|
|
|
case 18: value = (long)process.TitleId; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 20: value = (long)process.UserExceptionContextAddress; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-02-28 00:45:07 +01:00
|
|
|
break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
2018-02-28 00:45:07 +01:00
|
|
|
|
|
|
|
case 8:
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (handle != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
2018-02-28 00:45:07 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
2018-02-28 00:45:07 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = _system.Scheduler.GetCurrentProcess().Debug ? 1 : 0;
|
2018-02-28 00:45:07 +01:00
|
|
|
|
|
|
|
break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
2018-02-28 00:45:07 +01:00
|
|
|
|
2018-11-28 23:18:09 +01:00
|
|
|
case 9:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (handle != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (currentProcess.ResourceLimit != null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KHandleTable handleTable = currentProcess.HandleTable;
|
|
|
|
KResourceLimit resourceLimit = currentProcess.ResourceLimit;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (result != KernelResult.Success)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
return result;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = (uint)resLimHandle;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
2018-02-28 00:45:07 +01:00
|
|
|
|
|
|
|
break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (handle != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int currentCore = _system.Scheduler.GetCurrentThread().CurrentCore;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != -1 && subId != currentCore)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = _system.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks;
|
2018-06-11 02:46:42 +02:00
|
|
|
|
2018-08-15 20:59:51 +02:00
|
|
|
break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case 11:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (handle != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if ((ulong)subId > 3)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = currentProcess.RandomEntropy[subId];
|
2018-08-15 20:59:51 +02:00
|
|
|
|
2018-05-22 22:40:46 +02:00
|
|
|
break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case 0xf0000002u:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId < -1 || subId > 3)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KThread thread = _system.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (thread == null)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KThread currentThread = _system.Scheduler.GetCurrentThread();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int currentCore = currentThread.CurrentCore;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != -1 && subId != currentCore)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.Success;
|
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KCoreContext coreContext = _system.Scheduler.CoreContexts[currentCore];
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (subId != -1)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
value = KTimeManager.ConvertMillisecondsToTicks(timeDelta);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
long totalTimeRunning = thread.TotalTimeRunning;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (thread == currentThread)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
totalTimeRunning += timeDelta;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2018-04-22 07:48:17 +02:00
|
|
|
|
2018-11-28 23:18:09 +01:00
|
|
|
default: return KernelResult.InvalidEnumValue;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
|
|
|
|
2018-11-28 23:18:09 +01:00
|
|
|
return KernelResult.Success;
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult CreateEvent64(out int wEventHandle, out int rEventHandle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return CreateEvent(out wEventHandle, out rEventHandle);
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult CreateEvent(out int wEventHandle, out int rEventHandle)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KEvent Event = new KEvent(_system);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KernelResult result = _process.HandleTable.GenerateHandle(Event.WritableEvent, out wEventHandle);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (result == KernelResult.Success)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
result = _process.HandleTable.GenerateHandle(Event.ReadableEvent, out rEventHandle);
|
2018-09-23 20:11:46 +02:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (result != KernelResult.Success)
|
2018-09-23 20:11:46 +02:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
_process.HandleTable.CloseHandle(wEventHandle);
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
rEventHandle = 0;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
return result;
|
2018-09-23 20:11:46 +02:00
|
|
|
}
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult GetProcessList64(ulong address, int maxCount, out int count)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return GetProcessList(address, maxCount, out count);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult GetProcessList(ulong address, int maxCount, out int count)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
count = 0;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if ((maxCount >> 28) != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.MaximumExceeded;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (maxCount != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
ulong copySize = (ulong)maxCount * 8;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (address + copySize <= address)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidMemState;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (currentProcess.MemoryManager.OutsideAddrSpace(address, copySize))
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidMemState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
int copyCount = 0;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
lock (_system.Processes)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
foreach (KProcess process in _system.Processes.Values)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if (copyCount < maxCount)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
if (!KernelTransfer.KernelToUserInt64(_system, address + (ulong)copyCount * 8, process.Pid))
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
copyCount++;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
count = copyCount;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
|
|
|
return KernelResult.Success;
|
|
|
|
}
|
|
|
|
|
2018-12-18 06:33:36 +01:00
|
|
|
public KernelResult GetSystemInfo64(uint id, int handle, long subId, out long value)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-18 06:33:36 +01:00
|
|
|
return GetSystemInfo(id, handle, subId, out value);
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
private KernelResult GetSystemInfo(uint id, int handle, long subId, out long value)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
value = 0;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (id > 2)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidEnumValue;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (handle != 0)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
if (id < 2)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if ((ulong)subId > 3)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
KMemoryRegionManager region = _system.MemoryRegions[subId];
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
switch (id)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2019-07-02 04:39:22 +02:00
|
|
|
// Memory region capacity.
|
2018-12-06 12:16:24 +01:00
|
|
|
case 0: value = (long)region.Size; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2019-07-02 04:39:22 +02:00
|
|
|
// Memory region free space.
|
2018-11-28 23:18:09 +01:00
|
|
|
case 1:
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
ulong freePagesCount = region.GetFreePages();
|
2018-11-28 23:18:09 +01:00
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
value = (long)(freePagesCount * KMemoryManager.PageSize);
|
2018-11-28 23:18:09 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else /* if (Id == 2) */
|
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
if ((ulong)subId > 1)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
|
|
|
return KernelResult.InvalidCombination;
|
|
|
|
}
|
|
|
|
|
2018-12-06 12:16:24 +01:00
|
|
|
switch (subId)
|
2018-11-28 23:18:09 +01:00
|
|
|
{
|
2018-12-06 12:16:24 +01:00
|
|
|
case 0: value = _system.PrivilegedProcessLowestId; break;
|
|
|
|
case 1: value = _system.PrivilegedProcessHighestId; break;
|
2018-11-28 23:18:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return KernelResult.Success;
|
|
|
|
}
|
2018-02-05 00:08:20 +01:00
|
|
|
}
|
2018-02-25 00:09:10 +01:00
|
|
|
}
|