]> Zhao Yanbai Git Server - kernel.git/commitdiff
support alloc pages from buddy system
authorAceVest <zhaoyanbai@126.com>
Sat, 5 Apr 2014 08:32:55 +0000 (16:32 +0800)
committerAceVest <zhaoyanbai@126.com>
Sat, 5 Apr 2014 08:32:55 +0000 (16:32 +0800)
include/bug.h [new file with mode: 0644]
include/kernel.h [new file with mode: 0644]
include/list.h
include/page.h
include/sysctl.h [new file with mode: 0644]
include/system.h
kernel/printk.c
kernel/system.c
mm/buddy.c
mm/kmalloc.c
mm/page.c

diff --git a/include/bug.h b/include/bug.h
new file mode 100644 (file)
index 0000000..f932ba2
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: bug.h
+ *      Author: Zhao Yanbai
+ *              Sat Apr  5 14:51:50 2014
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+#define BUG() do {                                          \
+    printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);   \
+    panic("BUG!");                                          \
+} while (0)
+
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
diff --git a/include/kernel.h b/include/kernel.h
new file mode 100644 (file)
index 0000000..70d7d2c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: kernel.h
+ *      Author: Zhao Yanbai
+ *              Sat Apr  5 14:52:06 2014
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+#include <system.h>
+#include <bug.h>
index fba8175b3e717869ccd21e8afb325222cf40a15b..0e6145daafc65de87c21c57adb499a2eab4664ba 100644 (file)
@@ -81,7 +81,7 @@ static inline void list_del_init(list_head_t *entry)
     INIT_LIST_HEAD(entry);
 }
 
-static inline int list_is_empty(list_head_t *head)
+static inline int list_empty(list_head_t *head)
 {
     return head->next == head;
 }
index 07cfda2fe4e62ed14069ef3c4c164d1f42a6b867..930a24d4c87469818cb9aef0c0eee9064946014b 100644 (file)
@@ -57,6 +57,7 @@ typedef unsigned long pte_t;
 #define va2pfn(addr)    pa2pfn(va2pa(addr))
 #define pfn2va(pfn)     pa2va(pfn2pa(pfn))
 
+#define valid_va(addr)  ((addr) >= PAGE_OFFSET)
 
 #define PFN_UP(addr)     (((addr) + PAGE_SIZE - 1) >> PAGE_SHIFT)
 #define PFN_DW(addr)     ((addr) >> PAGE_SHIFT)
@@ -103,6 +104,10 @@ typedef struct free_area
     list_head_t   free_list;
 } free_area_t;
 
+
+unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order);
+void free_pages(unsigned long addr, unsigned int order);
+
 // TODO Remove
 typedef struct page_
 {
@@ -123,8 +128,8 @@ typedef struct free_area_
 } FreeArea, *pFreeArea;
 
 
-pPage    alloc_pages(unsigned int order);
-void    free_pages(pPage page);
+pPage   old_alloc_pages(unsigned int order);
+void    old_free_pages(pPage page);
 //void    free_pages(pPage page, unsigned int order);
 void    disp_free_area();
 
diff --git a/include/sysctl.h b/include/sysctl.h
new file mode 100644 (file)
index 0000000..709141c
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: sysctl.h
+ *      Author: Zhao Yanbai
+ *              Sat Apr  5 14:51:53 2014
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+#include <kernel.h>
index dd1301abe5798034c676a041bfe4fa90133cceca..bdd5906fc7813b8bb4d7a09cb5f875bce1fedf69 100644 (file)
@@ -25,6 +25,9 @@
 #include "types.h"
 #include "printk.h"
 
+#define likely(x)       __builtin_expect(!!(x), 1)
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+
 void    *kmalloc(size_t size);
 void    kfree(void *p);
 
index 9ab61384fee3885fdd718a71c750d34749c45c60..d89372023b8479365ab64c9fae6ec3a7a1a99769 100644 (file)
@@ -24,4 +24,3 @@ int printk(const char *fmtstr, ...)
     printString(pkbuf,0x2);
     return 0;
 }
-
index 726230cab96952620541d2568e4fd6d797ce05ba..7d9fe730ee90ed396e4055b2e2f129394e0faec2 100644 (file)
@@ -33,7 +33,7 @@ int    sysc_reboot(int mode)
 }
 
 
-inline void panic(char *msg)
+void panic(char *msg)
 {
     printk("PANIC:\"%s\" file:%s function:%s line:%d\n",
         msg, __FILE__, __FUNCTION__, __LINE__);
index 725325276b15d6e70f9cb4c7ea6f82fb72648613..1ce579f701263c2be3ceec7ca839e43609e5eb8a 100644 (file)
@@ -7,12 +7,13 @@
  * ------------------------------------------------------------------------
  */
 #include <mm.h>
+#include <sysctl.h>
 
-#define MAX_ORDER       10
+#define MAX_ORDER      5
 struct buddy_system
 {
     page_t      *page_map;
-    free_area_t free_area[MAX_ORDER + 1];
+    free_area_t free_area[MAX_ORDER];
 };
 
 struct buddy_system buddy_system;
@@ -25,6 +26,61 @@ int buddy_is_free(page_t *page, unsigned int order)
     return 0;
 }
 
+#define va2page(addr)   (buddy_system.page_map + va2pfn(addr))
+#define page2va(page)   (pfn2va((page) - buddy_system.page_map))
+
+page_t *__alloc_pages(unsigned int order)
+{
+    //
+    page_t *page = 0;
+    page_t *buddy= 0;
+    free_area_t *area;
+    unsigned long size;
+    unsigned int select_order;
+    for(select_order=order; select_order<MAX_ORDER; ++select_order)
+    {
+        area = buddy_system.free_area + select_order;
+        if(!list_empty(&(area->free_list)))
+        {
+            goto found;
+        }
+    }
+
+    return 0;
+
+found:
+    page = list_entry(area->free_list.next, page_t, lru);
+    list_del(&(page->lru));
+    ClearPagePrivate(page);
+    page->private = 0;
+    area->free_count--;
+
+    while(select_order > order)
+    {
+        area--;
+        select_order--;
+        size = 1UL << select_order;
+
+        buddy = page + size;
+        list_add(&(page->lru), &(area->free_list)); 
+        area->free_count++;
+        buddy->private = select_order;
+        SetPagePrivate(buddy);
+    }
+
+    return page;
+}
+
+unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order)
+{
+    // gfp_mask
+    // ...
+
+    page_t *page = __alloc_pages(order);
+
+    return (unsigned long) page2va(page);
+}
+
 void __free_pages(page_t *page, unsigned int order)
 {
     if(order > MAX_ORDER)
@@ -33,7 +89,7 @@ void __free_pages(page_t *page, unsigned int order)
     page_t *buddy = 0;
     page_t *base  = buddy_system.page_map;
     unsigned long page_inx  = page - base;
-    while(order < MAX_ORDER)
+    while(order < (MAX_ORDER-1))
     {
         unsigned long buddy_inx = page_inx ^ (1UL << order);
         buddy = base + buddy_inx;
@@ -60,10 +116,21 @@ void __free_pages(page_t *page, unsigned int order)
     buddy_system.free_area[order].free_count++;
 }
 
+
+void free_pages(unsigned long addr, unsigned int order)
+{
+    if(!valid_va(addr))
+    {
+        BUG_ON(!valid_va(addr));
+    }
+
+    __free_pages(va2page(addr), order);
+}
+
 void dump_buddy_system()
 {
     unsigned long i;
-    for(i=0; i<MAX_ORDER+1; ++i)
+    for(i=0; i<MAX_ORDER; ++i)
     {
         printk("order %2d free_count %d ", i, buddy_system.free_area[i].free_count);
 
@@ -82,6 +149,13 @@ void dump_buddy_system()
         printk("\n");
     }
 
+
+    printk("alloc 1 pages va 0x%08x\n", alloc_pages(0, 0));
+    printk("alloc 1 pages va 0x%08x\n", alloc_pages(0, 0));
+    printk("alloc 2 pages va 0x%08x\n", alloc_pages(0, 1));
+    printk("alloc 4 pages va 0x%08x\n", alloc_pages(0, 2));
+    printk("alloc 8 pages va 0x%08x\n", alloc_pages(0, 3));
+
 }
 
 void init_buddy_system()
@@ -93,7 +167,7 @@ void init_buddy_system()
     // init free area
     memset(&buddy_system, 0, sizeof(buddy_system));
 
-    for(i=0; i<MAX_ORDER+1; ++i)
+    for(i=0; i<MAX_ORDER; ++i)
     {
         INIT_LIST_HEAD(&(buddy_system.free_area[i].free_list));
     }
index 6fdd2f4c57b073a290faff9fc4075fd592e7a0fa..443ae8034001877e415a9a4deac6167c492360a2 100644 (file)
@@ -36,7 +36,7 @@ void    *kmalloc(size_t size)
     assert(0<size && size<=32*PAGE_SIZE);
     int    order = get_order(size);
     void    *p;
-    pPage page = alloc_pages(order);
+    pPage page = old_alloc_pages(order);
 
     if(page == NULL)
         return NULL;
@@ -58,5 +58,5 @@ void    kfree(void *p)
     //printk("kfree:%08x %08x %08x ", p, va2pa(p));
     page += ((unsigned long)va2pa(p)>>PAGE_SHIFT);
     //printk("%08x\n", page->mapNR);
-    free_pages(page);
+    old_free_pages(page);
 }
index e0c4d6511c70f2e8fbd8eac6a8e6921c59005f6b..5181754ffd697e2d4d24ede873fa54562b263c1a 100644 (file)
--- a/mm/page.c
+++ b/mm/page.c
@@ -132,10 +132,10 @@ void do_wp_page(void *addr)
     load_cr3(current);
 }
 
-inline pPage __alloc_pages(unsigned int order, unsigned int alloc_order)
+inline pPage __old_alloc_pages(unsigned int order, unsigned int alloc_order)
 {
     assert(0 <= order && order<MAX_OLD_ORDER);
-    assert(!list_is_empty(&freeArea[order].freeList));
+    assert(!list_empty(&freeArea[order].freeList));
     assert(alloc_order <= order);
 
     pListHead pl = freeArea[order].freeList.next;
@@ -174,10 +174,10 @@ inline pPage __alloc_pages(unsigned int order, unsigned int alloc_order)
     add_page2list(page, order-1);
 
     //int j=2000000;while(j--);
-    return __alloc_pages(order-1, alloc_order);
+    return __old_alloc_pages(order-1, alloc_order);
 }
 
-pPage    alloc_pages(unsigned int order)
+pPage    old_alloc_pages(unsigned int order)
 {
     if(order<0 || order>=MAX_OLD_ORDER)
         return NULL;
@@ -185,10 +185,10 @@ pPage    alloc_pages(unsigned int order)
     int i;
     for(i=order; i<MAX_OLD_ORDER; i++)
     {
-        if(list_is_empty(&freeArea[i].freeList))
+        if(list_empty(&freeArea[i].freeList))
             continue;
 
-        return    __alloc_pages(i, order);
+        return    __old_alloc_pages(i, order);
     }
     return NULL;
 }
@@ -226,7 +226,7 @@ pPage    get_buddy_page(pPage page, unsigned int order)
     return NULL;
 }
 
-void    free_pages(pPage page)
+void    old_free_pages(pPage page)
 {
     assert(page != NULL);
     unsigned int order = page->order;
@@ -257,16 +257,16 @@ void    free_pages(pPage page)
             panic("bug");
         }
 #endif
-        free_pages(page);
+        old_free_pages(page);
     }
 }
 
 #else
 
-inline pPage __alloc_pages(unsigned int order, unsigned int alloc_order)
+inline pPage __old_alloc_pages(unsigned int order, unsigned int alloc_order)
 {
     assert(0 <= order && order<MAX_OLD_ORDER);
-    assert(!list_is_empty(&freeArea[order].freeList));
+    assert(!list_empty(&freeArea[order].freeList));
     assert(alloc_order <= order);
 
     pListHead pl = freeArea[order].freeList.next;
@@ -285,10 +285,10 @@ inline pPage __alloc_pages(unsigned int order, unsigned int alloc_order)
     pg += (1 << (order-1));
     list_add(&pg->list, &freeArea[order-1].freeList);
 
-    return __alloc_pages(order-1, alloc_order);
+    return __old_alloc_pages(order-1, alloc_order);
 }
 
-pPage alloc_pages(unsigned int order)
+pPage old_alloc_pages(unsigned int order)
 {
     if(order >= MAX_OLD_ORDER)
         return NULL;
@@ -296,17 +296,17 @@ pPage alloc_pages(unsigned int order)
     int i;
     for(i=order; i<MAX_OLD_ORDER; i++)
     {
-        if(list_is_empty(&freeArea[i].freeList))
+        if(list_empty(&freeArea[i].freeList))
             continue;
 
-        return __alloc_pages(i, order);
+        return __old_alloc_pages(i, order);
     }
 
     return NULL;
 }
 
 
-void free_pages(pPage page, unsigned int order)
+void old_free_pages(pPage page, unsigned int order)
 {
     assert(0<=order &&  order<MAX_OLD_ORDER);
     assert(page != NULL);