]> Zhao Yanbai Git Server - kernel.git/commitdiff
新的简单的bootmem分配算法
authoracevest <zhaoyanbai@126.com>
Tue, 2 Nov 2021 05:28:46 +0000 (13:28 +0800)
committeracevest <zhaoyanbai@126.com>
Wed, 3 Nov 2021 02:45:47 +0000 (10:45 +0800)
include/mm.h
mm/bootmem.c
mm/buddy.c
mm/mm.c

index 10d4f45425e1b20b3fd835c8c8952ba51135db7e..ea778d4a15258b50687e953f830f7ff7ad4d9de9 100644 (file)
@@ -18,7 +18,5 @@ void *alloc_bootmem(unsigned long size, unsigned long align);
 unsigned long bootmem_max_pfn();
 unsigned long bootmem_page_state(unsigned long pfn);
 
-#define bootmem_alloc_pages(n) alloc_bootmem((n)*PAGE_SIZE, PAGE_SIZE)
-
 kmem_cache_t *kmem_cache_create(const char *name, size_t size, size_t align);
 void *kmem_cache_alloc(kmem_cache_t *cache, gfp_t gfpflags);
index 0b0dea31e60989ed5c6b87b47d7137d93222ad4d..d491194976ced71da03a66789c9d5b2c2c7bc453 100644 (file)
@@ -89,7 +89,10 @@ void e820_init_bootmem_data() {
         bootmem_data.max_pfn = max_support_pfn;
         printk("memory > 1G, only support to 1G.\n");
     }
+
     printk("pfn_min: %d pfn_max: %d\n", bootmem_data.min_pfn, bootmem_data.max_pfn);
+
+    bootmem_data.last_hit_pfn = bootmem_data.min_pfn;
 }
 
 void register_bootmem_pages() {
@@ -120,8 +123,8 @@ void reserve_bootmem(unsigned long bgn_pfn, unsigned long end_pfn) {
 }
 
 void reserve_kernel_pages() {
-    // reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end)));
-    reserve_bootmem(0, PFN_UP(va2pa(&kernel_end)));
+    reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end)));
+    // reserve_bootmem(0, PFN_UP(va2pa(&kernel_end)));
 }
 
 void reserve_bootmem_pages() {
@@ -145,6 +148,10 @@ void init_bootmem_allocator() {
     reserve_kernel_pages();
 
     reserve_bootmem_pages();
+
+    // 强制保留最开始的一页
+    // 免得alloc的时候分不清是失败,还是分配的第0页
+    reserve_bootmem(0, 1);
 }
 
 void init_bootmem() {
@@ -162,6 +169,54 @@ void init_bootmem() {
 #endif
 }
 
+// 由于只有在构建buddy system的时候才会用到
+// 所以这里就简单实现
+void *alloc_from_bootmem(unsigned long size, char *title) {
+    void *region = NULL;
+    unsigned long pfn_cnt = PFN_UP(size);
+    printk("%s alloc bootmem size: %x pfn: %d\n", title, size, pfn_cnt);
+
+    bootmem_data_t *pbd = &bootmem_data;
+
+    // 从该处开始查找空闲区间
+    unsigned long search_bgn_pfn = pbd->min_pfn;
+
+find_next_block:
+    // 先找到第一个空闲的pfn
+    unsigned long free_pfn = pbd->max_pfn;
+    for (unsigned long pfn = search_bgn_pfn; pfn < pbd->max_pfn; pfn++) {
+        if (bootmem_page_state(pfn) == BOOTMEM_PAGE_FREE) {
+            free_pfn = pfn;
+            break;
+        }
+        // printk("pfn %d alloced\n", pfn);
+    }
+
+    // 检验接下来是否有足够的size
+    unsigned long bgn_pfn = free_pfn;
+    unsigned long end_pfn = bgn_pfn + pfn_cnt;
+
+    // printk("free_pfn: %d end_pfn:%d max_pfn:%d \n", free_pfn, end_pfn, pbd->max_pfn);
+
+    // 剩余空间不足
+    if (bgn_pfn >= pbd->max_pfn || end_pfn >= pbd->max_pfn) {
+        return region;
+    }
+
+    //
+    for (unsigned long pfn = bgn_pfn; pfn < end_pfn; pfn++) {
+        if (bootmem_page_state(pfn) != BOOTMEM_PAGE_FREE) {
+            search_bgn_pfn = pfn + 1;
+            goto find_next_block;
+        }
+    }
+
+    reserve_bootmem(bgn_pfn, end_pfn);
+    region = pfn2va(bgn_pfn);
+
+    return region;
+}
+
 void *alloc_bootmem(unsigned long size, unsigned long align) {
     bootmem_data_t *pbd = &bootmem_data;
 
index 68c2a8117492ed29d0d56529d573842e26e35ba3..ba7213ac99c038a9e540ff1e5920bb98535c2f84 100644 (file)
@@ -30,7 +30,8 @@ page_t *_va2page(unsigned long addr) {
     assert(page >= buddy_system.page_map);
     // assert(page < buddy_system.page_map_end);
     if (page >= buddy_system.page_map_end) {
-        printk("buddy_system.page_map %08x buddy_system.page_map_end %08x\n", buddy_system.page_map, buddy_system.page_map_end);
+        printk("buddy_system.page_map %08x buddy_system.page_map_end %08x\n", buddy_system.page_map,
+               buddy_system.page_map_end);
         printk("error %s page %08x addr %08x\n", __func__, page, addr);
         panic("error");
     }
@@ -199,7 +200,7 @@ void init_buddy_system() {
 
     // init page map
     unsigned long page_map_size = pfn_cnt * sizeof(page_t);
-    buddy_system.page_map = alloc_bootmem(page_map_size, PAGE_SIZE);
+    buddy_system.page_map = alloc_from_bootmem(page_map_size, "buddy");
     if (0 == buddy_system.page_map) {
         printk("can not go on playing...\n");
         while (1)
@@ -207,7 +208,8 @@ void init_buddy_system() {
     }
 
     buddy_system.page_map_end = buddy_system.page_map + pfn_cnt + 1;
-    printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map_end, pfn_cnt, sizeof(page_t));
+    printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map_end,
+           pfn_cnt, sizeof(page_t));
     for (i = 0; i < pfn_cnt; ++i) {
         page = buddy_system.page_map + i;
         memset((void *)page, 0, sizeof(page_t));
diff --git a/mm/mm.c b/mm/mm.c
index ae3e7d57ddc4917a2084ad92117814ed016c4d83..9652e1e128df90ff6f621ef3add8de2cd09909c3 100644 (file)
--- a/mm/mm.c
+++ b/mm/mm.c
@@ -54,7 +54,7 @@ void init_paging() {
         unsigned long ti = pfn % PAGE_PTE_CNT;
         unsigned long page_addr = pfn2pa(pfn);
         if (ti == 0) {
-            pgtb_addr = (unsigned long)va2pa(bootmem_alloc_pages(1));
+            pgtb_addr = (unsigned long)va2pa(alloc_from_bootmem(PAGE_SIZE, "paging"));
             if (0 == pgtb_addr) panic("No Pages for Paging...");
 
             memset((void *)pgtb_addr, 0, PAGE_SIZE);
@@ -83,6 +83,7 @@ void init_mm() {
     printk("init bootmem alloc...\n");
     init_bootmem();
     printk("init global paging...\n");
+
     init_paging();
 
     printk("init buddy system...\n");