Exemplo n.º 1
0
        ////////////////////////////////////////////////

        /// <summary>
        /// Destroy the combined page
        /// </summary>
        static bool destroy_compound_pages(Page *page, byte order)
        {
            int  bad = 0;
            uint i;
            uint nr_pages = (1U << order);

            __ClearPageHead(page);
            for (i = 1; i < nr_pages; i++)
            {
                Page *p = page + i;
                if (!PageTail(p) || p->FirstPage != page)
                {
                    bad++;
                    BUDDY_BUG("destroy_compound_pages: error");
                }
                __ClearPageTail(p);
            }
            return(bad != 0);
        }
Exemplo n.º 2
0
        private bool MoveToFreeContinuous(uint pages)
        {
            Page *tryHead     = (Page *)FreeList;
            var   loopedPages = 0;

            Page *tmpHead = tryHead;
            var   found   = false;

            for (int i = 0; i < pages; i++)
            {
                if (loopedPages >= _FreePages)
                {
                    return(false);
                }
                loopedPages++;

                var next = (Page *)tmpHead->Lru.next;
                if (GetPageNum(next) - GetPageNum(tmpHead) != 1)
                {
                    tryHead = next;
                    tmpHead = next;
                    i       = -1; // Reset loop
                    continue;
                }

                tmpHead = next;

                if (i == pages - 1)
                {
                    found = true;
                }
            }
            if (found)
            {
                FreeList = (list_head *)tryHead;
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemplo n.º 3
0
        public void Initialize(MemoryRegion region, Page *pages, AddressSpaceKind addressSpaceKind)
        {
            _Requests = 0;
            _Releases = 0;

            KernelMessage.WriteLine("Init SimplePageAllocator");
            AddressSpaceKind = addressSpaceKind;
            _Region          = region;
            Pages            = pages;
            FirstPageNum     = region.Start / 4096;
            _FreePages       = region.Size / 4096;
            _TotalPages      = region.Size / 4096;
            var addr = region.Start;

            for (var i = 0; i < _TotalPages; i++)
            {
                Pages[i].Address = addr;
                addr            += 4096;
            }
        }
Exemplo n.º 4
0
        public static void buddy_free_pages(mem_zone *zone,
                                            Page *page)
        {
            byte order = compound_order(page);
            uint buddy_idx = 0, combinded_idx = 0;
            uint page_idx = (uint)(page - zone->first_page);

            //TODO: lock zone->lock
            if (PageCompound(page))
            {
                if (destroy_compound_pages(page, order))
                {
                    BUDDY_BUG("buddy_free_pages: error");
                }
            }

            while (order < BUDDY_MAX_ORDER - 1)
            {
                Page *buddy;
                // find and delete buddy to combine
                buddy_idx = __find_buddy_index(page_idx, order);
                buddy     = page + (buddy_idx - page_idx);
                if (!page_is_buddy(buddy, order))
                {
                    break;
                }
                list_head.list_del(&buddy->Lru);
                zone->free_area[order].nr_free--;
                // remove buddy's flag and order
                rmv_page_order_buddy(buddy);
                // update page and page_idx after combined
                combinded_idx = __find_combined_index(page_idx, order);
                page          = page + (combinded_idx - page_idx);
                page_idx      = combinded_idx;
                order++;
            }
            set_page_order_buddy(page, order);
            list_head.list_add(&page->Lru, &zone->free_area[order].free_list);
            zone->free_area[order].nr_free++;
            //TODO: unlock zone->lock
        }
Exemplo n.º 5
0
        public Page *NextCompoundPage(Page *page)
        {
            if (page == null)
            {
                return(null);
            }

            var next = NextPage(page);

            if (next == null)
            {
                return(null);
            }

            if (BuddyAllocatorImplementation.PageHead(page))
            {
                if (BuddyAllocatorImplementation.PageTail(next))
                {
                    return(next);
                }
                else
                {
                    return(null);
                }
            }
            else if (BuddyAllocatorImplementation.PageTail(page))
            {
                if (BuddyAllocatorImplementation.PageTail(next))
                {
                    return(next);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Releases a page to the free list
        /// </summary>
        public void Free(Page *page)
        {
            lock (this)
            {
                var head = page;
                if (head->Status == PageStatus.Reserved)
                {
                    Panic.Error("Cannot free reserved page");
                }

                //if (head->Free)
                if (head->Status == PageStatus.Free)
                {
                    Panic.Error("Double Free?");
                    return;
                }

                var num = head->PagesUsed;

                //KernelMessage.Write("F:{0};", num);

                var p = head;
                for (var n = 0; n < num; n++)
                {
                    if (p->Free)
                    {
                        Panic.Error("Already Free Page in Compound Page");
                        return;
                    }

                    p->Status    = PageStatus.Free;
                    p->PagesUsed = 0;
                    p->Head      = null;
                    p->Tail      = null;
                    p            = NextPage(p);
                    _FreePages++;
                }
                NextTryPage = head;
            }
        }
Exemplo n.º 7
0
        public static Page *buddy_get_pages(mem_zone *zone,
                                            byte order)
        {
            BUDDY_TRACE("buddy_get_pages, Order: {0:X8}", order);

            Page *page = null;

            if (order >= BUDDY_MAX_ORDER)
            {
                BUDDY_BUG("buddy_get_pages: order >= BUDDY_MAX_ORDER, {0}", order);
                return(null);
            }
            //TODO: lock zone->lock
            page = __alloc_page(order, zone);
            //TODO: unlock zone->lock

            if (page == null)
            {
                BUDDY_TRACE("Out of Memory?");
            }

            return(page);
        }
Exemplo n.º 8
0
        static Page *__alloc_page(byte order,
                                  mem_zone *zone)
        {
            Page *     page          = null;
            free_area *area          = null;
            byte       current_order = 0;

            for (current_order = order;
                 current_order < BUDDY_MAX_ORDER; current_order++)
            {
                area = zone->free_area + current_order;
                if (list_head.list_empty(&area->free_list))
                {
                    continue;
                }
                // remove closest size page
                //page = list_entry(area->free_list.next, struct page, lru);
                page = (Page *)&((Page *)area->free_list.next)->Lru;

                list_head.list_del(&page->Lru);
                rmv_page_order_buddy(page);
                area->nr_free--;
                // expand to lower order
                expand(zone, page, order, current_order, area);
                // compound page
                if (order > 0)
                {
                    prepare_compound_pages(page, order);
                }
                else // single page
                {
                    page->Order = 0;
                }
                return(page);
            }
            return(null);
        }
Exemplo n.º 9
0
        private unsafe Page *AllocatePagesNormal(uint pages, AllocatePageOptions options = default)
        {
            Page *prevHead   = null;
            Page *firstHead  = null;
            var   pagesFound = 0;

            for (var i = 0; i < _TotalPages; i++)
            {
                var page = &Pages[i];
                if (!InUse(page))
                {
                    if (firstHead == null)
                    {
                        firstHead = page;
                    }

                    if (prevHead != null)
                    {
                        SetNext(prevHead, page);
                    }
                    SetInUse(page);

                    pagesFound++;
                    _FreePages--;

                    if (pagesFound >= pages)
                    {
                        return(firstHead);
                    }

                    prevHead = page;
                }
            }

            return(null);
        }
Exemplo n.º 10
0
        public uint GetPageIndex(Page *page)
        {
            var addr = GetAddress(page);

            return((addr - Region.Start) / 4096);
        }
Exemplo n.º 11
0
        public Page *NextPage(Page *page)
        {
            var pageIdx = GetPageIndex(page) + 1;

            return(GetPageByIndex(pageIdx));
        }
Exemplo n.º 12
0
 public uint GetAddress(Page *page)
 {
     return((uint)BuddyAllocatorImplementation.page_to_virt(ZonePtr, page));
 }
Exemplo n.º 13
0
 public uint GetPageNum(Page *page)
 {
     return((uint)BuddyAllocatorImplementation.page_to_virt(ZonePtr, page) >> BuddyAllocatorImplementation.BUDDY_PAGE_SHIFT);
 }
Exemplo n.º 14
0
 public void Free(Page *page)
 {
     BuddyAllocatorImplementation.buddy_free_pages(ZonePtr, page);
 }
Exemplo n.º 15
0
        public Page *AllocatePages(uint pages, AllocatePageOptions options = default)
        {
            lock (this)
            {
                if (pages == 0)
                {
                    KernelMessage.WriteLine("Requesting zero pages");
                    return(null);
                }
                else if (pages > 1 && KConfig.Log.PageAllocation)
                {
                    KernelMessage.WriteLine("Requesting {0} pages", pages);
                }

                //KernelMessage.WriteLine("Request {0} pages...", num);

                uint statBlocks        = 0;
                uint statFreeBlocks    = 0;
                int  statMaxBlockPages = 0;
                uint statRangeChecks   = 0;

                uint cnt = 0;

                if (NextTryPage == null)
                {
                    NextTryPage = PageArray;
                }

                Page *p = NextTryPage;
                while (true)
                {
                    statBlocks++;

                    if (p == null)
                    {
                        p = PageArray;
                    }

                    if (p->Status == PageStatus.Free)
                    {
                        statFreeBlocks++;
                        var head = p;

                        // Found free Page. Check now free range.
                        for (var i = 0; i < pages; i++)
                        {
                            statRangeChecks++;
                            statMaxBlockPages = Math.Max(statMaxBlockPages, i);

                            if (p == null)
                            {
                                break;                        // Reached end. Our Range is incomplete
                            }
                            if (p->Status != PageStatus.Free) // Used -> so we can abort the search
                            {
                                break;
                            }

                            if (i == pages - 1)
                            { // all loops successful. So we found our range.
                                if (p == null)
                                {
                                    Panic.Error("Tail is null");
                                }

                                head->Tail      = p;
                                head->PagesUsed = pages;
                                p = head;
                                for (var n = 0; n < pages; n++)
                                {
                                    if (p->Status != PageStatus.Free)
                                    {
                                        Panic.Error("Page is not Free. PageFrame Array corrupted?");
                                    }

                                    p->Status = PageStatus.Used;
                                    p->Head   = head;
                                    p->Tail   = head->Tail;
                                    p         = NextPage(p);
                                    _FreePages--;
                                }

                                // correct version:
                                NextTryPage = p;

                                // TODO: HACK! Currently, we have somewhere a buffer overrun? Fix that!
                                //NextTryPage = p + 1;

                                //var t = head->Tail;
                                //var a = t->Address;
                                //var anum = (uint)a;
                                ////(uint)head->Tail->Address + 4096 - 1

                                //KernelMessage.Write("<");
                                //KernelMessage.WriteLine("Allocated from {0:X8} to {1:X8}, Status={2}", (uint)head->Address, anum, (uint)head->Status);
                                //KernelMessage.Write(">");

                                //if (head->PhysicalAddress == 0x01CA4000)
                                //{
                                //    KernelMessage.WriteLine("DEBUG-MARKER 2");
                                //    DumpPage(head);
                                //}

                                return(head);
                            }

                            p = NextPage(p);
                        }
                    }

                    if (p->Tail != null)
                    {
                        p = p->Tail;
                    }

                    p = NextPage(p);
                    if (++cnt > _TotalPages)
                    {
                        break;
                    }
                }

                KernelMessage.WriteLine("Blocks={0} FreeBlocks={1} MaxBlockPages={2} RangeChecks={3} cnt={4}", statBlocks, statFreeBlocks, (uint)statMaxBlockPages, statRangeChecks, cnt);
                this.DumpPages();
                Panic.Error("PageFrameAllocator: Could not allocate " + pages + " Pages.");
                return(null);
            }
        }
Exemplo n.º 16
0
 public bool ContainsPage(Page *page)
 {
     return(_Region.Contains(page->Address));
 }
Exemplo n.º 17
0
 public unsafe Page *NextPage(Page *page)
 {
     return(GetPageByIndex(GetPageIndex(page) + 1));
 }
Exemplo n.º 18
0
        public bool ContainsPage(Page *page)
        {
            var addr = GetAddress(page);

            return(Region.Contains(addr));
        }
Exemplo n.º 19
0
 public static void Free(Page *page)
 {
     Default.Free(page);
 }
Exemplo n.º 20
0
 private void DumpPage(Page *p)
 {
     KernelMessage.WriteLine("pNum {0}, phys {1:X8} status {2} struct {3:X8} structPage {4}", GetPageNum(p), GetAddress(p), p->Flags, (uint)p, (uint)p / 4096);
 }
Exemplo n.º 21
0
 public static unsafe Addr MapVirtualPages(Page *pages, uint count, ulong flags, Pgprot_t protection)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 22
0
 public static Page *NextCompoundPage(Page *page)
 {
     return(Default.NextCompoundPage(page));
 }
Exemplo n.º 23
0
 public static Addr GetAddress(Page *page)
 {
     return(Default.GetAddress(page));
 }
Exemplo n.º 24
0
 public static unsafe Addr MapVirtualPages(Page *pages, uint count, ulong flags, Pgprot_t protection)
 {
     return(Addr.Zero);
 }
Exemplo n.º 25
0
 public uint GetPageIndex(Page *page)
 {
     return(GetPageNum(page) - FistPageNum);
 }
Exemplo n.º 26
0
 public Page *NextCompoundPage(Page *page)
 {
     //KernelMessage.WriteLine("NextCompoundPage: {0:X8}, {1:X8}", GetAddress(page), (uint)page->FirstPage);
     return(page->FirstPage);
 }
Exemplo n.º 27
0
        /// <summary>
        /// Allocate a physical page from the free list
        /// </summary>
        /// <returns>The page</returns>
        Page *Allocate(uint num)
        {
            KernelMessage.Write("Request {0} pages...", num);

            var cnt = 0;

            if (lastAllocatedPage == null)
            {
                lastAllocatedPage = PageArray;
            }

            Page *p = lastAllocatedPage->Next;

            while (true)
            {
                if (p == null)
                {
                    p = PageArray;
                }

                if (p->Status == PageStatus.Free)
                {
                    var head = p;

                    // Found free Page. Check now free range.
                    for (var i = 0; i < num; i++)
                    {
                        if (p == null)
                        {
                            break;                        // Reached end. SorRange is incomplete
                        }
                        if (p->Status != PageStatus.Free) // Used -> so we can abort the searach
                        {
                            break;
                        }

                        if (i == num - 1)
                        { // all loops successful. So we found our range.
                            head->Tail      = p;
                            head->PagesUsed = num;
                            p = head;
                            for (var n = 0; n < num; n++)
                            {
                                p->Status = PageStatus.Used;
                                p->Head   = head;
                                p->Tail   = head->Tail;
                                p         = p->Next;
                                PagesUsed++;
                            }
                            lastAllocatedPage = p;

                            KernelMessage.WriteLine("Allocated from {0:X8} to {1:X8}", (uint)head->PhysicalAddress, (uint)head->Tail->PhysicalAddress);

                            return(head);
                        }

                        p = p->Next;
                    }
                }

                if (p->Tail != null)
                {
                    p = p->Tail;
                }

                p = p->Next;
                if (++cnt > PageCount)
                {
                    break;
                }
            }

            Panic.Error("PageFrameAllocator: No free Page found");
            return(null);
        }
Exemplo n.º 28
0
 public uint GetAddress(Page *page)
 {
     return(page->Address);
 }
Exemplo n.º 29
0
 public void Free(Page *page)
 {
     Free(page->PhysicalAddress);
 }
Exemplo n.º 30
0
 public uint GetPageNum(Page *page)
 {
     return(GetAddress(page) / 4096);
 }