Пример #1
0
        public virtual void Setup(MemoryRegion region, AddressSpaceKind addressSpaceKind)
        {
            AddressSpaceKind = addressSpaceKind;
            region.Size      = KMath.FloorToPowerOfTwo(region.Size);
            _Region          = region;
            var totalPages = region.Size >> BuddyAllocatorImplementation.BUDDY_PAGE_SHIFT;

            KernelMessage.WriteLine("Init Allocator: StartAddr: {0}, {1} Pages", region.Start, totalPages);
            // init global memory block
            // all pages area
            var pages_size = totalPages * (uint)sizeof(Page);

            KernelMessage.WriteLine("Page Array Size in bytes: {0}", pages_size);
            Pages = (Page *)AllocRawMemory(pages_size).Start;
            KernelMessage.WriteLine("Page Array Addr: {0:X8}", (uint)Pages);
            var start_addr = region.Start;

            Zone.free_area = (BuddyAllocatorImplementation.free_area *)AllocRawMemory(BuddyAllocatorImplementation.BUDDY_MAX_ORDER * (uint)sizeof(BuddyAllocatorImplementation.free_area)).Start;

            fixed(BuddyAllocatorImplementation.mem_zone *zone = &Zone)
            ZonePtr = zone;

            BuddyAllocatorImplementation.buddy_system_init(
                ZonePtr,
                Pages,
                start_addr,
                totalPages);
        }
Пример #2
0
        public static MemoryRegion AllocateRegion(this IPageFrameAllocator allocator, USize size, AllocatePageOptions options = default)
        {
            var pages = KMath.DivCeil(size, 4096);
            var p     = allocator.AllocatePages(pages, options);

            return(new MemoryRegion(allocator.GetAddress(p), pages * 4096));
        }
Пример #3
0
        public MemoryRegion FitToPageCeil()
        {
            var start = KMath.AlignValueCeil(Start, 4096);
            var end   = KMath.AlignValueCeil(Start + Size, 4096);

            return(FromLocation(start, end));
        }
Пример #4
0
        private static unsafe int ReadResultDisk(int msgId, byte *buf, uint bufSize)
        {
            var lineType = ReadByte();

            Assert.True(lineType == (byte)LineType.ResultFile);

            var msgId_ = ReadInt32();

            Assert.True(msgId_ == msgId);

            var len = ReadInt32();

            Assert.True(len <= bufSize);

            if (len <= 0)
            {
                return(0);
            }

            var blocks = KMath.DivCeil((uint)len, 512);
            var tmpBuf = new byte[blocks * 512];

            SharedDisk.ReadBlock(0, blocks, tmpBuf);

            for (var i = 0; i < len; i++)
            {
                buf[i] = tmpBuf[i];
            }

            RuntimeMemory.FreeObject(tmpBuf);

            return(len);
        }
Пример #5
0
        public static MemoryRegion AllocateRegion(USize size, AllocatePageOptions options = default)
        {
            var pages = KMath.DivCeil(size, 4096);
            var start = AllocatePages(pages, options);

            return(new MemoryRegion(start, pages * 4096));
        }
Пример #6
0
        public void Setup(MemoryRegion region, AddressSpaceKind addrKind)
        {
            TraceOptions      = new PageFrameAllocatorTraceOptions();
            _AddressSpaceKind = addrKind;
            _Region           = region;
            FistPageNum       = region.Start / PageSize;
            _TotalPages       = region.Size / PageSize;
            kmap      = AllocRawMemory(_TotalPages * (uint)sizeof(Page));
            PageArray = (Page *)kmap.Start;

            var firstSelfPageNum = KMath.DivFloor(kmap.Start, 4096);
            var selfPages        = KMath.DivFloor(kmap.Size, 4096);

            KernelMessage.WriteLine("Page Frame Array allocated {0} pages, beginning with page {1} at {2:X8}", selfPages, firstSelfPageNum, (uint)PageArray);

            PageTable.KernelTable.SetWritable(kmap.Start, kmap.Size);
            kmap.Clear();

            var addr = FistPageNum * 4096;

            for (uint i = 0; i < _TotalPages; i++)
            {
                //KernelMessage.WriteLine(i);
                PageArray[i].Address = addr;
                //if (i != 0)
                //    PageArray[i - 1].Next = &PageArray[i];
                addr += 4096;
            }

            KernelMessage.WriteLine("Setup free memory");
            SetupFreeMemory();
            KernelMessage.WriteLine("Build linked lists");
            BuildLinkedLists();
            KernelMessage.WriteLine("Build linked lists done");

            _FreePages = 0;
            for (uint i = 0; i < _TotalPages; i++)
            {
                if (PageArray[i].Status == PageStatus.Free)
                {
                    _FreePages++;
                }
            }

            //Assert.True(list_head.list_count(FreeList) == _FreePages, "list_head.list_count(FreeList) == _FreePages");
            var debugCheckCount = list_head.list_count(FreeList);

            if (debugCheckCount != _FreePages)
            {
                KernelMessage.WriteLine("debugCheckCount {0} != {1}", debugCheckCount, _FreePages);
                Debug.Break();
            }

            KernelMessage.Path(DebugName, "Pages Free: {0}", FreePages);
        }
Пример #7
0
        private static uint Cmd_GetPhysicalMemory(SysCallContext *context, SystemMessage *args)
        {
            var physAddr = args->Arg1;
            var pages    = KMath.DivCeil(args->Arg2, 4096);

            KernelMessage.WriteLine("Got Request for {0:X8} pages at Physical Addr {1:X8}", pages, physAddr);
            var proc     = Scheduler.GetCurrentThread().Process;
            var virtAddr = proc.UserPageAllocator.AllocatePagesAddr(pages);

            proc.PageTable.Map(virtAddr, physAddr, pages * 4096);
            return(virtAddr);
        }
Пример #8
0
        private static uint Cmd_RequestMemory(SysCallContext *context, SystemMessage *args)
        {
            var size = args->Arg1;

            size = KMath.AlignValueCeil(size, 4096);
            var proc     = Scheduler.GetCurrentThread().Process;
            var map      = PhysicalPageManager.AllocateRegion(size);
            var virtAddr = proc.UserPageAllocator.AllocatePagesAddr(size / 4096);

            Scheduler.GetCurrentThread().Process.PageTable.Map(virtAddr, map.Start, PhysicalPageManager.GetAllocatorByAddr(map.Start));
            return(virtAddr);
        }
Пример #9
0
        internal static unsafe void SetupAllocator()
        {
            Allocator = new RuntimeAllocator();
            var ptr = (byte *)SysCalls.RequestMemory(KMath.AlignValueCeil(Allocator.headSize, 4096));

            for (var i = 0; i < Allocator.headSize; i++)
            {
                *(ptr + i) = 0; // TODO: Optimize
            }
            Allocator.List_heads = (malloc_meta **)ptr;
            AllocatorInitialized = true;
        }
Пример #10
0
        public static void Setup()
        {
            KernelMessage.WriteLine("Multiboot Flags: {0:X}", Multiboot.Flags);
            BootInfo            = (BootInfoHeader *)Address.KernelBootInfo;
            BootInfo->Magic     = lonos.kernel.core.BootInfoHeader.BootInfoMagic;
            BootInfo->HeapStart = KMath.AlignValueCeil(Address.OriginalKernelElfSection + LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000);
            BootInfo->HeapSize  = 0;

            BootInfo->InstalledPhysicalMemory = 128 * 1024 * 1024;

            SetupVideoInfo();
            SetupMemoryMap();
        }
Пример #11
0
        private static uint Cmd_RequestMessageBuffer(SysCallContext *context, SystemMessage *args)
        {
            var size            = args->Arg1;
            var targetProcessID = (int)args->Arg2;
            var pages           = KMath.DivCeil(size, 4096);

            var currentProc  = Scheduler.GetCurrentThread().Process;
            var tableCurrent = currentProc.PageTable;

            var targetProc = ProcessManager.System;

            if (targetProcessID > 0)
            {
                targetProc = ProcessManager.GetProcess(targetProcessID);
            }
            var tableTarget = targetProc.PageTable;

            var virtHead = VirtualPageManager.AllocatePages(
                pages,
                new AllocatePageOptions
            {
                Pool = PageAllocationPool.Global,
            });

            var virtAddr = virtHead;

            for (var pageIdx = 0; pageIdx < pages; pageIdx++)
            {
                var physAddr = PageTable.KernelTable.GetPhysicalAddressFromVirtual(virtAddr);

                if (tableCurrent != PageTable.KernelTable)
                {
                    tableCurrent.Map(virtAddr, physAddr, flush: true);
                }

                if (tableTarget != PageTable.KernelTable)
                {
                    tableTarget.Map(virtAddr, physAddr, flush: true);
                }

                virtAddr += 4096;
            }

            // TODO: implement TargetProcess.RegisterMessageBuffer, because of individual VirtAddr

            currentProc.GlobalAllocations.Add(new GlobalAllocation {
                Addr = virtHead, TargetProcID = targetProcessID
            });

            return(virtHead);
        }
Пример #12
0
        public static void Setup()
        {
            KernelMessage.WriteLine("Multiboot Flags: {0:X}", Multiboot.Flags);
            BootInfo            = (BootInfoHeader *)Address.KernelBootInfo;
            BootInfo->Magic     = BootInfoHeader.BootInfoMagic;
            BootInfo->HeapStart = KMath.AlignValueCeil(Address.OriginalKernelElfSection + LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000);
            BootInfo->HeapSize  = 0;

            BootInfo->InstalledPhysicalMemory = 256 * 1024 * 1024;
            BootInfo->PageTableType           = KConfig.UsePAE ? PageTableType.PAE : PageTableType.X86;
            BootInfo->KernelBootStartCycles   = PerformanceCounter.KernelBootStartCycles;

            SetupVideoInfo();
            SetupMemoryMap();
        }
Пример #13
0
        public unsafe override void SetWritable(uint virtAddr, uint size)
        {
            //KernelMessage.WriteLine("Unprotect Memory: Start={0:X}, End={1:X}", virtAddr, virtAddr + size);
            var pages = KMath.DivCeil(size, 4096);

            for (var i = 0; i < pages; i++)
            {
                var entry = GetTableEntry(virtAddr);
                entry->Writable = true;

                virtAddr += 4096;
            }

            Flush();
        }
Пример #14
0
        public unsafe static void Setup()
        {
            kmallocAllocator = new Allocator();

            var ptr = (byte *)RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(KMath.AlignValueCeil(Allocator.headSize, 4096));

            for (var i = 0; i < Allocator.headSize; i++)
            {
                *(ptr + i) = 0;
            }
            kmallocAllocator.list_heads = (malloc_meta **)ptr;
            ManagedMemoy.useAllocator   = true;

            KernelMessage.WriteLine("Memory free: {0} MB", (PageFrameManager.PagesAvailable * 4096) / 1024 / 1024);
        }
Пример #15
0
        public static unsafe void Setup()
        {
            kmallocAllocator = new KernelAllocator();

            var ptr = (byte *)VirtualPageManager.AllocatePages(KMath.AlignValueCeil(Allocator.headSize, 4096));

            for (var i = 0; i < Allocator.headSize; i++)
            {
                *(ptr + i) = 0;
            }
            kmallocAllocator.List_heads = (malloc_meta **)ptr;
            ManagedMemory.UseAllocator  = true;
            KernelMessage.WriteLine("EarlyBootBytesUsed: {0} bytes", ManagedMemory.EarlyBootBytesUsed);

            KernelMessage.WriteLine("Memory free: {0} MB", PhysicalPageManager.FreePages * 4096 / 1024 / 1024);
        }
Пример #16
0
        public void Setup(MemoryRegion region, AddressSpaceKind addrKind)
        {
            _Requests = 0;
            _Releases = 0;

            _AddressSpaceKind = addrKind;
            _Region           = region;
            FistPageNum       = region.Start / PageSize;
            _TotalPages       = region.Size / PageSize;
            kmap        = AllocRawMemory(_TotalPages * (uint)sizeof(Page));
            PageArray   = (Page *)kmap.Start;
            NextTryPage = PageArray;

            var firstSelfPageNum = KMath.DivFloor(kmap.Start, 4096);
            var selfPages        = KMath.DivFloor(kmap.Size, 4096);

            KernelMessage.WriteLine("Page Frame Array allocated {0} pages, beginning with page {1}", selfPages, firstSelfPageNum);

            PageTableExtensions.SetWritable(PageTable.KernelTable, kmap.Start, kmap.Size);
            kmap.Clear();

            var addr = FistPageNum * 4096;

            for (uint i = 0; i < _TotalPages; i++)
            {
                PageArray[i].Address = addr;
                //if (i != 0)
                //    PageArray[i - 1].Next = &PageArray[i];
                addr += 4096;
            }

            SetupFreeMemory();

            _FreePages = 0;
            for (uint i = 0; i < _TotalPages; i++)
            {
                if (PageArray[i].Status == PageStatus.Free)
                {
                    _FreePages++;
                }
            }

            KernelMessage.WriteLine("Pages Free: {0}", FreePages);
        }
Пример #17
0
        public async Task BotInfoCommand()
        {
            var Data             = KMath.CalculateTime(DiscordBot.Instance.UpTime, DateTime.Now);
            int UserAmount       = (await Guild.GetMembersAsync()).Length;
            var commandCallValue = await DiscordBot.Instance.cacheManger.GetAsync("CommandCall");

            var messageCallValue = await DiscordBot.Instance.cacheManger.GetAsync("MessageCall");

            var        memoryUsage = Process.GetCurrentProcess().PrivateMemorySize64 / 1000 / 1000;
            EmbedMaker maker       = new EmbedMaker();

            maker.setTitle("Kururu's info")
            .addField("Info", $"This bot is running in {await Program.GuildsData.CountAsync()} Servers")
            .addInlineField("Language", "c#").addInlineField("Owner", "Hedari")
            .addInlineField("Commands", commandCallValue)
            .addInlineField("Messages", messageCallValue)
            .addInlineField("Memory Usage", $"{memoryUsage} MB")
            .addField("Runtime", $"This bot has been running for, {Data.Days} Day, {Data.Hours} Hour, {Data.Minutes} Minute and {Data.Seconds} Second");
            await Channel.SendMessageAsync("", false, maker);
        }
Пример #18
0
        public static void UnMap(this IPageTable table, Addr virtAddr, USize length, bool flush = false)
        {
            if (KConfig.Log.MemoryMapping && length > 4096)
            {
                KernelMessage.WriteLine("UnMap: virt={0:X8}, length={2:X8}", virtAddr, length);
            }

            var pages = KMath.DivCeil(length, 4096);

            for (var i = 0; i < pages; i++)
            {
                table.MapVirtualAddressToPhysical(virtAddr, 0, false);

                virtAddr += 4096;
            }
            if (flush)
            {
                table.Flush();
            }
        }
Пример #19
0
        public unsafe static void InitialKernelProtect_MakeWritable_BySize(uint virtAddr, uint size)
        {
            if (!UseKernelWriteProtection)
            {
                return;
            }

            //KernelMessage.WriteLine("Unprotect Memory: Start={0:X}, End={1:X}", virtAddr, virtAddr + size);
            var pages = KMath.DivCeil(size, 4096);

            for (var i = 0; i < pages; i++)
            {
                var entry = PageTable.GetTableEntry(virtAddr);
                entry->Writable = true;

                virtAddr += 4096;
            }

            Native.SetCR3(PageTable.AddrPageDirectory);
        }
Пример #20
0
        /// <summary>
        /// Sync specific mappings with another table.
        /// </summary>
        public static void MapCopy(this IPageTable table, IPageTable fromTable, Addr virtAddr, USize length, bool present = true, bool flush = false)
        {
            if (KConfig.Log.MemoryMapping && length > 4096)
            {
                KernelMessage.WriteLine("MapCopy: virt={0:X8}, length={1:X8}", virtAddr, length);
            }

            var pages = KMath.DivCeil(length, 4096);

            for (var i = 0; i < pages; i++)
            {
                var physAddr = fromTable.GetPhysicalAddressFromVirtual(virtAddr);
                table.MapVirtualAddressToPhysical(virtAddr, physAddr, present);

                virtAddr += 4096;
            }
            if (flush)
            {
                table.Flush();
            }
        }
Пример #21
0
        private void SetInitialPageStatus(KernelMemoryMapArray *maps, PageStatus status)
        {
            for (var i = 0; i < maps->Count; i++)
            {
                var map = maps->Items[i];
                if (map.Start >= BootInfo.Header->InstalledPhysicalMemory)
                {
                    continue;
                }

                if ((map.AddressSpaceKind & AddressSpaceKind.Physical) == 0)
                {
                    continue;
                }

                var mapPages    = KMath.DivCeil(map.Size, 4096);
                var fistPageNum = KMath.DivFloor(map.Start, 4096);
                KernelMessage.WriteLine("Mark Pages from {0:X8}, Size {1:X8}, Type {2}, FirstPage {3}, Pages {4}, Status {5}", map.Start, map.Size, (uint)map.Type, (uint)fistPageNum, mapPages, (uint)status);

                for (var p = fistPageNum; p < fistPageNum + mapPages; p++)
                {
                    var addr = p * 4096;
                    if (!Region.Contains(addr))
                    {
                        continue;
                    }

                    if (addr >= BootInfo.Header->InstalledPhysicalMemory)
                    {
                        KernelMessage.WriteLine("addr >= BootInfo.Header->InstalledPhysicalMemory");
                        break;
                    }
                    var page = GetPageByNum(p);
                    Assert.IsSet(page, "page == null");
                    page->Status = status;
                }
            }
        }
Пример #22
0
 private static uint RequiredPagesForSize(USize size)
 {
     return(KMath.DivCeil(size, 4096));
 }
Пример #23
0
        private static unsafe Process CreateProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0)
        {
            var proc = CreateEmptyProcess(new ProcessCreateOptions()
            {
                User = true
            });

            KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID);
            proc.Path      = path;
            proc.PageTable = PageTable.CreateInstance();

            var allocator = new UserInitialPageAllocator()
            {
                DebugName = "UserInitial"
            };

            allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual);
            proc.UserPageAllocator = allocator;

            // Setup User PageTable
            proc.PageTableAllocAddr = VirtualPageManager.AllocatePages(
                KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096),
                new AllocatePageOptions {
                Pool = PageAllocationPool.Identity
            });
            PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize);
            proc.PageTable.UserProcSetup(proc.PageTableAllocAddr);
            proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize);

            proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment);
            proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment);
            proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096);
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT));
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT));
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS));

            var tmpKernelElfHeaders = SetupElfHeader(proc, elf);

            // Setup ELF Sections
            for (uint i = 0; i < elf.ProgramHeaderCount; i++)
            {
                var section = elf.GetProgramHeader(i);

                var memSize  = section->MemSz;
                var fileSize = section->FileSz;
                var virtAddr = section->VAddr;
                var srcAddr  = elf.GetProgramPhysAddr(section);

                if (memSize == 0)
                {
                    continue;
                }

                KernelMessage.WriteLine("Setup Program Section VAddr {0:X8} SrcAddr {1:X8} Size {2:X8}", virtAddr, srcAddr, memSize);

                if (virtAddr == Addr.Zero)
                {
                    var mem = allocator.AllocatePagesAddr(KMath.DivCeil(memSize, 4096));
                    tmpKernelElfHeaders[i].Addr = mem;
                    virtAddr = mem;
                }

                // Map the Sections
                proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, memSize);
                if (i == 0) // TODO: Flags
                {
                    proc.PageTable.SetReadonly(virtAddr, memSize);
                }

                if (memSize > fileSize)
                {
                    MemoryOperation.Clear(srcAddr + fileSize, memSize - fileSize);
                }

                //if (name->Equals(".text"))
                //    proc.PageTable.SetExecutable(virtAddr, size);
            }
            KernelMessage.WriteLine("proc sections are ready");

            for (uint i = 0; i < elf.SectionHeaderCount; i++)
            {
                var section = elf.GetSectionHeader(i);

                var size     = section->Size;
                var virtAddr = section->Addr;
                var srcAddr  = elf.GetSectionPhysAddr(section);

                if (size == 0)
                {
                    continue;
                }

                var name = elf.GetSectionName(section);
                if (virtAddr == Addr.Zero)
                {
                }
                else
                {
                    if (name->Equals(".bss"))
                    {
                        MemoryOperation.Clear(srcAddr, size);
                        proc.BrkBase = virtAddr + size;
                        KernelMessage.WriteLine("sbrk_base: {0:X8}", proc.BrkBase);
                    }
                }
            }

            // Detect Thread-Main
            var entryPoint = GetMainEntryPointFromElf(elf);

            KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint);
            var defaultDispatchEntryPoint = GetDispatchEntryPointFromElf(elf);

            if (defaultDispatchEntryPoint != Addr.Zero)
            {
                KernelMessage.WriteLine("DispatchEntryPoint: {0:X8}", defaultDispatchEntryPoint);
                proc.Service.Init(defaultDispatchEntryPoint);
            }

            var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint)
            {
                ArgumentBufferSize  = argumentBufferSize,
                AllowUserModeIOPort = true,
                DebugName           = "UserProcMainThread",
            });

            KernelMessage.WriteLine("Created Process {0} ProcessID={1}", path, proc.ProcessID);

            return(proc);
        }
Пример #24
0
        public static unsafe void Main()
        {
            try
            {
                ManagedMemoy.InitializeGCMemory();
                StartUp.InitializeAssembly();
                KMath.Init();
                //Mosa.Runtime.StartUp.InitializeRuntimeMetadata();

                BootInfo.SetupStage1();

                Memory.InitialKernelProtect();

                ApiContext.Current = new ApiHost();
                Assert.Setup(AssertError);

                // Setup some pseudo devices
                DeviceManager.InitStage1();

                //Setup Output and Debug devices
                DeviceManager.InitStage2();

                // Write first output
                KernelMessage.WriteLine("<KERNEL:CONSOLE:BEGIN>");
                PerformanceCounter.Setup(BootInfo.Header->KernelBootStartCycles);
                KernelMessage.WriteLine("Starting Abanu Kernel...");

                KernelMessage.WriteLine("KConfig.UseKernelMemoryProtection: {0}", KConfig.UseKernelMemoryProtection);
                KernelMessage.WriteLine("KConfig.UsePAE: {0}", KConfig.UsePAE);
                KernelMessage.WriteLine("Apply PageTableType: {0}", (uint)BootInfo.Header->PageTableType);
                KernelMessage.WriteLine("GCInitialMemory: {0:X8}-{1:X8}", Address.GCInitialMemory, Address.GCInitialMemory + Address.GCInitialMemorySize - 1);

                Ulongtest1();
                Ulongtest2();
                InlineTest();

                // Detect environment (Memory Maps, Video Mode, etc.)
                BootInfo.SetupStage2();

                KernelMemoryMapManager.Setup();
                //KernelMemoryMapManager.Allocate(0x1000 * 1000, BootInfoMemoryType.PageDirectory);

                // Read own ELF-Headers and Sections
                KernelElf.Setup();

                // Initialize the embedded code (actually only a little proof of concept code)
                NativeCalls.Setup();

                //InitialKernelProtect();

                PhysicalPageManager.Setup();

                KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages);
                PhysicalPageManager.AllocatePages(10);
                KernelMessage.WriteLine("Phys free: {0}", PhysicalPageManager.FreePages);
                VirtualPageManager.Setup();

                Memory.Setup();

                // Now Memory Sub System is working. At this point it's valid
                // to allocate memory dynamically

                DeviceManager.InitFrameBuffer();

                // Setup Programmable Interrupt Table
                PIC.Setup();

                // Setup Interrupt Descriptor Table
                // Important Note: IDT depends on GDT. Never setup IDT before GDT.
                IDTManager.Setup();

                InitializeUserMode();
                SysCallManager.Setup();

                KernelMessage.WriteLine("Initialize Runtime Metadata");
                StartUp.InitializeRuntimeMetadata();

                KernelMessage.WriteLine("Performing some Non-Thread Tests");
                Tests();
            }
            catch (Exception ex)
            {
                Panic.Error(ex.Message);
            }

            if (KConfig.SingleThread)
            {
                StartupStage2();
            }
            else
            {
                ProcessManager.Setup(StartupStage2);
            }
        }
Пример #25
0
        public static unsafe Thread CreateThread(Process proc, ThreadStartOptions options)
        {
            Thread thread;
            uint   threadID;

            lock (SyncRoot)
            {
                threadID = FindEmptyThreadSlot();

                if (threadID == 0)
                {
                    ResetTerminatedThreads();
                    threadID = FindEmptyThreadSlot();

                    Assert.False(threadID == 0 && Enabled, "No more free Thread-Slots!");
                }

                thread        = Threads[threadID];
                thread.Status = ThreadStatus.Creating;
            }

            // Debug:
            //options.User = false;

            thread.User      = proc.User;
            thread.Debug     = options.Debug;
            thread.DebugName = options.DebugName;
            thread.Priority  = options.Priority;

            var stackSize  = options.StackSize;
            var argBufSize = options.ArgumentBufferSize;

            thread.ArgumentBufferSize = options.ArgumentBufferSize;

            var stackPages = KMath.DivCeil(stackSize, PhysicalPageManager.PageSize);

            if (KConfig.Log.Threads >= KLogLevel.Trace)
            {
                KernelMessage.WriteLine("Requesting {0} stack pages", stackPages);
            }

            var debugPadding = 8u;

            stackSize = stackPages * PhysicalPageManager.PageSize;
            var stack = new Pointer((void *)VirtualPageManager.AllocatePages(stackPages, new AllocatePageOptions {
                DebugName = "ThreadStack"
            }));

            PageTable.KernelTable.SetWritable((uint)stack, stackSize);

            if (thread.User && proc.PageTable != PageTable.KernelTable)
            {
                proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stack, stackSize);
            }

            stackSize -= debugPadding;
            var stackBottom = stack + (int)stackSize;

            if (KConfig.Log.Threads >= KLogLevel.Trace)
            {
                KernelMessage.Write("Create Thread {0}. EntryPoint: {1:X8} Stack: {2:X8}-{3:X8} Type: ", threadID, options.MethodAddr, (uint)stack, (uint)stackBottom - 1);
            }

            if (KConfig.Log.Threads >= KLogLevel.Trace)
            {
                if (thread.User)
                {
                    KernelMessage.Write("User");
                }
                else
                {
                    KernelMessage.Write("Kernel");
                }
            }

            if (KConfig.Log.Threads >= KLogLevel.Trace)
            {
                if (thread.DebugName != null)
                {
                    KernelMessage.Write(" Thread DebugName: {0}", thread.DebugName);
                }
                if (thread.Process != null)
                {
                    KernelMessage.WriteLine(" Process: {0}", thread.Process.Path);
                }
            }

            // -- kernel stack
            thread.KernelStackSize = 4 * 4096;
            //thhread.tssAddr = RawVirtualFrameAllocator.RequestRawVirtalMemoryPages(1);
            PageTable.KernelTable.SetWritable(KernelStart.TssAddr, 4096);
            thread.KernelStack = VirtualPageManager.AllocatePages(
                KMath.DivCeil(thread.KernelStackSize, 4096),
                new AllocatePageOptions {
                DebugName = "ThreadKernelStack"
            });                                                               // TODO: Decrease Kernel Stack, because Stack have to be changed directly because of multi-threading.
            thread.KernelStackBottom = thread.KernelStack + thread.KernelStackSize;

            if (KConfig.Log.Threads >= KLogLevel.Trace)
            {
                KernelMessage.WriteLine("tssEntry: {0:X8}, tssKernelStack: {1:X8}-{2:X8}", KernelStart.TssAddr, thread.KernelStack, thread.KernelStackBottom - 1);
            }

            PageTable.KernelTable.SetWritable(thread.KernelStack, 256 * 4096);

            // ---
            uint stackStateOffset = 8;

            stackStateOffset += argBufSize;

            uint cS = 0x08;

            if (thread.User)
            {
                cS = 0x1B;
            }

            var stateSize = thread.User ? IDTTaskStack.Size : IDTStack.Size;

            thread.StackTop    = (uint)stack;
            thread.StackBottom = (uint)stackBottom;

            Intrinsic.Store32(stackBottom, 4, 0xFF00001);          // Debug Marker
            Intrinsic.Store32(stackBottom, 0, 0xFF00002);          // Debug Marker

            Intrinsic.Store32(stackBottom, -4, (uint)stackBottom);
            Intrinsic.Store32(stackBottom, -(8 + (int)argBufSize), SignalThreadTerminationMethodAddress.ToInt32());  // Address of method that will raise a interrupt signal to terminate thread

            uint argAddr = (uint)stackBottom - argBufSize;

            IDTTaskStack *stackState = null;

            if (thread.User)
            {
                stackState = (IDTTaskStack *)VirtualPageManager.AllocatePages(1, new AllocatePageOptions {
                    DebugName = "ThreadStackState"
                });
                if (proc.PageTable != PageTable.KernelTable)
                {
                    proc.PageTable.MapCopy(PageTable.KernelTable, (uint)stackState, IDTTaskStack.Size);
                }
            }
            else
            {
                stackState = (IDTTaskStack *)(stackBottom - 8 - IDTStack.Size); // IDTStackSize is correct - we don't need the Task-Members.
            }
            thread.StackState = stackState;

            if (thread.User && KConfig.Log.Threads >= KLogLevel.Trace)
            {
                KernelMessage.WriteLine("StackState at {0:X8}", (uint)stackState);
            }

            stackState->Stack.EFLAGS = X86_EFlags.Reserved1;
            if (thread.User)
            {
                // Never set this values for Non-User, otherwise you will override stack informations.
                stackState->TASK_SS  = 0x23;
                stackState->TASK_ESP = (uint)stackBottom - (uint)stackStateOffset;

                proc.PageTable.MapCopy(PageTable.KernelTable, thread.KernelStack, thread.KernelStackSize);
                proc.PageTable.MapCopy(PageTable.KernelTable, KernelStart.TssAddr, 4096);
            }
            if (thread.User && options.AllowUserModeIOPort)
            {
                byte IOPL = 3;
                stackState->Stack.EFLAGS = (X86_EFlags)((uint)stackState->Stack.EFLAGS).SetBits(12, 2, IOPL);
            }

            stackState->Stack.CS  = cS;
            stackState->Stack.EIP = options.MethodAddr;
            stackState->Stack.EBP = (uint)(stackBottom - (int)stackStateOffset).ToInt32();

            thread.DataSelector = thread.User ? 0x23u : 0x10u;

            UninterruptableMonitor.Enter(proc.Threads);
            try
            {
                thread.Process = proc;
                proc.Threads.Add(thread);
            }
            finally
            {
                UninterruptableMonitor.Exit(proc.Threads);
            }

            ThreadsAllocated++;
            if (ThreadsAllocated > ThreadsMaxAllocated)
            {
                ThreadsMaxAllocated = ThreadsAllocated;
                if (KConfig.Log.Threads >= KLogLevel.Trace)
                {
                    KernelMessage.WriteLine("Threads Max Allocated: {0}. Allocated {0} Active: {1}", ThreadsMaxAllocated, ThreadsAllocated, GetActiveThreadCount());
                }
                if (KConfig.Log.Threads >= KLogLevel.Trace)
                {
                    DumpStats();
                }
            }
            else if (KConfig.Log.Threads >= KLogLevel.Debug)
            {
                KernelMessage.WriteLine("Threads Allocated {0} Active: {1}", ThreadsAllocated, GetActiveThreadCount());
            }
            return(thread);
        }
Пример #26
0
        private static void SetupMemoryMap()
        {
            var mbMapCount = Multiboot.MemoryMapCount;

            BootInfo->MemoryMapArray = (BootInfoMemory *)MallocBootInfoData((USize)(sizeof(MultiBootMemoryMap) * MemoryMapReserve));

            for (uint i = 0; i < mbMapCount; i++)
            {
                BootInfo->MemoryMapArray[i].Start = Multiboot.GetMemoryMapBase(i);
                BootInfo->MemoryMapArray[i].Size  = Multiboot.GetMemoryMapLength(i);
                var memType          = BootInfoMemoryType.Reserved;
                var type             = (BIOSMemoryMapType)Multiboot.GetMemoryMapType(i);
                var addressSpaceKind = AddressSpaceKind.Physical;
                var preMap           = false;

                switch (type)
                {
                case BIOSMemoryMapType.Usable:
                    memType = BootInfoMemoryType.SystemUsable;
                    break;

                case BIOSMemoryMapType.Reserved:
                    memType = BootInfoMemoryType.Reserved;
                    break;

                case BIOSMemoryMapType.ACPI_Relaimable:
                    memType = BootInfoMemoryType.ACPI_Relaimable;
                    break;

                case BIOSMemoryMapType.ACPI_NVS_Memory:
                    memType = BootInfoMemoryType.ACPI_NVS_Memory;
                    break;

                case BIOSMemoryMapType.BadMemory:
                    memType = BootInfoMemoryType.BadMemory;
                    break;

                default:
                    memType = BootInfoMemoryType.Unknown;
                    break;
                }
                BootInfo->MemoryMapArray[i].Type             = memType;
                BootInfo->MemoryMapArray[i].AddressSpaceKind = addressSpaceKind;
                BootInfo->MemoryMapArray[i].PreMap           = preMap;
            }

            // It's possible, that the BIOS-Area (@640K) is not correctly setup by Multiboot. So add it here manually to be sure
            var idx = mbMapCount + 0;

            BootInfo->MemoryMapArray[idx].Start            = 640 * 1024;
            BootInfo->MemoryMapArray[idx].Size             = (1024 - 640) * 1024;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.CustomReserved;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both; //TODO: Physical
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = Address.KernelElfSectionPhys;
            BootInfo->MemoryMapArray[idx].Size             = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000);
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelElf;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Physical;
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = Address.KernelBootInfo;
            BootInfo->MemoryMapArray[idx].Size             = 0x1000;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.BootInfoHeader;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both;
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = BootInfo->HeapStart;
            BootInfo->MemoryMapArray[idx].Size             = 0x1000; //TODO: Recalculate after Setup all Infos
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.BootInfoHeap;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both;
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            uint stackSize = 0x100000; // 1MB

            BootInfo->MemoryMapArray[idx].Start            = Address.InitialStack - stackSize;
            BootInfo->MemoryMapArray[idx].Size             = stackSize;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.InitialStack;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both;
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = Address.GCInitialMemory;
            BootInfo->MemoryMapArray[idx].Size             = Address.GCInitialMemorySize;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.InitialGCMemory;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both;
            BootInfo->MemoryMapArray[idx].PreMap           = true;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Addr;
            BootInfo->MemoryMapArray[idx].Size             = LoaderStart.OriginalKernelElf.GetSectionHeader(".bss")->Size;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelBssSegment;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual;
            BootInfo->MemoryMapArray[idx].PreMap           = false;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Addr;
            BootInfo->MemoryMapArray[idx].Size             = LoaderStart.OriginalKernelElf.GetSectionHeader(".text")->Size;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelTextSegment;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual;
            BootInfo->MemoryMapArray[idx].PreMap           = false;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Addr;
            BootInfo->MemoryMapArray[idx].Size             = LoaderStart.OriginalKernelElf.GetSectionHeader(".rodata")->Size;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelROdataSegment;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual;
            BootInfo->MemoryMapArray[idx].PreMap           = false;

            idx++;
            BootInfo->MemoryMapArray[idx].Start            = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Addr;
            BootInfo->MemoryMapArray[idx].Size             = LoaderStart.OriginalKernelElf.GetSectionHeader(".data")->Size;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelDataSegment;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Virtual;
            BootInfo->MemoryMapArray[idx].PreMap           = false;

            // Avoiding the use of the first megabyte of RAM
            idx++;
            BootInfo->MemoryMapArray[idx].Start            = 0x0;
            BootInfo->MemoryMapArray[idx].Size             = Address.ReserveMemory;
            BootInfo->MemoryMapArray[idx].Type             = BootInfoMemoryType.KernelReserved;
            BootInfo->MemoryMapArray[idx].AddressSpaceKind = AddressSpaceKind.Both;
            BootInfo->MemoryMapArray[idx].PreMap           = false;

            BootInfo->MemoryMapLength = idx + 1;
        }
Пример #27
0
        static void SetupMemoryMap()
        {
            uint customMaps = 7;
            var  mbMapCount = Multiboot.MemoryMapCount;

            BootInfo->MemoryMapLength = mbMapCount + customMaps;
            BootInfo->MemoryMapArray  = (BootInfoMemory *)MallocBootInfoData((USize)(sizeof(MultiBootMemoryMap) * MemoryMapReserve));

            for (uint i = 0; i < mbMapCount; i++)
            {
                BootInfo->MemoryMapArray[i].Start = Multiboot.GetMemoryMapBase(i);
                BootInfo->MemoryMapArray[i].Size  = Multiboot.GetMemoryMapLength(i);
                var memType = BootInfoMemoryType.Reserved;
                var type    = (BIOSMemoryMapType)Multiboot.GetMemoryMapType(i);

                switch (type)
                {
                case BIOSMemoryMapType.Usable:
                    memType = BootInfoMemoryType.SystemUsable;
                    break;

                case BIOSMemoryMapType.Reserved:
                    memType = BootInfoMemoryType.Reserved;
                    break;

                case BIOSMemoryMapType.ACPI_Relaimable:
                    memType = BootInfoMemoryType.ACPI_Relaimable;
                    break;

                case BIOSMemoryMapType.ACPI_NVS_Memory:
                    memType = BootInfoMemoryType.ACPI_NVS_Memory;
                    break;

                case BIOSMemoryMapType.BadMemory:
                    memType = BootInfoMemoryType.BadMemory;
                    break;

                default:
                    memType = BootInfoMemoryType.Unknown;
                    break;
                }
                BootInfo->MemoryMapArray[i].Type = memType;
            }

            var idx = mbMapCount + 0;

            BootInfo->MemoryMapArray[idx].Start = Address.OriginalKernelElfSection;
            BootInfo->MemoryMapArray[idx].Size  = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000);
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.OriginalKernelElfImage;

            idx++;
            BootInfo->MemoryMapArray[idx].Start = Address.KernelElfSection;
            BootInfo->MemoryMapArray[idx].Size  = KMath.AlignValueCeil(LoaderStart.OriginalKernelElf.TotalFileSize, 0x1000);
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.KernelElf;

            idx++;
            BootInfo->MemoryMapArray[idx].Start = Address.KernelBootInfo;
            BootInfo->MemoryMapArray[idx].Size  = 0x1000;
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.BootInfoHeader;

            idx++;
            BootInfo->MemoryMapArray[idx].Start = BootInfo->HeapStart;
            BootInfo->MemoryMapArray[idx].Size  = 0x1000; //TODO: Recaluclate after Setup all Infos
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.BootInfoHeap;

            idx++;
            uint stackSize = 0x100000; // 1MB

            BootInfo->MemoryMapArray[idx].Start = Address.InitialStack - stackSize;
            BootInfo->MemoryMapArray[idx].Size  = stackSize;
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.InitialStack;

            idx++;
            BootInfo->MemoryMapArray[idx].Start = Address.GCInitialMemory;
            BootInfo->MemoryMapArray[idx].Size  = Address.GCInitialMemorySize;
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.InitialGCMemory;

            idx++;
            BootInfo->MemoryMapArray[idx].Start = 0x0;
            BootInfo->MemoryMapArray[idx].Size  = 0xA0000; // 640 KB
            BootInfo->MemoryMapArray[idx].Type  = BootInfoMemoryType.KernelReserved;
        }
Пример #28
0
 private static byte GetOrderForPageCount(uint pages)
 {
     return((byte)KMath.Log2OfPowerOf2(KMath.CeilToPowerOfTwo(pages)));
 }
Пример #29
0
        private static unsafe Process StartProcessFromElf(ElfSections elf, string path, uint argumentBufferSize = 0)
        {
            var proc = CreateEmptyProcess(new ProcessCreateOptions()
            {
                User = true
            });

            KernelMessage.WriteLine("Create proc: {0}, PID: {1}", path, proc.ProcessID);
            proc.Path      = path;
            proc.PageTable = PageTable.CreateInstance();

            var allocator = new UserInitialPageAllocator()
            {
                DebugName = "UserInitial"
            };

            allocator.Setup(new MemoryRegion(500 * 1024 * 1024, 60 * 1024 * 1014), AddressSpaceKind.Virtual);
            proc.UserPageAllocator = allocator;

            // Setup User PageTable
            proc.PageTableAllocAddr = VirtualPageManager.AllocatePages(
                KMath.DivCeil(proc.PageTable.InitalMemoryAllocationSize, 4096),
                new AllocatePageOptions {
                Pool = PageAllocationPool.Identity
            });
            PageTable.KernelTable.SetWritable(proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize);
            proc.PageTable.UserProcSetup(proc.PageTableAllocAddr);
            proc.PageTable.Map(proc.PageTableAllocAddr, proc.PageTableAllocAddr, proc.PageTable.InitalMemoryAllocationSize);

            proc.PageTable.MapCopy(PageTable.KernelTable, BootInfoMemoryType.KernelTextSegment);
            proc.PageTable.SetExecutable(BootInfoMemoryType.KernelTextSegment);
            proc.PageTable.MapCopy(PageTable.KernelTable, Address.InterruptControlBlock, 4096);
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.GDT));
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.IDT));
            proc.PageTable.MapCopy(PageTable.KernelTable, KernelMemoryMapManager.Header->Used.GetMap(BootInfoMemoryType.TSS));

            var tmpKernelElfHeaders = SetupElfHeader(proc, elf);

            // Setup ELF Sections
            for (uint i = 0; i < elf.SectionHeaderCount; i++)
            {
                var section = elf.GetSectionHeader(i);
                var name    = elf.GeSectionName(section);

                var size     = section->Size;
                var virtAddr = section->Addr;
                var srcAddr  = elf.GetSectionPhysAddr(section);

                if (size == 0)
                {
                    continue;
                }

                if (virtAddr == Addr.Zero)
                {
                    var mem = allocator.AllocatePagesAddr(KMath.DivCeil(size, 4096));
                    tmpKernelElfHeaders[i].Addr = mem;
                    virtAddr = mem;
                }

                var sb = new StringBuffer();
                sb.Append("Map section ");
                sb.Append(name);
                sb.Append(" virt={0:X8} src={1:X8} size={2:X8}", virtAddr, srcAddr, size);
                KernelMessage.WriteLine(sb);
                //MemoryOperation.Copy4(elf.GetSectionPhysAddr(section), section->Addr, section->Size);

                // Map the Sections
                proc.PageTable.MapCopy(PageTable.KernelTable, srcAddr, virtAddr, size);
                if (name->Equals(".text"))
                {
                    proc.PageTable.SetExecutable(virtAddr, size);
                }
            }
            KernelMessage.WriteLine("proc sections are ready");

            // Detect Thread-Main
            var entryPoint = GetEntryPointFromElf(elf);

            KernelMessage.WriteLine("EntryPoint: {0:X8}", entryPoint);

            var mainThread = Scheduler.CreateThread(proc, new ThreadStartOptions(entryPoint)
            {
                ArgumentBufferSize  = argumentBufferSize,
                AllowUserModeIOPort = true,
                DebugName           = "UserProcMainThread",
            });

            KernelMessage.WriteLine("Starting {0} on Thread {1}", path, mainThread.ThreadID);
            proc.Start();

            return(proc);
        }