From 1c9b09da50affd6309740d28ca3168dcea2ddf57 Mon Sep 17 00:00:00 2001 From: AceVest Date: Sat, 5 Apr 2014 16:32:55 +0800 Subject: [PATCH] support alloc pages from buddy system --- include/bug.h | 17 ++++++++++ include/kernel.h | 13 ++++++++ include/list.h | 2 +- include/page.h | 9 ++++-- include/sysctl.h | 12 +++++++ include/system.h | 3 ++ kernel/printk.c | 1 - kernel/system.c | 2 +- mm/buddy.c | 84 +++++++++++++++++++++++++++++++++++++++++++++--- mm/kmalloc.c | 4 +-- mm/page.c | 30 ++++++++--------- 11 files changed, 150 insertions(+), 27 deletions(-) create mode 100644 include/bug.h create mode 100644 include/kernel.h create mode 100644 include/sysctl.h diff --git a/include/bug.h b/include/bug.h new file mode 100644 index 0000000..f932ba2 --- /dev/null +++ b/include/bug.h @@ -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 index 0000000..70d7d2c --- /dev/null +++ b/include/kernel.h @@ -0,0 +1,13 @@ +/* + * ------------------------------------------------------------------------ + * File Name: kernel.h + * Author: Zhao Yanbai + * Sat Apr 5 14:52:06 2014 + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once + +#include +#include diff --git a/include/list.h b/include/list.h index fba8175..0e6145d 100644 --- a/include/list.h +++ b/include/list.h @@ -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; } diff --git a/include/page.h b/include/page.h index 07cfda2..930a24d 100644 --- a/include/page.h +++ b/include/page.h @@ -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 index 0000000..709141c --- /dev/null +++ b/include/sysctl.h @@ -0,0 +1,12 @@ +/* + * ------------------------------------------------------------------------ + * File Name: sysctl.h + * Author: Zhao Yanbai + * Sat Apr 5 14:51:53 2014 + * Description: none + * ------------------------------------------------------------------------ + */ + +#pragma once + +#include diff --git a/include/system.h b/include/system.h index dd1301a..bdd5906 100644 --- a/include/system.h +++ b/include/system.h @@ -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); diff --git a/kernel/printk.c b/kernel/printk.c index 9ab6138..d893720 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -24,4 +24,3 @@ int printk(const char *fmtstr, ...) printString(pkbuf,0x2); return 0; } - diff --git a/kernel/system.c b/kernel/system.c index 726230c..7d9fe73 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -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__); diff --git a/mm/buddy.c b/mm/buddy.c index 7253252..1ce579f 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -7,12 +7,13 @@ * ------------------------------------------------------------------------ */ #include +#include -#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_orderfree_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>PAGE_SHIFT); //printk("%08x\n", page->mapNR); - free_pages(page); + old_free_pages(page); } diff --git a/mm/page.c b/mm/page.c index e0c4d65..5181754 100644 --- 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) return NULL; @@ -185,10 +185,10 @@ pPage alloc_pages(unsigned int order) int i; for(i=order; iorder; @@ -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 && orderlist, &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