From ef414c7fd2db100afcc32a55da2d1d46d00254b4 Mon Sep 17 00:00:00 2001 From: acevest Date: Tue, 2 Nov 2021 09:15:07 +0800 Subject: [PATCH] =?utf8?q?=E6=8B=86=E5=88=86=E5=87=BAbootmem=E5=B1=82?= =?utf8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/boot/boot.h | 13 +++ mm/bootmem.c | 264 ++++++++++++++++++++++++++++++++++++++++++++ mm/mm.c | 263 ------------------------------------------- 3 files changed, 277 insertions(+), 263 deletions(-) create mode 100644 mm/bootmem.c diff --git a/include/boot/boot.h b/include/boot/boot.h index 8894def..3507d5e 100644 --- a/include/boot/boot.h +++ b/include/boot/boot.h @@ -48,6 +48,19 @@ struct boot_params struct e820map e820map; }; +typedef struct bootmem_data +{ + unsigned long min_pfn; + unsigned long max_pfn; + + unsigned long last_offset; // offset to pfn2pa(this->min_pfn); + unsigned long last_hit_pfn; // last hit index in bitmap + + void *bitmap; + unsigned long mapsize; +} bootmem_data_t; + extern struct boot_params boot_params; +extern bootmem_data_t bootmem_data; #endif diff --git a/mm/bootmem.c b/mm/bootmem.c new file mode 100644 index 0000000..d332411 --- /dev/null +++ b/mm/bootmem.c @@ -0,0 +1,264 @@ +/* + * ------------------------------------------------------------------------ + * File Name: bootmem.c + * Author: Zhao Yanbai + * 2021-11-02 09:07:32 Tuesday CST + * Description: none + * ------------------------------------------------------------------------ + */ +#include +#include +#include +#include + +extern char kernel_begin, kernel_end; + +static void e820_print_type(unsigned long type) +{ + switch (type) + { + case E820_RAM: + printk("usable"); + break; + case E820_RESERVED: + printk("reserved"); + break; + case E820_ACPI: + printk("ACPI data"); + break; + case E820_NVS: + printk("ACPI NVS"); + break; + case E820_UNUSABLE: + printk("unusable"); + break; + default: + printk("type %x", type); + break; + } +} + +void e820_print_map() +{ + unsigned int i = 0; + + for (i = 0; i < boot_params.e820map.map_cnt; ++i) + { + struct e820_entry *p = boot_params.e820map.map + i; + + printk(" [%02d] 0x%08x - 0x%08x size %- 10d %8dKB %5dMB ", i, p->addr, p->addr + p->size - 1, p->size, p->size >> 10, p->size >> 20); + + e820_print_type(p->type); + + printk("\n"); + } +} + +bootmem_data_t bootmem_data; + +unsigned long bootmem_max_pfn() +{ + return bootmem_data.max_pfn; +} + +unsigned long bootmem_page_state(unsigned long pfn) +{ + return constant_test_bit(pfn, bootmem_data.bitmap); +} + +void e820_init_bootmem_data() +{ + unsigned int i = 0; + + memset(&bootmem_data, 0, sizeof(bootmem_data)); + bootmem_data.min_pfn = ~0UL; + + unsigned long bgn_pfn; + unsigned long end_pfn; + + for (i = 0; i < boot_params.e820map.map_cnt; ++i) + { + struct e820_entry *p = boot_params.e820map.map + i; + + if (p->type != E820_RAM) + continue; + + bgn_pfn = PFN_UP(p->addr); + end_pfn = PFN_DW(p->addr + p->size); + + if (bootmem_data.max_pfn < end_pfn) + bootmem_data.max_pfn = end_pfn; + } + + bootmem_data.min_pfn = 0; + + // limit max_pfn + unsigned long max_support_pfn = PFN_DW(MAX_SUPT_PHYMM_SIZE); + if (bootmem_data.max_pfn > max_support_pfn) + { + bootmem_data.max_pfn = max_support_pfn; + } +} + +void register_bootmem_pages() +{ + unsigned int i = 0; + unsigned int j = 0; + + for (i = 0; i < boot_params.e820map.map_cnt; ++i) + { + struct e820_entry *p = boot_params.e820map.map + i; + + if (p->type != E820_RAM) + continue; + + unsigned long bgn_pfn = PFN_UP(p->addr); + unsigned long end_pfn = PFN_DW(p->addr + p->size); + + for (j = bgn_pfn; j < end_pfn; ++j) + { + test_and_clear_bit(j, bootmem_data.bitmap); + } + } +} + +void reserve_bootmem(unsigned long bgn_pfn, unsigned long end_pfn) +{ + //printk("reserve %d %d\n", bgn_pfn, end_pfn); + + int i = 0; + for (i = bgn_pfn; i < end_pfn; ++i) + { + test_and_set_bit(i, bootmem_data.bitmap); + } +} + +void reserve_kernel_pages() +{ + //reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end))); + reserve_bootmem(0, PFN_UP(va2pa(&kernel_end))); +} + +void reserve_bootmem_pages() +{ + unsigned long bgn_pfn = PFN_DW(va2pa(bootmem_data.bitmap)); + + unsigned long end_pfn = bgn_pfn + PFN_UP(bootmem_data.mapsize); + + reserve_bootmem(bgn_pfn, end_pfn); +} + +void init_bootmem_allocator() +{ + int mapsize = (bootmem_data.max_pfn + 7) / 8; + + bootmem_data.bitmap = &kernel_end; + bootmem_data.mapsize = mapsize; + + memset(bootmem_data.bitmap, 0xFF, mapsize); + + register_bootmem_pages(); + + reserve_kernel_pages(); + + reserve_bootmem_pages(); +} + +void init_bootmem() +{ + e820_print_map(); + e820_init_bootmem_data(); + init_bootmem_allocator(); + +#if 0 + printk("alloc 10 bytes align 8 addr %08x\n", alloc_bootmem(10, 8)); + printk("alloc 40961 bytes align 4096 addr %08x\n", alloc_bootmem(40961, 4096)); + printk("alloc 5 bytes align 4 addr %08x\n", alloc_bootmem(5, 4)); + printk("alloc 10 bytes align 1024 addr %08x\n", alloc_bootmem(10, 1024)); + printk("alloc 123bytes align 2 addr %08x\n", alloc_bootmem(123, 2)); + printk("alloc 123bytes align 2 addr %08x\n", alloc_bootmem(123, 2)); +#endif +} + +void *alloc_bootmem(unsigned long size, unsigned long align) +{ + bootmem_data_t *pbd = &bootmem_data; + + assert(size != 0); + assert((align & (align - 1)) == 0); // must be power of 2 + + unsigned long fallback = 0; + unsigned long bgn_pfn, end_pfn, step; + + step = align >> PAGE_SHIFT; + step = step > 0 ? step : 1; + + bgn_pfn = ALIGN(pbd->min_pfn, step); + end_pfn = pbd->max_pfn; + + // start from last position + if (pbd->last_hit_pfn > bgn_pfn) + { + fallback = bgn_pfn + 1; + bgn_pfn = ALIGN(pbd->last_hit_pfn, step); + } + + while (1) + { + int merge; + void *region; + unsigned long i, search_end_pfn; + unsigned long start_off, end_off; + + find_block: + + bgn_pfn = find_next_zero_bit(pbd->bitmap, end_pfn, bgn_pfn); + bgn_pfn = ALIGN(bgn_pfn, step); + + search_end_pfn = bgn_pfn + PFN_UP(size); + + if (bgn_pfn >= end_pfn || search_end_pfn > end_pfn) + break; + + for (i = bgn_pfn; i < search_end_pfn; ++i) + { + if (bootmem_page_state(i) != BOOTMEM_PAGE_FREE) + { // space not enough + bgn_pfn = ALIGN(i, step); + if (bgn_pfn == i) + bgn_pfn += step; + + goto find_block; + } + } + + // try to use the unused part of last page + if (pbd->last_offset & (PAGE_SIZE - 1) && PFN_DW(pbd->last_offset) + 1 == bgn_pfn) + start_off = ALIGN(pbd->last_offset, align); + else + start_off = pfn2pa(bgn_pfn); + + merge = PFN_DW(start_off) < bgn_pfn; + end_off = start_off + size; + + pbd->last_offset = end_off; + pbd->last_hit_pfn = PFN_UP(end_off); + + reserve_bootmem(PFN_DW(start_off) + merge, PFN_UP(end_off)); + + region = pa2va(start_off); + + memset(region, 0, size); + + return region; + } + + if (fallback) + { + bgn_pfn = ALIGN(fallback - 1, step); + fallback = 0; + goto find_block; + } + + return 0; +} \ No newline at end of file diff --git a/mm/mm.c b/mm/mm.c index 115f915..2f5a181 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -22,273 +22,10 @@ #include #include -extern char kernel_begin, kernel_end; extern char etext, edata, end; extern void init_buddy_system(); extern void init_slub_system(); -static void e820_print_type(unsigned long type) -{ - switch (type) - { - case E820_RAM: - printk("usable"); - break; - case E820_RESERVED: - printk("reserved"); - break; - case E820_ACPI: - printk("ACPI data"); - break; - case E820_NVS: - printk("ACPI NVS"); - break; - case E820_UNUSABLE: - printk("unusable"); - break; - default: - printk("type %x", type); - break; - } -} - -void e820_print_map() -{ - unsigned int i = 0; - - for (i = 0; i < boot_params.e820map.map_cnt; ++i) - { - struct e820_entry *p = boot_params.e820map.map + i; - - printk(" [%02d] 0x%08x - 0x%08x size %- 10d %8dKB %5dMB ", i, p->addr, p->addr + p->size - 1, p->size, p->size >> 10, p->size >> 20); - - e820_print_type(p->type); - - printk("\n"); - } -} - -typedef struct bootmem_data -{ - unsigned long min_pfn; - unsigned long max_pfn; - - unsigned long last_offset; // offset to pfn2pa(this->min_pfn); - unsigned long last_hit_pfn; // last hit index in bitmap - - void *bitmap; - unsigned long mapsize; -} bootmem_data_t; - -bootmem_data_t bootmem_data; - -unsigned long bootmem_max_pfn() -{ - return bootmem_data.max_pfn; -} - -unsigned long bootmem_page_state(unsigned long pfn) -{ - return constant_test_bit(pfn, bootmem_data.bitmap); -} - -void e820_init_bootmem_data() -{ - unsigned int i = 0; - - memset(&bootmem_data, 0, sizeof(bootmem_data)); - bootmem_data.min_pfn = ~0UL; - - unsigned long bgn_pfn; - unsigned long end_pfn; - - for (i = 0; i < boot_params.e820map.map_cnt; ++i) - { - struct e820_entry *p = boot_params.e820map.map + i; - - if (p->type != E820_RAM) - continue; - - bgn_pfn = PFN_UP(p->addr); - end_pfn = PFN_DW(p->addr + p->size); - - if (bootmem_data.max_pfn < end_pfn) - bootmem_data.max_pfn = end_pfn; - } - - bootmem_data.min_pfn = 0; - - // limit max_pfn - unsigned long max_support_pfn = PFN_DW(MAX_SUPT_PHYMM_SIZE); - if (bootmem_data.max_pfn > max_support_pfn) - { - bootmem_data.max_pfn = max_support_pfn; - } -} - -void register_bootmem_pages() -{ - unsigned int i = 0; - unsigned int j = 0; - - for (i = 0; i < boot_params.e820map.map_cnt; ++i) - { - struct e820_entry *p = boot_params.e820map.map + i; - - if (p->type != E820_RAM) - continue; - - unsigned long bgn_pfn = PFN_UP(p->addr); - unsigned long end_pfn = PFN_DW(p->addr + p->size); - - for (j = bgn_pfn; j < end_pfn; ++j) - { - test_and_clear_bit(j, bootmem_data.bitmap); - } - } -} - -void reserve_bootmem(unsigned long bgn_pfn, unsigned long end_pfn) -{ - //printk("reserve %d %d\n", bgn_pfn, end_pfn); - - int i = 0; - for (i = bgn_pfn; i < end_pfn; ++i) - { - test_and_set_bit(i, bootmem_data.bitmap); - } -} - -void reserve_kernel_pages() -{ - //reserve_bootmem(PFN_DW(va2pa(&kernel_begin)), PFN_UP(va2pa(&kernel_end))); - reserve_bootmem(0, PFN_UP(va2pa(&kernel_end))); -} - -void reserve_bootmem_pages() -{ - unsigned long bgn_pfn = PFN_DW(va2pa(bootmem_data.bitmap)); - - unsigned long end_pfn = bgn_pfn + PFN_UP(bootmem_data.mapsize); - - reserve_bootmem(bgn_pfn, end_pfn); -} - -void init_bootmem_allocator() -{ - int mapsize = (bootmem_data.max_pfn + 7) / 8; - - bootmem_data.bitmap = &kernel_end; - bootmem_data.mapsize = mapsize; - - memset(bootmem_data.bitmap, 0xFF, mapsize); - - register_bootmem_pages(); - - reserve_kernel_pages(); - - reserve_bootmem_pages(); -} - -void init_bootmem() -{ - e820_print_map(); - e820_init_bootmem_data(); - init_bootmem_allocator(); - -#if 0 - printk("alloc 10 bytes align 8 addr %08x\n", alloc_bootmem(10, 8)); - printk("alloc 40961 bytes align 4096 addr %08x\n", alloc_bootmem(40961, 4096)); - printk("alloc 5 bytes align 4 addr %08x\n", alloc_bootmem(5, 4)); - printk("alloc 10 bytes align 1024 addr %08x\n", alloc_bootmem(10, 1024)); - printk("alloc 123bytes align 2 addr %08x\n", alloc_bootmem(123, 2)); - printk("alloc 123bytes align 2 addr %08x\n", alloc_bootmem(123, 2)); -#endif -} - -void *alloc_bootmem(unsigned long size, unsigned long align) -{ - bootmem_data_t *pbd = &bootmem_data; - - assert(size != 0); - assert((align & (align - 1)) == 0); // must be power of 2 - - unsigned long fallback = 0; - unsigned long bgn_pfn, end_pfn, step; - - step = align >> PAGE_SHIFT; - step = step > 0 ? step : 1; - - bgn_pfn = ALIGN(pbd->min_pfn, step); - end_pfn = pbd->max_pfn; - - // start from last position - if (pbd->last_hit_pfn > bgn_pfn) - { - fallback = bgn_pfn + 1; - bgn_pfn = ALIGN(pbd->last_hit_pfn, step); - } - - while (1) - { - int merge; - void *region; - unsigned long i, search_end_pfn; - unsigned long start_off, end_off; - - find_block: - - bgn_pfn = find_next_zero_bit(pbd->bitmap, end_pfn, bgn_pfn); - bgn_pfn = ALIGN(bgn_pfn, step); - - search_end_pfn = bgn_pfn + PFN_UP(size); - - if (bgn_pfn >= end_pfn || search_end_pfn > end_pfn) - break; - - for (i = bgn_pfn; i < search_end_pfn; ++i) - { - if (bootmem_page_state(i) != BOOTMEM_PAGE_FREE) - { // space not enough - bgn_pfn = ALIGN(i, step); - if (bgn_pfn == i) - bgn_pfn += step; - - goto find_block; - } - } - - // try to use the unused part of last page - if (pbd->last_offset & (PAGE_SIZE - 1) && PFN_DW(pbd->last_offset) + 1 == bgn_pfn) - start_off = ALIGN(pbd->last_offset, align); - else - start_off = pfn2pa(bgn_pfn); - - merge = PFN_DW(start_off) < bgn_pfn; - end_off = start_off + size; - - pbd->last_offset = end_off; - pbd->last_hit_pfn = PFN_UP(end_off); - - reserve_bootmem(PFN_DW(start_off) + merge, PFN_UP(end_off)); - - region = pa2va(start_off); - - memset(region, 0, size); - - return region; - } - - if (fallback) - { - bgn_pfn = ALIGN(fallback - 1, step); - fallback = 0; - goto find_block; - } - - return 0; -} - pde_t __initdata init_pgd[PDECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE))); pte_t __initdata init_pgt[PTECNT_PER_PAGE * BOOT_INIT_PAGETBL_CNT] __attribute__((__aligned__(PAGE_SIZE))); -- 2.44.0