From: acevest Date: Tue, 2 Nov 2021 05:28:46 +0000 (+0800) Subject: 新的简单的bootmem分配算法 X-Git-Url: http://zhaoyanbai.com/repos/man.dnssec-importkey.html?a=commitdiff_plain;h=6a1ac2bb91951205732db4074253626dce780efc;p=kernel.git 新的简单的bootmem分配算法 --- diff --git a/include/mm.h b/include/mm.h index 10d4f45..ea778d4 100644 --- a/include/mm.h +++ b/include/mm.h @@ -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); diff --git a/mm/bootmem.c b/mm/bootmem.c index 0b0dea3..d491194 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -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; diff --git a/mm/buddy.c b/mm/buddy.c index 68c2a81..ba7213a 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -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 ae3e7d5..9652e1e 100644 --- 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");