private void UndefinedInstructionHandler(IExecutionContext context, ulong address, int opCode) { KernelStatic.GetCurrentThread().PrintGuestStackTrace(); KernelStatic.GetCurrentThread()?.PrintGuestRegisterPrintout(); throw new UndefinedInstructionException(address, opCode); }
public void TerminateCurrentProcess() { bool shallTerminate = false; KernelContext.CriticalSection.Enter(); lock (_processLock) { if (State >= ProcessState.Started) { if (State == ProcessState.Started || State == ProcessState.Attached || State == ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); shallTerminate = true; } } } KernelContext.CriticalSection.Leave(); if (shallTerminate) { UnpauseAndTerminateAllThreadsExcept(KernelStatic.GetCurrentThread()); HandleTable.Destroy(); // NOTE: this is supposed to be called in receiving of the mailbox. SignalExitToDebugExited(); SignalExit(); } }
private void InterruptHandler(object sender, EventArgs e) { KThread currentThread = KernelStatic.GetCurrentThread(); if (currentThread.Owner != null && currentThread.GetUserDisableCount() != 0 && currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null) { KernelContext.CriticalSection.Enter(); currentThread.Owner.PinThread(currentThread); currentThread.SetUserInterruptFlag(); if (currentThread.IsSchedulable) { KernelContext.Schedulers[currentThread.CurrentCore].Schedule(); } KernelContext.CriticalSection.Leave(); } else if (currentThread.IsSchedulable) { KernelContext.Schedulers[currentThread.CurrentCore].Schedule(); } currentThread.HandlePostSyscall(); }
public KernelResult Unmap(ulong address, ulong size) { if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) { return(KernelResult.InvalidSize); } lock (_lock) { KProcess process = KernelStatic.GetCurrentProcess(); KernelResult result = process.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeWritable); if (result != KernelResult.Success) { return(result); } Debug.Assert(_isMapped); _isMapped = false; } return(KernelResult.Success); }
public KernelResult Map(ulong address, ulong size, KMemoryPermission perm) { if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) { return(KernelResult.InvalidSize); } lock (_lock) { if (_isMapped) { return(KernelResult.InvalidState); } KProcess process = KernelStatic.GetCurrentProcess(); KernelResult result = process.MemoryManager.MapPages(address, _pageList, MemoryState.CodeWritable, KMemoryPermission.ReadAndWrite); if (result != KernelResult.Success) { return(result); } _isMapped = true; } return(KernelResult.Success); }
public KernelResult ArbitrateUnlock(ulong mutexAddress) { _context.CriticalSection.Enter(); KThread currentThread = KernelStatic.GetCurrentThread(); (int mutexValue, KThread newOwnerThread) = MutexUnlock(currentThread, mutexAddress); KernelResult result = KernelResult.Success; if (!KernelTransfer.KernelToUserInt32(_context, mutexAddress, mutexValue)) { result = KernelResult.InvalidMemState; } if (result != KernelResult.Success && newOwnerThread != null) { newOwnerThread.SignaledObj = null; newOwnerThread.ObjSyncResult = result; } _context.CriticalSection.Leave(); return(result); }
public KernelResult ConnectLight(out KLightClientSession clientSession) { clientSession = null; KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.ResourceLimit != null && !currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1)) { return(KernelResult.ResLimitExceeded); } if (!IncrementSessionsCount()) { currentProcess.ResourceLimit?.Release(LimitableResource.Session, 1); return(KernelResult.SessionCountExceeded); } KLightSession session = new KLightSession(KernelContext); KernelResult result = _parent.EnqueueIncomingLightSession(session.ServerSession); if (result != KernelResult.Success) { session.ClientSession.DecrementReferenceCount(); session.ServerSession.DecrementReferenceCount(); return(result); } clientSession = session.ClientSession; return(result); }
public void SvcCall(IExecutionContext context, ulong address, int id) { KThread currentThread = KernelStatic.GetCurrentThread(); if (currentThread.Owner != null && currentThread.GetUserDisableCount() != 0 && currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null) { _context.CriticalSection.Enter(); currentThread.Owner.PinThread(currentThread); currentThread.SetUserInterruptFlag(); _context.CriticalSection.Leave(); } if (context.IsAarch32) { SyscallDispatch.Dispatch32(_context.Syscall, context, id); } else { SyscallDispatch.Dispatch64(_context.Syscall, context, id); } currentThread.HandlePostSyscall(); }
public static void Yield(KernelContext context) { KThread currentThread = KernelStatic.GetCurrentThread(); if (!currentThread.IsSchedulable) { return; } context.CriticalSection.Enter(); if (currentThread.SchedFlags != ThreadSchedState.Running) { context.CriticalSection.Leave(); return; } KThread nextThread = context.PriorityQueue.Reschedule(currentThread.DynamicPriority, currentThread.ActiveCore, currentThread); if (nextThread != currentThread) { context.ThreadReselectionRequested = true; } context.CriticalSection.Leave(); }
private void UndefinedInstructionHandler(object sender, InstUndefinedEventArgs e) { KernelStatic.GetCurrentThread().PrintGuestStackTrace(); KernelStatic.GetCurrentThread()?.PrintGuestRegisterPrintout(); throw new UndefinedInstructionException(e.Address, e.OpCode); }
public KernelResult Map(ulong address, ulong size, KMemoryPermission perm) { if (_pageCount != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) { return(KernelResult.InvalidSize); } lock (_lock) { if (_isMapped) { return(KernelResult.InvalidState); } KProcess proc = KernelStatic.GetCurrentProcess(); // TODO: Mark pages as MemoryState.CodeWritable KernelResult resultCode = proc.MemoryManager.MapPages(address, _hostPagelist, KMemoryPermission.ReadAndWrite); if (resultCode != KernelResult.Success) { return(KernelResult.InvalidState); } _isMapped = true; } return(KernelResult.Success); }
private void InterruptHandler(IExecutionContext context) { KThread currentThread = KernelStatic.GetCurrentThread(); if (currentThread.Context.Running && currentThread.Owner != null && currentThread.GetUserDisableCount() != 0 && currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null) { KernelContext.CriticalSection.Enter(); currentThread.Owner.PinThread(currentThread); currentThread.SetUserInterruptFlag(); KernelContext.CriticalSection.Leave(); } if (currentThread.IsSchedulable) { KernelContext.Schedulers[currentThread.CurrentCore].Schedule(); } currentThread.HandlePostSyscall(); }
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(); } // 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(); } } // 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(); } }
private bool InvalidAccessHandler(ulong va) { KernelStatic.GetCurrentThread()?.PrintGuestStackTrace(); Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}."); return(false); }
public void WaitIsAllocatingEvent() { Monitor.Exit(Lock); KernelStatic.YieldUntilCompletion(WaitForLock); Monitor.Enter(Lock); }
public void WaitDequeueEvent() { Monitor.Exit(Lock); KernelStatic.YieldUntilCompletion(WaitForLock); Monitor.Enter(Lock); }
public static void EnableScheduling(KernelContext context, ulong scheduledCoresMask) { KScheduler currentScheduler = context.Schedulers[KernelStatic.GetCurrentThread().CurrentCore]; // Note that "RescheduleCurrentCore" will block, so "RescheduleOtherCores" must be done first. currentScheduler.RescheduleOtherCores(scheduledCoresMask); currentScheduler.RescheduleCurrentCore(); }
public static void YieldWithLoadBalancing(KernelContext context) { KThread currentThread = KernelStatic.GetCurrentThread(); context.CriticalSection.Enter(); if (currentThread.SchedFlags != ThreadSchedState.Running) { context.CriticalSection.Leave(); return; } int prio = currentThread.DynamicPriority; int core = currentThread.ActiveCore; // Move current thread to the end of the queue. KThread nextThread = context.PriorityQueue.Reschedule(prio, core, currentThread); IEnumerable <KThread> SuitableCandidates() { foreach (KThread suggested in context.PriorityQueue.SuggestedThreads(core)) { int suggestedCore = suggested.ActiveCore; if (suggestedCore >= 0) { KThread selectedSuggestedCore = context.Schedulers[suggestedCore]._state.SelectedThread; if (selectedSuggestedCore == suggested || (selectedSuggestedCore != null && selectedSuggestedCore.DynamicPriority < 2)) { continue; } } // If the candidate was scheduled after the current thread, then it's not worth it, // unless the priority is higher than the current one. if (suggested.LastScheduledTime <= nextThread.LastScheduledTime || suggested.DynamicPriority < nextThread.DynamicPriority) { yield return(suggested); } } } KThread dst = SuitableCandidates().FirstOrDefault(x => x.DynamicPriority <= prio); if (dst != null) { context.PriorityQueue.TransferToCore(dst.DynamicPriority, core, dst); context.ThreadReselectionRequested = true; } else if (currentThread != nextThread) { context.ThreadReselectionRequested = true; } context.CriticalSection.Leave(); }
public static void YieldToAnyThread(KernelContext context) { KThread currentThread = KernelStatic.GetCurrentThread(); context.CriticalSection.Enter(); if (currentThread.SchedFlags != ThreadSchedState.Running) { context.CriticalSection.Leave(); return; } int core = currentThread.ActiveCore; context.PriorityQueue.TransferToCore(currentThread.DynamicPriority, -1, currentThread); if (!context.PriorityQueue.ScheduledThreads(core).Any()) { KThread selectedThread = null; foreach (KThread suggested in context.PriorityQueue.SuggestedThreads(core)) { int suggestedCore = suggested.ActiveCore; if (suggestedCore < 0) { continue; } KThread firstCandidate = context.PriorityQueue.ScheduledThreads(suggestedCore).FirstOrDefault(); if (firstCandidate == suggested) { continue; } if (firstCandidate == null || firstCandidate.DynamicPriority >= 2) { context.PriorityQueue.TransferToCore(suggested.DynamicPriority, core, suggested); } selectedThread = suggested; break; } if (currentThread != selectedThread) { context.ThreadReselectionRequested = true; } } else { context.ThreadReselectionRequested = true; } context.CriticalSection.Leave(); }
private MessageHeader GetServerMessageHeader(Message serverMsg) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); uint word0 = currentProcess.CpuMemory.Read <uint>(serverMsg.Address + 0); uint word1 = currentProcess.CpuMemory.Read <uint>(serverMsg.Address + 4); uint word2 = currentProcess.CpuMemory.Read <uint>(serverMsg.Address + 8); return(new MessageHeader(word0, word1, word2)); }
private void InterruptHandler(object sender, EventArgs e) { KThread currentThread = KernelStatic.GetCurrentThread(); if (currentThread.IsSchedulable) { KernelContext.Schedulers[currentThread.CurrentCore].Schedule(); } currentThread.HandlePostSyscall(); }
public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context) { _parent = parent; ParentPort = parentPort; parentPort?.IncrementReferenceCount(); State = ChannelState.Open; CreatorProcess = KernelStatic.GetCurrentProcess(); CreatorProcess.IncrementReferenceCount(); }
public KernelResult Initialize(ulong address, ulong size) { _owner = KernelStatic.GetCurrentProcess(); _hostPagelist = _owner.MemoryManager.GetPhysicalRegions(address, size); _pageCount = BitUtils.DivRoundUp(size, KPageTableBase.PageSize); _isOwnerMapped = false; _isMapped = false; return(KernelResult.Success); }
public KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) { KThread currentThread = KernelStatic.GetCurrentThread(); _context.CriticalSection.Enter(); currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.Success; KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (!KernelTransfer.UserToKernelInt32(_context, mutexAddress, out int mutexValue)) { _context.CriticalSection.Leave(); return(KernelResult.InvalidMemState); } if (mutexValue != (ownerHandle | HasListenersMask)) { _context.CriticalSection.Leave(); return(0); } KThread mutexOwner = currentProcess.HandleTable.GetObject <KThread>(ownerHandle); if (mutexOwner == null) { _context.CriticalSection.Leave(); return(KernelResult.InvalidHandle); } currentThread.MutexAddress = mutexAddress; currentThread.ThreadHandleForUserMutex = requesterHandle; mutexOwner.AddMutexWaiter(currentThread); currentThread.Reschedule(ThreadSchedState.Paused); _context.CriticalSection.Leave(); _context.CriticalSection.Enter(); if (currentThread.MutexOwner != null) { currentThread.MutexOwner.RemoveMutexWaiter(currentThread); } _context.CriticalSection.Leave(); return(currentThread.ObjSyncResult); }
public static bool KernelToUser <T>(ulong address, T value) where T : unmanaged { KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)Unsafe.SizeOf <T>())) { currentProcess.CpuMemory.Write(address, value); return(true); } return(false); }
public KernelResult SendAsyncRequest(KWritableEvent asyncEvent, ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread currentThread = KernelStatic.GetCurrentThread(); KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize, asyncEvent); KernelContext.CriticalSection.Enter(); KernelResult result = _parent.ServerSession.EnqueueRequest(request); KernelContext.CriticalSection.Leave(); return(result); }
public static bool KernelToUserInt64(KernelContext context, ulong address, long value) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsMapped(address) && currentProcess.CpuMemory.IsMapped(address + 7)) { currentProcess.CpuMemory.Write(address, value); return(true); } return(false); }
public static bool UserToKernelString(out string value, ulong address, uint size) { KProcess currentProcess = KernelStatic.GetCurrentProcess(); if (currentProcess.CpuMemory.IsRangeMapped(address, size)) { value = MemoryHelper.ReadAsciiString(currentProcess.CpuMemory, address, size); return(true); } value = null; return(false); }
// AtmosphereGetProcessInfo(os::ProcessId process_id) -> sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status public ResultCode GetProcessInfo(ServiceCtx context) { ulong pid = context.RequestData.ReadUInt64(); KProcess process = KernelStatic.GetProcessByPid(pid); if (context.Process.HandleTable.GenerateHandle(process, out int processHandle) != KernelResult.Success) { throw new System.Exception("Out of handles!"); } context.Response.HandleDesc = IpcHandleDesc.MakeCopy(processHandle); return(ResultCode.Success); }
public static bool UserToKernelArray <T>(ulong address, Span <T> values) where T : unmanaged { KProcess currentProcess = KernelStatic.GetCurrentProcess(); Span <byte> data = MemoryMarshal.Cast <T, byte>(values); if (currentProcess.CpuMemory.IsRangeMapped(address, (ulong)data.Length)) { currentProcess.CpuMemory.Read(address, data); return(true); } return(false); }