Esempio n. 1
0
        public static void InitializeResourceLimit(KResourceLimit ResourceLimit)
        {
            void EnsureSuccess(KernelResult Result)
            {
                if (Result != KernelResult.Success)
                {
                    throw new InvalidOperationException($"Unexpected result \"{Result}\".");
                }
            }

            int KernelMemoryCfg = 0;

            long RamSize = GetRamSize(KernelMemoryCfg);

            EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Memory, RamSize));
            EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Thread, 800));
            EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Event, 700));
            EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.TransferMemory, 200));
            EnsureSuccess(ResourceLimit.SetLimitValue(LimitableResource.Session, 900));

            if (!ResourceLimit.Reserve(LimitableResource.Memory, 0) ||
                !ResourceLimit.Reserve(LimitableResource.Memory, 0x60000))
            {
                throw new InvalidOperationException("Unexpected failure reserving memory on resource limit.");
            }
        }
Esempio n. 2
0
        public KernelResult Initialize(
            ProcessCreationInfo creationInfo,
            int[]               caps,
            KResourceLimit resourceLimit,
            MemoryRegion memRegion)
        {
            ResourceLimit = resourceLimit;
            _memRegion    = memRegion;

            ulong personalMmHeapSize = GetPersonalMmHeapSize((ulong)creationInfo.PersonalMmHeapPagesCount, memRegion);

            ulong codePagesCount = (ulong)creationInfo.CodePagesCount;

            ulong neededSizeForProcess = personalMmHeapSize + codePagesCount * KMemoryManager.PageSize;

            if (neededSizeForProcess != 0 && resourceLimit != null)
            {
                if (!resourceLimit.Reserve(LimitableResource.Memory, neededSizeForProcess))
                {
                    return(KernelResult.ResLimitExceeded);
                }
            }

            void CleanUpForError()
            {
                if (neededSizeForProcess != 0 && resourceLimit != null)
                {
                    resourceLimit.Release(LimitableResource.Memory, neededSizeForProcess);
                }
            }

            PersonalMmHeapPagesCount = (ulong)creationInfo.PersonalMmHeapPagesCount;

            KMemoryBlockAllocator memoryBlockAllocator;

            if (PersonalMmHeapPagesCount != 0)
            {
                memoryBlockAllocator = new KMemoryBlockAllocator(PersonalMmHeapPagesCount * KMemoryManager.PageSize);
            }
            else
            {
                memoryBlockAllocator = (MmuFlags & 0x40) != 0
                    ? System.LargeMemoryBlockAllocator
                    : System.SmallMemoryBlockAllocator;
            }

            AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7);

            bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0;

            ulong codeAddress = creationInfo.CodeAddress;

            ulong codeSize = codePagesCount * KMemoryManager.PageSize;

            KernelResult result = MemoryManager.InitializeForProcess(
                addrSpaceType,
                aslrEnabled,
                !aslrEnabled,
                memRegion,
                codeAddress,
                codeSize,
                memoryBlockAllocator);

            if (result != KernelResult.Success)
            {
                CleanUpForError();

                return(result);
            }

            if (!ValidateCodeAddressAndSize(codeAddress, codeSize))
            {
                CleanUpForError();

                return(KernelResult.InvalidMemRange);
            }

            result = MemoryManager.MapNewProcessCode(
                codeAddress,
                codePagesCount,
                MemoryState.CodeStatic,
                MemoryPermission.None);

            if (result != KernelResult.Success)
            {
                CleanUpForError();

                return(result);
            }

            result = Capabilities.InitializeForUser(caps, MemoryManager);

            if (result != KernelResult.Success)
            {
                CleanUpForError();

                return(result);
            }

            Pid = System.GetProcessId();

            if (Pid == -1 || (ulong)Pid < Horizon.InitialProcessId)
            {
                throw new InvalidOperationException($"Invalid Process Id {Pid}.");
            }

            result = ParseProcessInfo(creationInfo);

            if (result != KernelResult.Success)
            {
                CleanUpForError();
            }

            return(result);
        }
Esempio n. 3
0
        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()
                {
                    mainThread?.Terminate();
                    HandleTable.Destroy();

                    if (_mainThreadStackSize != 0)
                    {
                        ulong stackBottom = stackTop - _mainThreadStackSize;

                        ulong stackPagesCount = _mainThreadStackSize / KMemoryManager.PageSize;

                        MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack);
                    }

                    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);

                return(result);
            }
        }
Esempio n. 4
0
        public KernelResult Initialize(
            ProcessCreationInfo CreationInfo,
            int[]               Caps,
            KResourceLimit ResourceLimit,
            MemoryRegion MemRegion)
        {
            this.ResourceLimit = ResourceLimit;
            this.MemRegion     = MemRegion;

            ulong PersonalMmHeapSize = GetPersonalMmHeapSize((ulong)CreationInfo.PersonalMmHeapPagesCount, MemRegion);

            ulong CodePagesCount = (ulong)CreationInfo.CodePagesCount;

            ulong NeededSizeForProcess = PersonalMmHeapSize + CodePagesCount * KMemoryManager.PageSize;

            if (NeededSizeForProcess != 0 && ResourceLimit != null)
            {
                if (!ResourceLimit.Reserve(LimitableResource.Memory, NeededSizeForProcess))
                {
                    return(KernelResult.ResLimitExceeded);
                }
            }

            void CleanUpForError()
            {
                if (NeededSizeForProcess != 0 && ResourceLimit != null)
                {
                    ResourceLimit.Release(LimitableResource.Memory, NeededSizeForProcess);
                }
            }

            PersonalMmHeapPagesCount = (ulong)CreationInfo.PersonalMmHeapPagesCount;

            KMemoryBlockAllocator MemoryBlockAllocator;

            if (PersonalMmHeapPagesCount != 0)
            {
                MemoryBlockAllocator = new KMemoryBlockAllocator(PersonalMmHeapPagesCount * KMemoryManager.PageSize);
            }
            else
            {
                MemoryBlockAllocator = (MmuFlags & 0x40) != 0
                    ? System.LargeMemoryBlockAllocator
                    : System.SmallMemoryBlockAllocator;
            }

            AddressSpaceType AddrSpaceType = (AddressSpaceType)((CreationInfo.MmuFlags >> 1) & 7);

            bool AslrEnabled = ((CreationInfo.MmuFlags >> 5) & 1) != 0;

            ulong CodeAddress = CreationInfo.CodeAddress;

            ulong CodeSize = CodePagesCount * KMemoryManager.PageSize;

            KernelResult Result = MemoryManager.InitializeForProcess(
                AddrSpaceType,
                AslrEnabled,
                !AslrEnabled,
                MemRegion,
                CodeAddress,
                CodeSize,
                MemoryBlockAllocator);

            if (Result != KernelResult.Success)
            {
                CleanUpForError();

                return(Result);
            }

            if (!ValidateCodeAddressAndSize(CodeAddress, CodeSize))
            {
                CleanUpForError();

                return(KernelResult.InvalidMemRange);
            }

            Result = MemoryManager.MapNewProcessCode(
                CodeAddress,
                CodePagesCount,
                MemoryState.CodeStatic,
                MemoryPermission.None);

            if (Result != KernelResult.Success)
            {
                CleanUpForError();

                return(Result);
            }

            Result = Capabilities.InitializeForUser(Caps, MemoryManager);

            if (Result != KernelResult.Success)
            {
                CleanUpForError();

                return(Result);
            }

            Pid = System.GetProcessId();

            if (Pid == -1 || (ulong)Pid < Horizon.InitialProcessId)
            {
                throw new InvalidOperationException($"Invalid Process Id {Pid}.");
            }

            Result = ParseProcessInfo(CreationInfo);

            if (Result != KernelResult.Success)
            {
                CleanUpForError();
            }

            return(Result);
        }