Example #1
0
        private KernelResult AllocateTlsPage(out KTlsPageInfo pageInfo)
        {
            pageInfo = default(KTlsPageInfo);

            if (!System.UserSlabHeapPages.TryGetItem(out ulong tlsPagePa))
            {
                return(KernelResult.OutOfMemory);
            }

            ulong regionStart = MemoryManager.TlsIoRegionStart;
            ulong regionSize  = MemoryManager.TlsIoRegionEnd - regionStart;

            ulong regionPagesCount = regionSize / KMemoryManager.PageSize;

            KernelResult result = MemoryManager.AllocateOrMapPa(
                1,
                KMemoryManager.PageSize,
                tlsPagePa,
                true,
                regionStart,
                regionPagesCount,
                MemoryState.ThreadLocal,
                MemoryPermission.ReadAndWrite,
                out ulong tlsPageVa);

            if (result != KernelResult.Success)
            {
                System.UserSlabHeapPages.Free(tlsPagePa);
            }
            else
            {
                pageInfo = new KTlsPageInfo(tlsPageVa);

                MemoryHelper.FillWithZeros(CpuMemory, (long)tlsPageVa, KMemoryManager.PageSize);
            }

            return(result);
        }
Example #2
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()
                {
                    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);
            }
        }
Example #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);
            }
        }