Esempio n. 1
0
        private void UndefinedInstructionHandler(IExecutionContext context, ulong address, int opCode)
        {
            KernelStatic.GetCurrentThread().PrintGuestStackTrace();
            KernelStatic.GetCurrentThread()?.PrintGuestRegisterPrintout();

            throw new UndefinedInstructionException(address, opCode);
        }
Esempio n. 2
0
        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();
            }
        }
Esempio n. 3
0
        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();
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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();
        }
Esempio n. 9
0
        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();
        }
Esempio n. 10
0
        private void UndefinedInstructionHandler(object sender, InstUndefinedEventArgs e)
        {
            KernelStatic.GetCurrentThread().PrintGuestStackTrace();
            KernelStatic.GetCurrentThread()?.PrintGuestRegisterPrintout();

            throw new UndefinedInstructionException(e.Address, e.OpCode);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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();
        }
Esempio n. 13
0
        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();
            }
        }
Esempio n. 14
0
        private bool InvalidAccessHandler(ulong va)
        {
            KernelStatic.GetCurrentThread()?.PrintGuestStackTrace();

            Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}.");

            return(false);
        }
Esempio n. 15
0
        public void WaitIsAllocatingEvent()
        {
            Monitor.Exit(Lock);

            KernelStatic.YieldUntilCompletion(WaitForLock);

            Monitor.Enter(Lock);
        }
Esempio n. 16
0
        public void WaitDequeueEvent()
        {
            Monitor.Exit(Lock);

            KernelStatic.YieldUntilCompletion(WaitForLock);

            Monitor.Enter(Lock);
        }
Esempio n. 17
0
        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();
        }
Esempio n. 18
0
        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();
        }
Esempio n. 19
0
        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();
        }
Esempio n. 20
0
        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));
        }
Esempio n. 21
0
        private void InterruptHandler(object sender, EventArgs e)
        {
            KThread currentThread = KernelStatic.GetCurrentThread();

            if (currentThread.IsSchedulable)
            {
                KernelContext.Schedulers[currentThread.CurrentCore].Schedule();
            }

            currentThread.HandlePostSyscall();
        }
Esempio n. 22
0
        public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context)
        {
            _parent    = parent;
            ParentPort = parentPort;

            parentPort?.IncrementReferenceCount();

            State = ChannelState.Open;

            CreatorProcess = KernelStatic.GetCurrentProcess();
            CreatorProcess.IncrementReferenceCount();
        }
Esempio n. 23
0
        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);
        }
Esempio n. 24
0
        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);
        }
Esempio n. 25
0
        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);
        }
Esempio n. 26
0
        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);
        }
Esempio n. 27
0
        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);
        }
Esempio n. 28
0
        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);
        }
Esempio n. 30
0
        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);
        }