Example #1
0
        public unsafe Page *AllocatePages(uint pages, AllocatePageOptions options = default)
        {
            if (pages > _FreePages)
            {
                Panic.Error("Out of Memory");
                return(null);
            }

            Page *page;

            if (AddressSpaceKind == AddressSpaceKind.Virtual || options.Continuous)
            {
                page = AllocatePagesContinuous(pages, options);
            }
            else
            {
                page = AllocatePagesNormal(pages, options);
            }

            if (page == null)
            {
                KernelMessage.WriteLine("DebugName: {0}", DebugName);
                KernelMessage.WriteLine("Free pages: {0:X8}, Requested: {1:X8}", FreePages, pages);
                Panic.Error("Out of Memory");
            }

            KernelMessage.Path(DebugName, "SimpleAlloc: Request {0} Pages, Addr {1:X8}", pages, GetAddress(page));

            return(page);
        }
 static void BUDDY_BUG(string msg, uint value = 0)
 {
     //printf("BUDDY_BUG in %s, %d.\n", f, line);
     //System.Console.WriteLine(msg);
     KernelMessage.Path("Allocator", msg, value);
     //assert(0);
 }
Example #3
0
        /// <summary>
        /// Releases a page to the free list
        /// </summary>
        public void Free(Page *page)
        {
            var    oldFree   = _FreePages;
            string debugName = null;

            if (page->DebugTag != null)
            {
                debugName = (string)Intrinsic.GetObjectFromAddress((Pointer)(uint)page->DebugTag);
            }

            UninterruptableMonitor.Enter(this);
            try
            {
                var debugCount = list_head.list_count((list_head *)page); // DEBUG

                SelfCheck("SCF1", debugCount);
                Page *temp   = page;
                uint  result = 0;

                do
                {
                    result++;
                    if (temp->Status == PageStatus.Free)
                    {
                        //Panic.Error("Double Free");
                        SelfCheck("SCF3", debugCount);
                        KernelMessage.WriteLine("Double Free. Pages {0} Iteration {1}", debugCount, result);
                        Debug.Break();
                    }

                    temp->Status = PageStatus.Free;

                    var oldTemp = temp;
                    temp = (Page *)temp->Lru.next;
                    Native.Nop();
                    _FreePages++;

                    list_head.list_move_tail((list_head *)oldTemp, FreeList);
                }while (temp != page && result != debugCount);

                //list_head.list_headless_splice_tail((list_head*)page, FreeList);
                SelfCheck("SCF2", debugCount);
            }
            finally
            {
                UninterruptableMonitor.Exit(this);
            }
            var freedPages = _FreePages - oldFree;

            if (KConfig.Log.PageAllocation && TraceOptions.Enabled && freedPages >= TraceOptions.MinPages)
            {
                KernelMessage.Path(DebugName, "Freed Pages: {1}. Addr: {2:X8}. Now available: {3} --> {4}. Allocations={5} DebugName={0}.", debugName, freedPages, GetAddress(page), oldFree, _FreePages, (uint)Requests);
            }

            _Releases++;
        }
Example #4
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);
        }
Example #5
0
        private void CheckAllocation(Page *page, uint pages)
        {
            //return;
            var count = list_head.list_count((list_head *)page);

            //Assert.True(count == pages);

            if (count != pages)
            {
                KernelMessage.Path(DebugName, "Pages {0} != {1}, num={2} addr={3:X8} ptr={4:X8}", pages, count, GetPageNum(page), GetAddress(page), (uint)page);
                Debug.Break();
            }
        }
Example #6
0
        protected override MemoryRegion AllocRawMemory(uint size)
        {
            var kmap = KernelMemoryMapManager.Allocate(size, BootInfoMemoryType.PageFrameAllocator, AddressSpaceKind.Both);

            KernelMessage.Path(DebugName, "AllocRawMemory: Done. Current maps:");
            KernelMemoryMapManager.PrintMapArrays();
            PageTable.KernelTable.Map(kmap.Start, kmap.Start, kmap.Size, flush: true);
            PageTable.KernelTable.SetWritable(kmap.Start, kmap.Size);
            var region = new MemoryRegion(kmap.Start, kmap.Size);

            region.Clear();
            return(region);
        }
Example #7
0
        public static void Setup()
        {
            var addr = Initial_FindFreePage();

            KernelMessage.Path("KernelMemoryMapManager", "Initial Page: {0:X}", addr);
            PageTable.KernelTable.Map(addr, addr, flush: true);

            // 80KB should be enough
            // TODO: Check if really 80KB are available after this address.
            InitialMap = new KernelMemoryMap(addr, 0x1000 * 20, BootInfoMemoryType.KernelMemoryMap, AddressSpaceKind.Both);
            PageTable.KernelTable.Map(InitialMap.Start, InitialMap.Start, InitialMap.Size, flush: true);
            PageTable.KernelTable.SetWritable(InitialMap.Start, InitialMap.Size);

            Header = (KernelMemoryMapHeader *)InitialMap.Start;

            var arrayOffset1 = 0x1000;
            var arrayOffset2 = 0x2000;
            var arrayOffset3 = 0x3000;

            Header->SystemUsable   = new KernelMemoryMapArray((KernelMemoryMap *)(InitialMap.Start + arrayOffset1), 50);
            Header->Used           = new KernelMemoryMapArray((KernelMemoryMap *)(InitialMap.Start + arrayOffset2), 100);
            Header->KernelReserved = new KernelMemoryMapArray((KernelMemoryMap *)(InitialMap.Start + arrayOffset3), 100);

            for (uint i = 0; i < BootInfo.Header->MemoryMapLength; i++)
            {
                var map  = BootInfo.Header->MemoryMapArray[i];
                var kmap = new KernelMemoryMap(map.Start, map.Size, map.Type, map.AddressSpaceKind);
                if (kmap.Type == BootInfoMemoryType.SystemUsable)
                {
                    Header->SystemUsable.Add(kmap);
                }
                else
                {
                    if (kmap.Type == BootInfoMemoryType.KernelReserved)
                    {
                        Header->KernelReserved.Add(kmap);
                    }
                    else
                    {
                        Header->Used.Add(kmap);
                    }
                }
            }
            Header->Used.Add(InitialMap);

            KernelMessage.Path("KernelMemoryMapManager", "Filling Lists Done. SystemUsable: {0}, CustomReserved: {1}, Used: {2}", Header->SystemUsable.Count, Header->KernelReserved.Count, Header->Used.Count);
            PrintMapArrays();

            //Debug_FillAvailableMemory();
        }
Example #8
0
        /// <summary>
        /// Video Stage
        /// </summary>
        public static unsafe void InitFrameBuffer()
        {
            if (!BootInfo.Header->FBPresent || BootInfo.Header->VBEMode < 0x100)
            {
                KernelMessage.Path("fb", "not present");
                return;
            }

            KernelMessage.WriteLine("InitFrameBuffer");

            Fb = new FrameBuffer(BootInfo.Header->FbInfo.FbAddr, BootInfo.Header->FbInfo.FbWidth, BootInfo.Header->FbInfo.FbHeight, BootInfo.Header->FbInfo.FbPitch, 8);
            Fb.Init();

            FrameBufferTextScreen = new FrameBufferTextScreenDevice(Fb);
            Console.SetOutputDevice(FrameBufferTextScreen);
        }
Example #9
0
        public static KernelMemoryMap Allocate(USize size, BootInfoMemoryType type, AddressSpaceKind addressSpaceKind)
        {
            var cnt = Header->Used.Count;

            for (uint i = 0; i < cnt; i++)
            {
                var map = Header->Used.Items[i];
                if (CheckPageIsUsableAfterMap(map, size, addressSpaceKind))
                {
                    var newMap = new KernelMemoryMap(map.Start + map.Size, size, type, addressSpaceKind);
                    Header->Used.Add(newMap);
                    KernelMessage.Path("KernelMemoryMapManager", "Allocated: at {0:X8}, size {1:X8}, type {2}", newMap.Start, size, (uint)type);
                    return(newMap);
                }
            }
            return(KernelMemoryMap.Empty);
        }
Example #10
0
        public Page *AllocatePages(uint pages, AllocatePageOptions options = default)
        {
            Page *page = AllocateInternal(pages, options);

            if (page == null)
            {
                //KernelMessage.WriteLine("DebugName: {0}", DebugName);
                KernelMessage.WriteLine("Free pages: {0:X8}, Requested: {1:X8}", FreePages, pages);
                Panic.Error("Out of Memory");
            }

            if (FreePages < 1000)
            {
                KernelMessage.Path(DebugName, "WARNING: Low pages. Available: {0}", FreePages);
            }

            return(page);
        }
Example #11
0
        /// <summary>
        /// Video Stage
        /// </summary>
        public static unsafe void InitFrameBuffer()
        {
            if (!BootInfo.Header->FBPresent || BootInfo.Header->VBEMode < 0x100)
            {
                KernelMessage.Path("fb", "not present");
                return;
            }

            KernelMessage.WriteLine("InitFrameBuffer");

            Fb = new FrameBuffer(ref BootInfo.Header->FbInfo);
            for (uint at = Fb.Addr; at < Fb.Addr + Fb.MemorySize; at += 4096)
            {
                PageTable.KernelTable.MapVirtualAddressToPhysical(at, at);
            }
            PageTable.KernelTable.Flush();

            FrameBufferTextScreen = new FrameBufferTextScreenDevice(Fb);
            Console.SetOutputDevice(FrameBufferTextScreen);
        }
Example #12
0
        private void SelfCheck(string checkName, uint debugVal = 0)
        {
            return;

            var page  = (Page *)FreeList;
            var count = list_head.list_count(FreeList);

            if (count != _FreePages)
            {
                this.DumpPages();
                this.DumpStats();
                this.DumpPage(page);
                KernelMessage.WriteLine("SelfCheck: {0} DebugVal={1}", checkName, debugVal);
                KernelMessage.Path(DebugName, "FreeListCount {0} != {1}, num={2} addr={3:X8} ptr={4:X8}", _FreePages, count, GetPageNum(page), GetAddress(page), (uint)page);
                Debug.Break();
            }
            else
            {
                //Serial.Write(Serial.COM1, (byte)'!');
            }
        }
Example #13
0
        private Page *AllocateInternal(uint pages, AllocatePageOptions options = default)
        {
            if (KConfig.Log.PageAllocation && TraceOptions.Enabled && pages >= TraceOptions.MinPages)
            {
                KernelMessage.Path(DebugName, "Requesting Pages: {1}. Available: {2} DebugName={0}", options.DebugName, pages, _FreePages);
            }

            if (pages == 256)
            {
                Debug.Nop();
            }

            UninterruptableMonitor.Enter(this);
            try
            {
                SelfCheck("SC1");
                if (pages > 1 && (AddressSpaceKind == AddressSpaceKind.Virtual || options.Continuous))
                {
                    if (!MoveToFreeContinuous(pages))
                    {
                        // Compact
                        //KernelMessage.Path(DebugName, "Compacting Linked List");
                        //this.DumpPages();
                        BuildLinkedLists();
                        if (!MoveToFreeContinuous(pages))
                        {
                            this.DumpPages();
                            KernelMessage.WriteLine("Requesting {0} pages failed", pages);
                            Panic.Error("Requesting pages failed: out of memory");
                        }
                    }
                }

                // ---
                var head     = FreeList;
                var headPage = (Page *)head;
                FreeList = head->next;
                list_head.list_del_init(head);
                headPage->Status = PageStatus.Used;
                if (KConfig.Log.PageAllocation)
                {
                    if (options.DebugName != null)
                    {
                        headPage->DebugTag = (uint)Intrinsic.GetObjectAddress(options.DebugName);
                    }
                    else
                    {
                        headPage->DebugTag = null;
                    }
                }
                _FreePages--;
                // ---

                for (var i = 1; i < pages; i++)
                {
                    var tmpNextFree = FreeList->next;
                    list_head.list_move_tail(FreeList, head);
                    var p = (Page *)FreeList;
                    if (p->Status == PageStatus.Used)
                    {
                        this.DumpPages();
                        this.DumpPage(p);
                        KernelMessage.Path(DebugName, "Double Alloc pages={0} allocs={1} free={2} ptr={3:X8}", pages, (uint)_Requests, _FreePages, (uint)p);
                        Panic.Error("Double Alloc");
                    }
                    p->Status = PageStatus.Used;
                    FreeList  = tmpNextFree;
                    _FreePages--;
                }

                if (KConfig.Log.PageAllocation && TraceOptions.Enabled && pages >= TraceOptions.MinPages)
                {
                    KernelMessage.Path(DebugName, "Allocation done. Addr: {0:X8} Available: {1}", GetAddress(headPage), _FreePages);
                }

                _Requests++;

                CheckAllocation(headPage, pages);
                SelfCheck("SC2");

                return(headPage);
            }
            finally
            {
                UninterruptableMonitor.Exit(this);
            }
        }