private void SvcGetThreadContext3(AThreadState ThreadState) { long Position = (long)ThreadState.X0; int Handle = (int)ThreadState.X1; KThread Thread = Process.HandleTable.GetData <KThread>(Handle); if (Thread == null) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); return; } if (Process.GetThread(ThreadState.Tpidr) == Thread) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is current thread!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread); return; } Memory.WriteUInt64(Position + 0x0, ThreadState.X0); Memory.WriteUInt64(Position + 0x8, ThreadState.X1); Memory.WriteUInt64(Position + 0x10, ThreadState.X2); Memory.WriteUInt64(Position + 0x18, ThreadState.X3); Memory.WriteUInt64(Position + 0x20, ThreadState.X4); Memory.WriteUInt64(Position + 0x28, ThreadState.X5); Memory.WriteUInt64(Position + 0x30, ThreadState.X6); Memory.WriteUInt64(Position + 0x38, ThreadState.X7); Memory.WriteUInt64(Position + 0x40, ThreadState.X8); Memory.WriteUInt64(Position + 0x48, ThreadState.X9); Memory.WriteUInt64(Position + 0x50, ThreadState.X10); Memory.WriteUInt64(Position + 0x58, ThreadState.X11); Memory.WriteUInt64(Position + 0x60, ThreadState.X12); Memory.WriteUInt64(Position + 0x68, ThreadState.X13); Memory.WriteUInt64(Position + 0x70, ThreadState.X14); Memory.WriteUInt64(Position + 0x78, ThreadState.X15); Memory.WriteUInt64(Position + 0x80, ThreadState.X16); Memory.WriteUInt64(Position + 0x88, ThreadState.X17); Memory.WriteUInt64(Position + 0x90, ThreadState.X18); Memory.WriteUInt64(Position + 0x98, ThreadState.X19); Memory.WriteUInt64(Position + 0xa0, ThreadState.X20); Memory.WriteUInt64(Position + 0xa8, ThreadState.X21); Memory.WriteUInt64(Position + 0xb0, ThreadState.X22); Memory.WriteUInt64(Position + 0xb8, ThreadState.X23); Memory.WriteUInt64(Position + 0xc0, ThreadState.X24); Memory.WriteUInt64(Position + 0xc8, ThreadState.X25); Memory.WriteUInt64(Position + 0xd0, ThreadState.X26); Memory.WriteUInt64(Position + 0xd8, ThreadState.X27); Memory.WriteUInt64(Position + 0xe0, ThreadState.X28); Memory.WriteUInt64(Position + 0xe8, ThreadState.X29); Memory.WriteUInt64(Position + 0xf0, ThreadState.X30); Memory.WriteUInt64(Position + 0xf8, ThreadState.X31); Memory.WriteInt64(Position + 0x100, Thread.LastPc); Memory.WriteUInt64(Position + 0x108, (ulong)ThreadState.Psr); Memory.WriteVector128(Position + 0x110, ThreadState.V0); Memory.WriteVector128(Position + 0x120, ThreadState.V1); Memory.WriteVector128(Position + 0x130, ThreadState.V2); Memory.WriteVector128(Position + 0x140, ThreadState.V3); Memory.WriteVector128(Position + 0x150, ThreadState.V4); Memory.WriteVector128(Position + 0x160, ThreadState.V5); Memory.WriteVector128(Position + 0x170, ThreadState.V6); Memory.WriteVector128(Position + 0x180, ThreadState.V7); Memory.WriteVector128(Position + 0x190, ThreadState.V8); Memory.WriteVector128(Position + 0x1a0, ThreadState.V9); Memory.WriteVector128(Position + 0x1b0, ThreadState.V10); Memory.WriteVector128(Position + 0x1c0, ThreadState.V11); Memory.WriteVector128(Position + 0x1d0, ThreadState.V12); Memory.WriteVector128(Position + 0x1e0, ThreadState.V13); Memory.WriteVector128(Position + 0x1f0, ThreadState.V14); Memory.WriteVector128(Position + 0x200, ThreadState.V15); Memory.WriteVector128(Position + 0x210, ThreadState.V16); Memory.WriteVector128(Position + 0x220, ThreadState.V17); Memory.WriteVector128(Position + 0x230, ThreadState.V18); Memory.WriteVector128(Position + 0x240, ThreadState.V19); Memory.WriteVector128(Position + 0x250, ThreadState.V20); Memory.WriteVector128(Position + 0x260, ThreadState.V21); Memory.WriteVector128(Position + 0x270, ThreadState.V22); Memory.WriteVector128(Position + 0x280, ThreadState.V23); Memory.WriteVector128(Position + 0x290, ThreadState.V24); Memory.WriteVector128(Position + 0x2a0, ThreadState.V25); Memory.WriteVector128(Position + 0x2b0, ThreadState.V26); Memory.WriteVector128(Position + 0x2c0, ThreadState.V27); Memory.WriteVector128(Position + 0x2d0, ThreadState.V28); Memory.WriteVector128(Position + 0x2e0, ThreadState.V29); Memory.WriteVector128(Position + 0x2f0, ThreadState.V30); Memory.WriteVector128(Position + 0x300, ThreadState.V31); Memory.WriteInt32(Position + 0x310, ThreadState.Fpcr); Memory.WriteInt32(Position + 0x314, ThreadState.Fpsr); Memory.WriteInt64(Position + 0x318, ThreadState.Tpidr); ThreadState.X0 = 0; }
private void UnpauseAndTerminateAllThreadsExcept(KThread thread) { // TODO. }
private void SvcSetThreadCoreMask(AThreadState ThreadState) { int Handle = (int)ThreadState.X0; int IdealCore = (int)ThreadState.X1; long CoreMask = (long)ThreadState.X2; Ns.Log.PrintDebug(LogClass.KernelSvc, "Handle = " + Handle.ToString("x8") + ", " + "IdealCore = " + IdealCore.ToString("x8") + ", " + "CoreMask = " + CoreMask.ToString("x16")); KThread Thread = GetThread(ThreadState.Tpidr, Handle); if (IdealCore == -2) { //TODO: Get this value from the NPDM file. IdealCore = 0; CoreMask = 1 << IdealCore; } else { if ((uint)IdealCore > 3) { if ((IdealCore | 2) != -1) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core id 0x{IdealCore:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidCoreId); return; } } else if ((CoreMask & (1 << IdealCore)) == 0) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); return; } } if (Thread == null) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); return; } //-1 is used as "don't care", so the IdealCore value is ignored. //-2 is used as "use NPDM default core id" (handled above). //-3 is used as "don't update", the old IdealCore value is kept. if (IdealCore == -3 && (CoreMask & (1 << Thread.IdealCore)) == 0) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid core mask 0x{CoreMask:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMaskValue); return; } Process.Scheduler.ChangeCore(Thread, IdealCore, (int)CoreMask); ThreadState.X0 = 0; }
public void BeginDownLoadFileFlushToMemory(string URL, Action<byte[], float, bool> callback, bool AutoStart = false) { m_curRequest.field0 = URL; m_curRequest.field1 = HttpType.DOWNLOADFILE_TOMEMORY; #if USE_COR m_curRequest.field2 =m_SuccessEvent; requestList.Push(m_curRequest); m_task = new Task (UnityConnect (), AutoStart); #else this.onProcess = callback; m_curRequest.field2 = file; m_thread = KThread.StartTask(ThreadDownLoad, false); #endif }
private KernelResult GetThreadContext3(ulong address, int handle) { KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KThread currentThread = _system.Scheduler.GetCurrentThread(); KThread thread = _process.HandleTable.GetObject <KThread>(handle); if (thread == null) { return(KernelResult.InvalidHandle); } if (thread.Owner != currentProcess) { return(KernelResult.InvalidHandle); } if (currentThread == thread) { return(KernelResult.InvalidThread); } IMemoryManager memory = currentProcess.CpuMemory; memory.WriteUInt64((long)address + 0x0, thread.Context.GetX(0)); memory.WriteUInt64((long)address + 0x8, thread.Context.GetX(1)); memory.WriteUInt64((long)address + 0x10, thread.Context.GetX(2)); memory.WriteUInt64((long)address + 0x18, thread.Context.GetX(3)); memory.WriteUInt64((long)address + 0x20, thread.Context.GetX(4)); memory.WriteUInt64((long)address + 0x28, thread.Context.GetX(5)); memory.WriteUInt64((long)address + 0x30, thread.Context.GetX(6)); memory.WriteUInt64((long)address + 0x38, thread.Context.GetX(7)); memory.WriteUInt64((long)address + 0x40, thread.Context.GetX(8)); memory.WriteUInt64((long)address + 0x48, thread.Context.GetX(9)); memory.WriteUInt64((long)address + 0x50, thread.Context.GetX(10)); memory.WriteUInt64((long)address + 0x58, thread.Context.GetX(11)); memory.WriteUInt64((long)address + 0x60, thread.Context.GetX(12)); memory.WriteUInt64((long)address + 0x68, thread.Context.GetX(13)); memory.WriteUInt64((long)address + 0x70, thread.Context.GetX(14)); memory.WriteUInt64((long)address + 0x78, thread.Context.GetX(15)); memory.WriteUInt64((long)address + 0x80, thread.Context.GetX(16)); memory.WriteUInt64((long)address + 0x88, thread.Context.GetX(17)); memory.WriteUInt64((long)address + 0x90, thread.Context.GetX(18)); memory.WriteUInt64((long)address + 0x98, thread.Context.GetX(19)); memory.WriteUInt64((long)address + 0xa0, thread.Context.GetX(20)); memory.WriteUInt64((long)address + 0xa8, thread.Context.GetX(21)); memory.WriteUInt64((long)address + 0xb0, thread.Context.GetX(22)); memory.WriteUInt64((long)address + 0xb8, thread.Context.GetX(23)); memory.WriteUInt64((long)address + 0xc0, thread.Context.GetX(24)); memory.WriteUInt64((long)address + 0xc8, thread.Context.GetX(25)); memory.WriteUInt64((long)address + 0xd0, thread.Context.GetX(26)); memory.WriteUInt64((long)address + 0xd8, thread.Context.GetX(27)); memory.WriteUInt64((long)address + 0xe0, thread.Context.GetX(28)); memory.WriteUInt64((long)address + 0xe8, thread.Context.GetX(29)); memory.WriteUInt64((long)address + 0xf0, thread.Context.GetX(30)); memory.WriteUInt64((long)address + 0xf8, thread.Context.GetX(31)); memory.WriteInt64((long)address + 0x100, thread.LastPc); memory.WriteUInt64((long)address + 0x108, (ulong)GetPsr(thread.Context)); memory.WriteVector128((long)address + 0x110, thread.Context.GetV(0)); memory.WriteVector128((long)address + 0x120, thread.Context.GetV(1)); memory.WriteVector128((long)address + 0x130, thread.Context.GetV(2)); memory.WriteVector128((long)address + 0x140, thread.Context.GetV(3)); memory.WriteVector128((long)address + 0x150, thread.Context.GetV(4)); memory.WriteVector128((long)address + 0x160, thread.Context.GetV(5)); memory.WriteVector128((long)address + 0x170, thread.Context.GetV(6)); memory.WriteVector128((long)address + 0x180, thread.Context.GetV(7)); memory.WriteVector128((long)address + 0x190, thread.Context.GetV(8)); memory.WriteVector128((long)address + 0x1a0, thread.Context.GetV(9)); memory.WriteVector128((long)address + 0x1b0, thread.Context.GetV(10)); memory.WriteVector128((long)address + 0x1c0, thread.Context.GetV(11)); memory.WriteVector128((long)address + 0x1d0, thread.Context.GetV(12)); memory.WriteVector128((long)address + 0x1e0, thread.Context.GetV(13)); memory.WriteVector128((long)address + 0x1f0, thread.Context.GetV(14)); memory.WriteVector128((long)address + 0x200, thread.Context.GetV(15)); memory.WriteVector128((long)address + 0x210, thread.Context.GetV(16)); memory.WriteVector128((long)address + 0x220, thread.Context.GetV(17)); memory.WriteVector128((long)address + 0x230, thread.Context.GetV(18)); memory.WriteVector128((long)address + 0x240, thread.Context.GetV(19)); memory.WriteVector128((long)address + 0x250, thread.Context.GetV(20)); memory.WriteVector128((long)address + 0x260, thread.Context.GetV(21)); memory.WriteVector128((long)address + 0x270, thread.Context.GetV(22)); memory.WriteVector128((long)address + 0x280, thread.Context.GetV(23)); memory.WriteVector128((long)address + 0x290, thread.Context.GetV(24)); memory.WriteVector128((long)address + 0x2a0, thread.Context.GetV(25)); memory.WriteVector128((long)address + 0x2b0, thread.Context.GetV(26)); memory.WriteVector128((long)address + 0x2c0, thread.Context.GetV(27)); memory.WriteVector128((long)address + 0x2d0, thread.Context.GetV(28)); memory.WriteVector128((long)address + 0x2e0, thread.Context.GetV(29)); memory.WriteVector128((long)address + 0x2f0, thread.Context.GetV(30)); memory.WriteVector128((long)address + 0x300, thread.Context.GetV(31)); memory.WriteInt32((long)address + 0x310, (int)thread.Context.Fpcr); memory.WriteInt32((long)address + 0x314, (int)thread.Context.Fpsr); memory.WriteInt64((long)address + 0x318, thread.Context.Tpidr); return(KernelResult.Success); }
public void PushMessage(Switch device, KThread thread, KClientSession session, ulong messagePtr, ulong messageSize) { _ipcProcessor.Add(new IpcRequest(device, thread, session, messagePtr, messageSize)); }
private void CallStopModule( KModule module, int args, int argp ) { if( module.ModuleStop == 0 ) return; // Create a thread KThread thread = new KThread( _kernel, module, _kernel.Partitions[ 2 ], "module_stop_thread", module.ModuleStop, 0, KThreadAttributes.User, 0x4000 ); _kernel.AddHandle( thread ); thread.Start( ( uint )args, ( uint )argp ); // Setup handler so that we get the callback when the thread ends and we can kill it _kernel.Cpu.SetContextSafetyCallback( thread.ContextID, new ContextSafetyDelegate( this.KmoduleStopThreadEnd ), ( int )thread.UID ); Log.WriteLine( Verbosity.Verbose, Feature.Bios, "ModuleMgrForUser: starting module_stop thread with UID {0:X} for module {1}", thread.UID, module.Name ); // Schedule so that our thread runs _kernel.Schedule(); }
public static KernelResult IpcCall( Switch device, KProcess process, IMemoryManager memory, KThread thread, KClientSession session, IpcMessage request, long cmdPtr) { IpcMessage response = new IpcMessage(); using (MemoryStream raw = new MemoryStream(request.RawData)) { BinaryReader reqReader = new BinaryReader(raw); if (request.Type == IpcMessageType.Request || request.Type == IpcMessageType.RequestWithContext) { response.Type = IpcMessageType.Response; using (MemoryStream resMs = new MemoryStream()) { BinaryWriter resWriter = new BinaryWriter(resMs); ServiceCtx context = new ServiceCtx( device, process, memory, thread, session, request, response, reqReader, resWriter); session.Service.CallMethod(context); response.RawData = resMs.ToArray(); } } else if (request.Type == IpcMessageType.Control || request.Type == IpcMessageType.ControlWithContext) { long magic = reqReader.ReadInt64(); long cmdId = reqReader.ReadInt64(); switch (cmdId) { case 0: { request = FillResponse(response, 0, session.Service.ConvertToDomain()); break; } case 3: { request = FillResponse(response, 0, 0x500); break; } // TODO: Whats the difference between IpcDuplicateSession/Ex? case 2: case 4: { int unknown = reqReader.ReadInt32(); if (process.HandleTable.GenerateHandle(session, out int handle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } response.HandleDesc = IpcHandleDesc.MakeMove(handle); request = FillResponse(response, 0); break; } default: throw new NotImplementedException(cmdId.ToString()); } } else if (request.Type == IpcMessageType.CloseSession) { // TODO return(KernelResult.PortRemoteClosed); } else { throw new NotImplementedException(request.Type.ToString()); } memory.WriteBytes(cmdPtr, response.GetBytes(cmdPtr)); } return(KernelResult.Success); }
private void CondVarSignal( AThreadState ThreadState, KThread CurrThread, long CondVarAddress, int Count) { lock (Process.ThreadSyncLock) { while (Count == -1 || Count-- > 0) { KThread WaitThread = PopCondVarThreadUnsafe(CondVarAddress); if (WaitThread == null) { Ns.Log.PrintDebug(LogClass.KernelSvc, "No more threads to wake up!"); break; } WaitThread.CondVarSignaled = true; long MutexAddress = WaitThread.MutexAddress; Memory.SetExclusive(ThreadState, MutexAddress); int MutexValue = Memory.ReadInt32(MutexAddress); while (MutexValue != 0) { if (Memory.TestExclusive(ThreadState, MutexAddress)) { //Wait until the lock is released. InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread); Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask); Memory.ClearExclusiveForStore(ThreadState); break; } Memory.SetExclusive(ThreadState, MutexAddress); MutexValue = Memory.ReadInt32(MutexAddress); } Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8")); if (MutexValue == 0) { //Give the lock to this thread. Memory.WriteInt32ToSharedAddr(MutexAddress, WaitThread.WaitHandle); WaitThread.WaitHandle = 0; WaitThread.MutexAddress = 0; WaitThread.CondVarAddress = 0; WaitThread.MutexOwner?.UpdatePriority(); WaitThread.MutexOwner = null; Process.Scheduler.WakeUp(WaitThread); } } } }
public KernelResult Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread serverThread = KernelStatic.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; KernelContext.CriticalSection.Enter(); if (_parent.ClientSession.State != ChannelState.Open) { KernelContext.CriticalSection.Leave(); return(KernelResult.PortRemoteClosed); } if (_activeRequest != null || !DequeueRequest(out KSessionRequest request)) { KernelContext.CriticalSection.Leave(); return(KernelResult.NotFound); } if (request.ClientThread == null) { KernelContext.CriticalSection.Leave(); return(KernelResult.PortRemoteClosed); } KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; KernelContext.CriticalSection.Leave(); _activeRequest = request; request.ServerProcess = serverProcess; Message clientMsg = new Message(request); Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize); MessageHeader clientHeader = GetClientMessageHeader(clientMsg); MessageHeader serverHeader = GetServerMessageHeader(serverMsg); KernelResult serverResult = KernelResult.NotFound; KernelResult clientResult = KernelResult.Success; void CleanUpForError() { if (request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager) == KernelResult.Success) { request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager); } CloseAllHandles(serverMsg, clientHeader, serverProcess); KernelContext.CriticalSection.Enter(); _activeRequest = null; if (_requests.Count != 0) { Signal(); } KernelContext.CriticalSection.Leave(); WakeClientThread(request, clientResult); } if (clientHeader.ReceiveListType < 2 && clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType == 2 && clientHeader.ReceiveListOffset + 8 > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType > 2 && clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.MessageSizeInWords * 4 > clientMsg.Size) { CleanUpForError(); return(KernelResult.CmdBufferTooSmall); } ulong[] receiveList = GetReceiveList( serverMsg, serverHeader.ReceiveListType, serverHeader.ReceiveListOffset); serverProcess.CpuMemory.Write(serverMsg.Address + 0, clientHeader.Word0); serverProcess.CpuMemory.Write(serverMsg.Address + 4, clientHeader.Word1); uint offset; // Copy handles. if (clientHeader.HasHandles) { if (clientHeader.MoveHandlesCount != 0) { CleanUpForError(); return(KernelResult.InvalidCombination); } serverProcess.CpuMemory.Write(serverMsg.Address + 8, clientHeader.Word2); offset = 3; if (clientHeader.HasPid) { serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, clientProcess.Pid); offset += 2; } for (int index = 0; index < clientHeader.CopyHandlesCount; index++) { int newHandle = 0; int handle = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4); if (clientResult == KernelResult.Success && handle != 0) { clientResult = GetCopyObjectHandle(clientThread, serverProcess, handle, out newHandle); } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle); offset++; } for (int index = 0; index < clientHeader.MoveHandlesCount; index++) { int newHandle = 0; int handle = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4); if (handle != 0) { if (clientResult == KernelResult.Success) { clientResult = GetMoveObjectHandle(clientProcess, serverProcess, handle, out newHandle); } else { clientProcess.HandleTable.CloseHandle(handle); } } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle); offset++; } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } else { offset = 2; } // Copy pointer/receive list buffers. uint recvListDstOffset = 0; for (int index = 0; index < clientHeader.PointerBuffersCount; index++) { ulong pointerDesc = KernelContext.Memory.Read <ulong>(clientMsg.DramAddress + offset * 4); PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc); if (descriptor.BufferSize != 0) { clientResult = GetReceiveListAddress( descriptor, serverMsg, serverHeader.ReceiveListType, clientHeader.MessageSizeInWords, receiveList, ref recvListDstOffset, out ulong recvListBufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess( recvListBufferAddress, descriptor.BufferSize, descriptor.BufferAddress, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, KMemoryPermission.Read, MemoryAttribute.Uncached, MemoryAttribute.None); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } descriptor.BufferAddress = recvListBufferAddress; } else { descriptor.BufferAddress = 0; } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, descriptor.Pack()); offset += 2; } // Copy send, receive and exchange buffers. uint totalBuffersCount = clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount + clientHeader.ExchangeBuffersCount; for (int index = 0; index < totalBuffersCount; index++) { ulong clientDescAddress = clientMsg.DramAddress + offset * 4; uint descWord0 = KernelContext.Memory.Read <uint>(clientDescAddress + 0); uint descWord1 = KernelContext.Memory.Read <uint>(clientDescAddress + 4); uint descWord2 = KernelContext.Memory.Read <uint>(clientDescAddress + 8); bool isSendDesc = index < clientHeader.SendBuffersCount; bool isExchangeDesc = index >= clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount; bool notReceiveDesc = isSendDesc || isExchangeDesc; bool isReceiveDesc = !notReceiveDesc; KMemoryPermission permission = index >= clientHeader.SendBuffersCount ? KMemoryPermission.ReadAndWrite : KMemoryPermission.Read; uint sizeHigh4 = (descWord2 >> 24) & 0xf; ulong bufferSize = descWord0 | (ulong)sizeHigh4 << 32; ulong dstAddress = 0; if (bufferSize != 0) { ulong bufferAddress; bufferAddress = descWord2 >> 28; bufferAddress |= ((descWord2 >> 2) & 7) << 4; bufferAddress = (bufferAddress << 32) | descWord1; MemoryState state = IpcMemoryStates[(descWord2 + 1) & 3]; clientResult = serverProcess.MemoryManager.MapBufferFromClientProcess( bufferSize, bufferAddress, clientProcess.MemoryManager, permission, state, notReceiveDesc, out dstAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } if (isSendDesc) { clientResult = request.BufferDescriptorTable.AddSendBuffer(bufferAddress, dstAddress, bufferSize, state); } else if (isReceiveDesc) { clientResult = request.BufferDescriptorTable.AddReceiveBuffer(bufferAddress, dstAddress, bufferSize, state); } else /* if (isExchangeDesc) */ { clientResult = request.BufferDescriptorTable.AddExchangeBuffer(bufferAddress, dstAddress, bufferSize, state); } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } descWord1 = (uint)dstAddress; descWord2 &= 3; descWord2 |= sizeHigh4 << 24; descWord2 |= (uint)(dstAddress >> 34) & 0x3ffffffc; descWord2 |= (uint)(dstAddress >> 4) & 0xf0000000; ulong serverDescAddress = serverMsg.Address + offset * 4; serverProcess.CpuMemory.Write(serverDescAddress + 0, descWord0); serverProcess.CpuMemory.Write(serverDescAddress + 4, descWord1); serverProcess.CpuMemory.Write(serverDescAddress + 8, descWord2); offset += 3; } // Copy raw data. if (clientHeader.RawDataSizeInWords != 0) { ulong copySrc = clientMsg.Address + offset * 4; ulong copyDst = serverMsg.Address + offset * 4; ulong copySize = clientHeader.RawDataSizeInWords * 4; if (serverMsg.IsCustom || clientMsg.IsCustom) { KMemoryPermission permission = clientMsg.IsCustom ? KMemoryPermission.None : KMemoryPermission.Read; clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess( copyDst, copySize, copySrc, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, permission, MemoryAttribute.Uncached, MemoryAttribute.None); } else { copySrc = clientProcess.MemoryManager.GetDramAddressFromVa(copySrc); copyDst = serverProcess.MemoryManager.GetDramAddressFromVa(copyDst); KernelContext.Memory.Copy(copyDst, copySrc, copySize); } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } return(KernelResult.Success); }
public KernelResult Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread serverThread = KernelStatic.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; KernelContext.CriticalSection.Enter(); if (_activeRequest == null) { KernelContext.CriticalSection.Leave(); return(KernelResult.InvalidState); } KSessionRequest request = _activeRequest; _activeRequest = null; if (_requests.Count != 0) { Signal(); } KernelContext.CriticalSection.Leave(); KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; Message clientMsg = new Message(request); Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize); MessageHeader clientHeader = GetClientMessageHeader(clientMsg); MessageHeader serverHeader = GetServerMessageHeader(serverMsg); KernelResult clientResult = KernelResult.Success; KernelResult serverResult = KernelResult.Success; void CleanUpForError() { CloseAllHandles(clientMsg, serverHeader, clientProcess); FinishRequest(request, clientResult); } if (clientHeader.ReceiveListType < 2 && clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType == 2 && clientHeader.ReceiveListOffset + 8 > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType > 2 && clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (serverHeader.MessageSizeInWords * 4 > clientMsg.Size) { CleanUpForError(); return(KernelResult.CmdBufferTooSmall); } if (serverHeader.SendBuffersCount != 0 || serverHeader.ReceiveBuffersCount != 0 || serverHeader.ExchangeBuffersCount != 0) { CleanUpForError(); return(KernelResult.InvalidCombination); } // Read receive list. ulong[] receiveList = GetReceiveList( clientMsg, clientHeader.ReceiveListType, clientHeader.ReceiveListOffset); // Copy receive and exchange buffers. clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } // Copy header. KernelContext.Memory.Write(clientMsg.DramAddress + 0, serverHeader.Word0); KernelContext.Memory.Write(clientMsg.DramAddress + 4, serverHeader.Word1); // Copy handles. uint offset; if (serverHeader.HasHandles) { offset = 3; KernelContext.Memory.Write(clientMsg.DramAddress + 8, serverHeader.Word2); if (serverHeader.HasPid) { KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, serverProcess.Pid); offset += 2; } for (int index = 0; index < serverHeader.CopyHandlesCount; index++) { int newHandle = 0; int handle = serverProcess.CpuMemory.Read <int>(serverMsg.Address + offset * 4); if (handle != 0) { GetCopyObjectHandle(serverThread, clientProcess, handle, out newHandle); } KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } for (int index = 0; index < serverHeader.MoveHandlesCount; index++) { int newHandle = 0; int handle = serverProcess.CpuMemory.Read <int>(serverMsg.Address + offset * 4); if (handle != 0) { if (clientResult == KernelResult.Success) { clientResult = GetMoveObjectHandle(serverProcess, clientProcess, handle, out newHandle); } else { serverProcess.HandleTable.CloseHandle(handle); } } KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } } else { offset = 2; } // Copy pointer/receive list buffers. uint recvListDstOffset = 0; for (int index = 0; index < serverHeader.PointerBuffersCount; index++) { ulong pointerDesc = serverProcess.CpuMemory.Read <ulong>(serverMsg.Address + offset * 4); PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc); ulong recvListBufferAddress = 0; if (descriptor.BufferSize != 0) { clientResult = GetReceiveListAddress( descriptor, clientMsg, clientHeader.ReceiveListType, serverHeader.MessageSizeInWords, receiveList, ref recvListDstOffset, out recvListBufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess( recvListBufferAddress, descriptor.BufferSize, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, KMemoryPermission.Read, MemoryAttribute.Uncached, MemoryAttribute.None, descriptor.BufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } ulong dstDescAddress = clientMsg.DramAddress + offset * 4; ulong clientPointerDesc = (recvListBufferAddress << 32) | ((recvListBufferAddress >> 20) & 0xf000) | ((recvListBufferAddress >> 30) & 0xffc0); clientPointerDesc |= pointerDesc & 0xffff000f; KernelContext.Memory.Write(dstDescAddress + 0, clientPointerDesc); offset += 2; } // Set send, receive and exchange buffer descriptors to zero. uint totalBuffersCount = serverHeader.SendBuffersCount + serverHeader.ReceiveBuffersCount + serverHeader.ExchangeBuffersCount; for (int index = 0; index < totalBuffersCount; index++) { ulong dstDescAddress = clientMsg.DramAddress + offset * 4; KernelContext.Memory.Write(dstDescAddress + 0, 0); KernelContext.Memory.Write(dstDescAddress + 4, 0); KernelContext.Memory.Write(dstDescAddress + 8, 0); offset += 3; } // Copy raw data. if (serverHeader.RawDataSizeInWords != 0) { ulong copyDst = clientMsg.Address + offset * 4; ulong copySrc = serverMsg.Address + offset * 4; ulong copySize = serverHeader.RawDataSizeInWords * 4; if (serverMsg.IsCustom || clientMsg.IsCustom) { KMemoryPermission permission = clientMsg.IsCustom ? KMemoryPermission.None : KMemoryPermission.Read; clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess( copyDst, copySize, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, permission, MemoryAttribute.Uncached, MemoryAttribute.None, copySrc); } else { copyDst = clientProcess.MemoryManager.GetDramAddressFromVa(copyDst); copySrc = serverProcess.MemoryManager.GetDramAddressFromVa(copySrc); KernelContext.Memory.Copy(copyDst, copySrc, copySize); } } // Unmap buffers from server. FinishRequest(request, clientResult); return(serverResult); }
private void ServerLoop() { _selfProcess = KernelStatic.GetCurrentProcess(); if (SmObjectFactory != null) { _context.Syscall.ManageNamedPort(out int serverPortHandle, "sm:", 50); AddPort(serverPortHandle, SmObjectFactory); } InitDone.Set(); KThread thread = KernelStatic.GetCurrentThread(); ulong messagePtr = thread.TlsAddress; _context.Syscall.SetHeapSize(out ulong heapAddr, 0x200000); _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); int replyTargetHandle = 0; while (true) { int[] portHandles = _portHandles.ToArray(); int[] sessionHandles = _sessionHandles.ToArray(); int[] handles = new int[portHandles.Length + sessionHandles.Length]; portHandles.CopyTo(handles, 0); sessionHandles.CopyTo(handles, portHandles.Length); // We still need a timeout here to allow the service to pick up and listen new sessions... var rc = _context.Syscall.ReplyAndReceive(out int signaledIndex, handles, replyTargetHandle, 1000000L); thread.HandlePostSyscall(); if (!thread.Context.Running) { break; } replyTargetHandle = 0; if (rc == KernelResult.Success && signaledIndex >= portHandles.Length) { // We got a IPC request, process it, pass to the appropriate service if needed. int signaledHandle = handles[signaledIndex]; if (Process(signaledHandle, heapAddr)) { replyTargetHandle = signaledHandle; } } else { if (rc == KernelResult.Success) { // We got a new connection, accept the session to allow servicing future requests. if (_context.Syscall.AcceptSession(out int serverSessionHandle, handles[signaledIndex]) == KernelResult.Success) { IpcService obj = _ports[handles[signaledIndex]].Invoke(); AddSessionObj(serverSessionHandle, obj); } } _selfProcess.CpuMemory.Write(messagePtr + 0x0, 0); _selfProcess.CpuMemory.Write(messagePtr + 0x4, 2 << 10); _selfProcess.CpuMemory.Write(messagePtr + 0x8, heapAddr | ((ulong)PointerBufferSize << 48)); } } Dispose(); }
private bool Process(int serverSessionHandle, ulong recvListAddr) { KProcess process = KernelStatic.GetCurrentProcess(); KThread thread = KernelStatic.GetCurrentThread(); ulong messagePtr = thread.TlsAddress; ulong messageSize = 0x100; byte[] reqData = new byte[messageSize]; process.CpuMemory.Read(messagePtr, reqData); IpcMessage request = new IpcMessage(reqData, (long)messagePtr); IpcMessage response = new IpcMessage(); ulong tempAddr = recvListAddr; int sizesOffset = request.RawData.Length - ((request.RecvListBuff.Count * 2 + 3) & ~3); bool noReceive = true; for (int i = 0; i < request.ReceiveBuff.Count; i++) { noReceive &= (request.ReceiveBuff[i].Position == 0); } if (noReceive) { for (int i = 0; i < request.RecvListBuff.Count; i++) { ulong size = (ulong)BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan(sizesOffset + i * 2, 2)); response.PtrBuff.Add(new IpcPtrBuffDesc(tempAddr, (uint)i, size)); request.RecvListBuff[i] = new IpcRecvListBuffDesc(tempAddr, size); tempAddr += size; } } bool shouldReply = true; bool isTipcCommunication = false; using (MemoryStream raw = new MemoryStream(request.RawData)) { BinaryReader reqReader = new BinaryReader(raw); if (request.Type == IpcMessageType.HipcRequest || request.Type == IpcMessageType.HipcRequestWithContext) { response.Type = IpcMessageType.HipcResponse; using (MemoryStream resMs = new MemoryStream()) { BinaryWriter resWriter = new BinaryWriter(resMs); ServiceCtx context = new ServiceCtx( _context.Device, process, process.CpuMemory, thread, request, response, reqReader, resWriter); _sessions[serverSessionHandle].CallHipcMethod(context); response.RawData = resMs.ToArray(); } } else if (request.Type == IpcMessageType.HipcControl || request.Type == IpcMessageType.HipcControlWithContext) { uint magic = (uint)reqReader.ReadUInt64(); uint cmdId = (uint)reqReader.ReadUInt64(); switch (cmdId) { case 0: request = FillResponse(response, 0, _sessions[serverSessionHandle].ConvertToDomain()); break; case 3: request = FillResponse(response, 0, PointerBufferSize); break; // TODO: Whats the difference between IpcDuplicateSession/Ex? case 2: case 4: int unknown = reqReader.ReadInt32(); _context.Syscall.CreateSession(out int dupServerSessionHandle, out int dupClientSessionHandle, false, 0); AddSessionObj(dupServerSessionHandle, _sessions[serverSessionHandle]); response.HandleDesc = IpcHandleDesc.MakeMove(dupClientSessionHandle); request = FillResponse(response, 0); break; default: throw new NotImplementedException(cmdId.ToString()); } } else if (request.Type == IpcMessageType.HipcCloseSession || request.Type == IpcMessageType.TipcCloseSession) { _context.Syscall.CloseHandle(serverSessionHandle); _sessionHandles.Remove(serverSessionHandle); IpcService service = _sessions[serverSessionHandle]; if (service is IDisposable disposableObj) { disposableObj.Dispose(); } _sessions.Remove(serverSessionHandle); shouldReply = false; } // If the type is past 0xF, we are using TIPC else if (request.Type > IpcMessageType.TipcCloseSession) { isTipcCommunication = true; // Response type is always the same as request on TIPC. response.Type = request.Type; using (MemoryStream resMs = new MemoryStream()) { BinaryWriter resWriter = new BinaryWriter(resMs); ServiceCtx context = new ServiceCtx( _context.Device, process, process.CpuMemory, thread, request, response, reqReader, resWriter); _sessions[serverSessionHandle].CallTipcMethod(context); response.RawData = resMs.ToArray(); } process.CpuMemory.Write(messagePtr, response.GetBytesTipc()); } else { throw new NotImplementedException(request.Type.ToString()); } if (!isTipcCommunication) { process.CpuMemory.Write(messagePtr, response.GetBytes((long)messagePtr, recvListAddr | ((ulong)PointerBufferSize << 48))); } return(shouldReply); } }
private void PostSvcHandler() { KThread currentThread = _context.Scheduler.GetCurrentThread(); currentThread.HandlePostSyscall(); }
private void SvcExitThread(AThreadState ThreadState) { KThread CurrThread = Process.GetThread(ThreadState.Tpidr); CurrThread.Thread.StopExecution(); }
private KernelResult GetThreadContext3(ulong address, int handle) { KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KThread currentThread = _system.Scheduler.GetCurrentThread(); KThread thread = _process.HandleTable.GetObject <KThread>(handle); if (thread == null) { return(KernelResult.InvalidHandle); } if (thread.Owner != currentProcess) { return(KernelResult.InvalidHandle); } if (currentThread == thread) { return(KernelResult.InvalidThread); } MemoryManager memory = currentProcess.CpuMemory; memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0); memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1); memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2); memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3); memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4); memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5); memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6); memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7); memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8); memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9); memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10); memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11); memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12); memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13); memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14); memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15); memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16); memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17); memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18); memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19); memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20); memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21); memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22); memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23); memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24); memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25); memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26); memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27); memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28); memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29); memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30); memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31); memory.WriteInt64((long)address + 0x100, thread.LastPc); memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr); memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0); memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1); memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2); memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3); memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4); memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5); memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6); memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7); memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8); memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9); memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10); memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11); memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12); memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13); memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14); memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15); memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16); memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17); memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18); memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19); memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20); memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21); memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22); memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23); memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24); memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25); memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26); memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27); memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28); memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29); memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30); memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31); memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr); memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr); memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr); return(KernelResult.Success); }
private KernelResult GetInfo(uint 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: { if (subId != 0) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess process = currentProcess.HandleTable.GetKProcess(handle); if (process == null) { return(KernelResult.InvalidHandle); } switch (id) { case 0: value = process.Capabilities.AllowedCpuCoresMask; break; case 1: value = process.Capabilities.AllowedThreadPriosMask; break; case 2: value = (long)process.MemoryManager.AliasRegionStart; break; case 3: value = (long)(process.MemoryManager.AliasRegionEnd - process.MemoryManager.AliasRegionStart); break; case 4: value = (long)process.MemoryManager.HeapRegionStart; break; case 5: value = (long)(process.MemoryManager.HeapRegionEnd - process.MemoryManager.HeapRegionStart); break; case 6: value = (long)process.GetMemoryCapacity(); break; case 7: value = (long)process.GetMemoryUsage(); break; case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; case 14: value = (long)process.MemoryManager.StackRegionStart; break; case 15: value = (long)(process.MemoryManager.StackRegionEnd - process.MemoryManager.StackRegionStart); break; case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break; case 17: if (process.PersonalMmHeapPagesCount != 0) { value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize; } break; case 18: value = process.TitleId; break; case 20: value = (long)process.UserExceptionContextAddress; break; case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; } break; } case 8: { if (handle != 0) { return(KernelResult.InvalidHandle); } if (subId != 0) { return(KernelResult.InvalidCombination); } value = _system.Scheduler.GetCurrentProcess().Debug ? 1 : 0; break; } case 9: { if (handle != 0) { return(KernelResult.InvalidHandle); } if (subId != 0) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); if (currentProcess.ResourceLimit != null) { KHandleTable handleTable = currentProcess.HandleTable; KResourceLimit resourceLimit = currentProcess.ResourceLimit; KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle); if (result != KernelResult.Success) { return(result); } value = (uint)resLimHandle; } break; } case 10: { if (handle != 0) { return(KernelResult.InvalidHandle); } int currentCore = _system.Scheduler.GetCurrentThread().CurrentCore; if (subId != -1 && subId != currentCore) { return(KernelResult.InvalidCombination); } value = _system.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks; break; } case 11: { if (handle != 0) { return(KernelResult.InvalidHandle); } if ((ulong)subId > 3) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); value = currentProcess.RandomEntropy[subId]; break; } case 0xf0000002u: { if (subId < -1 || subId > 3) { return(KernelResult.InvalidCombination); } KThread thread = _system.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle); if (thread == null) { return(KernelResult.InvalidHandle); } KThread currentThread = _system.Scheduler.GetCurrentThread(); int currentCore = currentThread.CurrentCore; if (subId != -1 && subId != currentCore) { return(KernelResult.Success); } KCoreContext coreContext = _system.Scheduler.CoreContexts[currentCore]; long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime; if (subId != -1) { value = KTimeManager.ConvertMillisecondsToTicks(timeDelta); } else { long totalTimeRunning = thread.TotalTimeRunning; if (thread == currentThread) { totalTimeRunning += timeDelta; } value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning); } break; } default: return(KernelResult.InvalidEnumValue); } return(KernelResult.Success); }
public bool IsExceptionUserThread(KThread thread) { // TODO return(false); }
protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { _isDisposed = true; KProcess terminationProcess = new KProcess(KernelContext); KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. lock (KernelContext.Processes) { // Terminate application. foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) { process.Terminate(); process.DecrementReferenceCount(); } // The application existed, now surface flinger can exit too. SurfaceFlinger.Dispose(); // 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))) { process.Terminate(); process.DecrementReferenceCount(); } KernelContext.Processes.Clear(); } // Exit ourself now! KernelStatic.GetCurrentThread().Exit(); }); terminationThread.Start(); // Wait until the thread is actually started. while (terminationThread.HostThread.ThreadState == ThreadState.Unstarted) { Thread.Sleep(10); } // Wait until the termination thread is done terminating all the other threads. terminationThread.HostThread.Join(); // Destroy nvservices channels as KThread could be waiting on some user events. // This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade. INvDrvServices.Destroy(); AudioManager.Dispose(); AudioOutputManager.Dispose(); AudioInputManager.Dispose(); AudioRendererManager.Dispose(); KernelContext.Dispose(); } }
public KernelResult Start(int mainThreadPriority, ulong stackSize) { lock (_processLock) { if (State > ProcessState.CreatedAttached) { return(KernelResult.InvalidState); } if (ResourceLimit != null && !ResourceLimit.Reserve(LimitableResource.Thread, 1)) { return(KernelResult.ResLimitExceeded); } KResourceLimit threadResourceLimit = ResourceLimit; KResourceLimit memoryResourceLimit = null; if (_mainThreadStackSize != 0) { throw new InvalidOperationException("Trying to start a process with a invalid state!"); } ulong stackSizeRounded = BitUtils.AlignUp(stackSize, KPageTableBase.PageSize); ulong neededSize = stackSizeRounded + _imageSize; // Check if the needed size for the code and the stack will fit on the // memory usage capacity of this Process. Also check for possible overflow // on the above addition. if (neededSize > _memoryUsageCapacity || neededSize < stackSizeRounded) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.OutOfMemory); } if (stackSizeRounded != 0 && ResourceLimit != null) { memoryResourceLimit = ResourceLimit; if (!memoryResourceLimit.Reserve(LimitableResource.Memory, stackSizeRounded)) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.ResLimitExceeded); } } KernelResult result; KThread mainThread = null; ulong stackTop = 0; void CleanUpForError() { HandleTable.Destroy(); mainThread?.DecrementReferenceCount(); if (_mainThreadStackSize != 0) { ulong stackBottom = stackTop - _mainThreadStackSize; ulong stackPagesCount = _mainThreadStackSize / KPageTableBase.PageSize; MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack); _mainThreadStackSize = 0; } memoryResourceLimit?.Release(LimitableResource.Memory, stackSizeRounded); threadResourceLimit?.Release(LimitableResource.Thread, 1); } if (stackSizeRounded != 0) { ulong stackPagesCount = stackSizeRounded / KPageTableBase.PageSize; ulong regionStart = MemoryManager.StackRegionStart; ulong regionSize = MemoryManager.StackRegionEnd - regionStart; ulong regionPagesCount = regionSize / KPageTableBase.PageSize; result = MemoryManager.MapPages( stackPagesCount, KPageTableBase.PageSize, 0, false, regionStart, regionPagesCount, MemoryState.Stack, KMemoryPermission.ReadAndWrite, out ulong stackBottom); if (result != KernelResult.Success) { CleanUpForError(); return(result); } _mainThreadStackSize += stackSizeRounded; stackTop = stackBottom + stackSizeRounded; } ulong heapCapacity = _memoryUsageCapacity - _mainThreadStackSize - _imageSize; result = MemoryManager.SetHeapCapacity(heapCapacity); if (result != KernelResult.Success) { CleanUpForError(); return(result); } HandleTable = new KHandleTable(KernelContext); result = HandleTable.Initialize(Capabilities.HandleTableSize); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread = new KThread(KernelContext); result = mainThread.Initialize( _entrypoint, 0, stackTop, mainThreadPriority, DefaultCpuCore, this, ThreadType.User, _customThreadStart); if (result != KernelResult.Success) { CleanUpForError(); return(result); } result = HandleTable.GenerateHandle(mainThread, out int mainThreadHandle); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread.SetEntryArguments(0, mainThreadHandle); ProcessState oldState = State; ProcessState newState = State != ProcessState.Created ? ProcessState.Attached : ProcessState.Started; SetState(newState); result = mainThread.Start(); if (result != KernelResult.Success) { SetState(oldState); CleanUpForError(); } if (result == KernelResult.Success) { mainThread.IncrementReferenceCount(); } mainThread.DecrementReferenceCount(); return(result); } }
public void BeginGet(string URL, Action<string> callback, bool AutoStart = true) { m_curRequest.field0 = URL; m_curRequest.field1 = HttpType.GET; this.m_SuccessEvent = callback; #if USE_COR m_curRequest.field2 =m_SuccessEvent; requestList.Push(m_curRequest); m_task = new Task (UnityConnect (), AutoStart); #else m_varUtils.field0 = 0; m_thread = KThread.StartTask(HttpThread, false); #endif }
public KernelResult Start(int mainThreadPriority, ulong stackSize) { lock (_processLock) { if (_state > ProcessState.CreatedAttached) { return(KernelResult.InvalidState); } if (ResourceLimit != null && !ResourceLimit.Reserve(LimitableResource.Thread, 1)) { return(KernelResult.ResLimitExceeded); } KResourceLimit threadResourceLimit = ResourceLimit; KResourceLimit memoryResourceLimit = null; if (_mainThreadStackSize != 0) { throw new InvalidOperationException("Trying to start a process with a invalid state!"); } ulong stackSizeRounded = BitUtils.AlignUp(stackSize, KMemoryManager.PageSize); ulong neededSize = stackSizeRounded + _imageSize; // Check if the needed size for the code and the stack will fit on the // memory usage capacity of this Process. Also check for possible overflow // on the above addition. if (neededSize > _memoryUsageCapacity || neededSize < stackSizeRounded) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.OutOfMemory); } if (stackSizeRounded != 0 && ResourceLimit != null) { memoryResourceLimit = ResourceLimit; if (!memoryResourceLimit.Reserve(LimitableResource.Memory, stackSizeRounded)) { threadResourceLimit?.Release(LimitableResource.Thread, 1); return(KernelResult.ResLimitExceeded); } } KernelResult result; KThread mainThread = null; ulong stackTop = 0; void CleanUpForError() { HandleTable.Destroy(); mainThread?.DecrementReferenceCount(); if (_mainThreadStackSize != 0) { ulong stackBottom = stackTop - _mainThreadStackSize; ulong stackPagesCount = _mainThreadStackSize / KMemoryManager.PageSize; MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack); _mainThreadStackSize = 0; } memoryResourceLimit?.Release(LimitableResource.Memory, stackSizeRounded); threadResourceLimit?.Release(LimitableResource.Thread, 1); } if (stackSizeRounded != 0) { ulong stackPagesCount = stackSizeRounded / KMemoryManager.PageSize; ulong regionStart = MemoryManager.StackRegionStart; ulong regionSize = MemoryManager.StackRegionEnd - regionStart; ulong regionPagesCount = regionSize / KMemoryManager.PageSize; result = MemoryManager.AllocateOrMapPa( stackPagesCount, KMemoryManager.PageSize, 0, false, regionStart, regionPagesCount, MemoryState.Stack, MemoryPermission.ReadAndWrite, out ulong stackBottom); if (result != KernelResult.Success) { CleanUpForError(); return(result); } _mainThreadStackSize += stackSizeRounded; stackTop = stackBottom + stackSizeRounded; } ulong heapCapacity = _memoryUsageCapacity - _mainThreadStackSize - _imageSize; result = MemoryManager.SetHeapCapacity(heapCapacity); if (result != KernelResult.Success) { CleanUpForError(); return(result); } HandleTable = new KHandleTable(System); result = HandleTable.Initialize(Capabilities.HandleTableSize); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread = new KThread(System); result = mainThread.Initialize( _entrypoint, 0, stackTop, mainThreadPriority, DefaultCpuCore, this); if (result != KernelResult.Success) { CleanUpForError(); return(result); } result = HandleTable.GenerateHandle(mainThread, out int mainThreadHandle); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread.SetEntryArguments(0, mainThreadHandle); ProcessState oldState = _state; ProcessState newState = _state != ProcessState.Created ? ProcessState.Attached : ProcessState.Started; SetState(newState); // TODO: We can't call KThread.Start from a non-guest thread. // We will need to make some changes to allow the creation of // dummy threads that will be used to initialize the current // thread on KCoreContext so that GetCurrentThread doesn't fail. /* Result = MainThread.Start(); * * if (Result != KernelResult.Success) * { * SetState(OldState); * * CleanUpForError(); * } */ mainThread.Reschedule(ThreadSchedState.Running); if (result == KernelResult.Success) { mainThread.IncrementReferenceCount(); } mainThread.DecrementReferenceCount(); return(result); } }
public void BeginDownLoadFileFlushToFile(string URL, string Filepath, Action<byte[], float, bool> callback, bool AutoStart = false) { m_curRequest.field0 = URL; m_curRequest.field1 = HttpType.DOWNLOADFILE; #if USE_COR m_curRequest.field0 = URL +";"+Filepath; m_curRequest.field2 = callback; requestList.Push(m_curRequest); m_task = new Task (UnityConnect (), AutoStart); #else this.onProcess = callback; file.field0 = Filepath; m_curRequest.field2 = file; m_thread = KThread.StartTask(ThreadDownLoad, false); #endif }
public virtual ResultCode GetClockContext(KThread thread, out SystemClockContext context) { context = _context; return(ResultCode.Success); }