| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- using ChocolArm64.State;
- using Ryujinx.Common.Logging;
- using System.Collections.Generic;
- using static Ryujinx.HLE.HOS.ErrorCode;
- namespace Ryujinx.HLE.HOS.Kernel
- {
- partial class SvcHandler
- {
- private void SvcWaitSynchronization(CpuThreadState ThreadState)
- {
- long HandlesPtr = (long)ThreadState.X1;
- int HandlesCount = (int)ThreadState.X2;
- long Timeout = (long)ThreadState.X3;
- Logger.PrintDebug(LogClass.KernelSvc,
- "HandlesPtr = 0x" + HandlesPtr .ToString("x16") + ", " +
- "HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " +
- "Timeout = 0x" + Timeout .ToString("x16"));
- if ((uint)HandlesCount > 0x40)
- {
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
- return;
- }
- List<KSynchronizationObject> SyncObjs = new List<KSynchronizationObject>();
- for (int Index = 0; Index < HandlesCount; Index++)
- {
- int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
- KSynchronizationObject SyncObj = Process.HandleTable.GetObject<KSynchronizationObject>(Handle);
- if (SyncObj == null)
- {
- break;
- }
- SyncObjs.Add(SyncObj);
- }
- int HndIndex = (int)ThreadState.X1;
- ulong High = ThreadState.X1 & (0xffffffffUL << 32);
- long Result = System.Synchronization.WaitFor(SyncObjs.ToArray(), Timeout, ref HndIndex);
- if (Result != 0)
- {
- if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) ||
- Result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled))
- {
- Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- else
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- }
- ThreadState.X0 = (ulong)Result;
- ThreadState.X1 = (uint)HndIndex | High;
- }
- private void SvcCancelSynchronization(CpuThreadState ThreadState)
- {
- int ThreadHandle = (int)ThreadState.X0;
- Logger.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8"));
- KThread Thread = Process.HandleTable.GetKThread(ThreadHandle);
- if (Thread == null)
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- return;
- }
- Thread.CancelSynchronization();
- ThreadState.X0 = 0;
- }
- private void SvcArbitrateLock(CpuThreadState ThreadState)
- {
- int OwnerHandle = (int)ThreadState.X0;
- long MutexAddress = (long)ThreadState.X1;
- int RequesterHandle = (int)ThreadState.X2;
- Logger.PrintDebug(LogClass.KernelSvc,
- "OwnerHandle = 0x" + OwnerHandle .ToString("x8") + ", " +
- "MutexAddress = 0x" + MutexAddress .ToString("x16") + ", " +
- "RequesterHandle = 0x" + RequesterHandle.ToString("x8"));
- if (IsPointingInsideKernel(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
- return;
- }
- if (IsAddressNotWordAligned(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
- return;
- }
- long Result = System.AddressArbiter.ArbitrateLock(
- Process,
- Memory,
- OwnerHandle,
- MutexAddress,
- RequesterHandle);
- if (Result != 0)
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- ThreadState.X0 = (ulong)Result;
- }
- private void SvcArbitrateUnlock(CpuThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
- Logger.PrintDebug(LogClass.KernelSvc, "MutexAddress = 0x" + MutexAddress.ToString("x16"));
- if (IsPointingInsideKernel(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
- return;
- }
- if (IsAddressNotWordAligned(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
- return;
- }
- long Result = System.AddressArbiter.ArbitrateUnlock(Memory, MutexAddress);
- if (Result != 0)
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- ThreadState.X0 = (ulong)Result;
- }
- private void SvcWaitProcessWideKeyAtomic(CpuThreadState ThreadState)
- {
- long MutexAddress = (long)ThreadState.X0;
- long CondVarAddress = (long)ThreadState.X1;
- int ThreadHandle = (int)ThreadState.X2;
- long Timeout = (long)ThreadState.X3;
- Logger.PrintDebug(LogClass.KernelSvc,
- "MutexAddress = 0x" + MutexAddress .ToString("x16") + ", " +
- "CondVarAddress = 0x" + CondVarAddress.ToString("x16") + ", " +
- "ThreadHandle = 0x" + ThreadHandle .ToString("x8") + ", " +
- "Timeout = 0x" + Timeout .ToString("x16"));
- if (IsPointingInsideKernel(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
- return;
- }
- if (IsAddressNotWordAligned(MutexAddress))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned mutex address 0x{MutexAddress:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
- return;
- }
- long Result = System.AddressArbiter.WaitProcessWideKeyAtomic(
- Memory,
- MutexAddress,
- CondVarAddress,
- ThreadHandle,
- Timeout);
- if (Result != 0)
- {
- if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout))
- {
- Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- else
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- }
- ThreadState.X0 = (ulong)Result;
- }
- private void SvcSignalProcessWideKey(CpuThreadState ThreadState)
- {
- long Address = (long)ThreadState.X0;
- int Count = (int)ThreadState.X1;
- Logger.PrintDebug(LogClass.KernelSvc,
- "Address = 0x" + Address.ToString("x16") + ", " +
- "Count = 0x" + Count .ToString("x8"));
- System.AddressArbiter.SignalProcessWideKey(Process, Memory, Address, Count);
- ThreadState.X0 = 0;
- }
- private void SvcWaitForAddress(CpuThreadState ThreadState)
- {
- long Address = (long)ThreadState.X0;
- ArbitrationType Type = (ArbitrationType)ThreadState.X1;
- int Value = (int)ThreadState.X2;
- long Timeout = (long)ThreadState.X3;
- Logger.PrintDebug(LogClass.KernelSvc,
- "Address = 0x" + Address.ToString("x16") + ", " +
- "Type = " + Type .ToString() + ", " +
- "Value = 0x" + Value .ToString("x8") + ", " +
- "Timeout = 0x" + Timeout.ToString("x16"));
- if (IsPointingInsideKernel(Address))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
- return;
- }
- if (IsAddressNotWordAligned(Address))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
- return;
- }
- long Result;
- switch (Type)
- {
- case ArbitrationType.WaitIfLessThan:
- Result = System.AddressArbiter.WaitForAddressIfLessThan(Memory, Address, Value, false, Timeout);
- break;
- case ArbitrationType.DecrementAndWaitIfLessThan:
- Result = System.AddressArbiter.WaitForAddressIfLessThan(Memory, Address, Value, true, Timeout);
- break;
- case ArbitrationType.WaitIfEqual:
- Result = System.AddressArbiter.WaitForAddressIfEqual(Memory, Address, Value, Timeout);
- break;
- default:
- Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
- break;
- }
- if (Result != 0)
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- ThreadState.X0 = (ulong)Result;
- }
- private void SvcSignalToAddress(CpuThreadState ThreadState)
- {
- long Address = (long)ThreadState.X0;
- SignalType Type = (SignalType)ThreadState.X1;
- int Value = (int)ThreadState.X2;
- int Count = (int)ThreadState.X3;
- Logger.PrintDebug(LogClass.KernelSvc,
- "Address = 0x" + Address.ToString("x16") + ", " +
- "Type = " + Type .ToString() + ", " +
- "Value = 0x" + Value .ToString("x8") + ", " +
- "Count = 0x" + Count .ToString("x8"));
- if (IsPointingInsideKernel(Address))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid address 0x{Address:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);
- return;
- }
- if (IsAddressNotWordAligned(Address))
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Unaligned address 0x{Address:x16}!");
- ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);
- return;
- }
- long Result;
- switch (Type)
- {
- case SignalType.Signal:
- Result = System.AddressArbiter.Signal(Address, Count);
- break;
- case SignalType.SignalAndIncrementIfEqual:
- Result = System.AddressArbiter.SignalAndIncrementIfEqual(Memory, Address, Value, Count);
- break;
- case SignalType.SignalAndModifyIfEqual:
- Result = System.AddressArbiter.SignalAndModifyIfEqual(Memory, Address, Value, Count);
- break;
- default:
- Result = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
- break;
- }
- if (Result != 0)
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
- }
- ThreadState.X0 = (ulong)Result;
- }
- private bool IsPointingInsideKernel(long Address)
- {
- return ((ulong)Address + 0x1000000000) < 0xffffff000;
- }
- private bool IsAddressNotWordAligned(long Address)
- {
- return (Address & 3) != 0;
- }
- }
- }
|