X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/c1811aecaae88bc006ce20bd301a6519dd89abda..b60166b327a9108b07e3069fa6568a451529ffd9:/lunaix-os/kernel/mm/pmm.c diff --git a/lunaix-os/kernel/mm/pmm.c b/lunaix-os/kernel/mm/pmm.c index 304d19d..b1cea96 100644 --- a/lunaix-os/kernel/mm/pmm.c +++ b/lunaix-os/kernel/mm/pmm.c @@ -1,83 +1,53 @@ #include #include +#include -#define MARK_PG_AUX_VAR(ppn) \ - uint32_t group = ppn / 8; \ - uint32_t msk = (0x80U >> (ppn % 8)); \ +// This is a very large array... +static struct pp_struct pm_table[PM_BMP_MAX_SIZE]; +export_symbol(debug, pmm, pm_table); -#define MARK_CHUNK_AUX_VAR(start_ppn, page_count) \ - uint32_t group = start_ppn / 8; \ - uint32_t offset = start_ppn % 8; \ - uint32_t group_count = (page_count + offset) / 8; \ - uint32_t remainder = (page_count + offset) % 8; \ - uint32_t leading_shifts = \ - (page_count + offset) < 8 ? page_count : 8 - offset; +static ptr_t max_pg; +export_symbol(debug, pmm, max_pg); -uint8_t pm_bitmap[PM_BMP_MAX_SIZE]; - -uintptr_t max_pg; - -// ... |xxxx xxxx | -// ... |-->| void -pmm_mark_page_free(uintptr_t ppn) +pmm_mark_page_free(ptr_t ppn) { - MARK_PG_AUX_VAR(ppn) - pm_bitmap[group] = pm_bitmap[group] & ~msk; + pm_table[ppn].ref_counts = 0; } void -pmm_mark_page_occupied(uintptr_t ppn) +pmm_mark_page_occupied(ptr_t ppn, pp_attr_t attr) { - MARK_PG_AUX_VAR(ppn) - pm_bitmap[group] = pm_bitmap[group] | msk; + pm_table[ppn] = + (struct pp_struct){ .ref_counts = 1, .attr = attr }; } void -pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count) +pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count) { - MARK_CHUNK_AUX_VAR(start_ppn, page_count) - - // nasty bit level hacks but it reduce # of iterations. - - pm_bitmap[group] &= ~(((1U << leading_shifts) - 1) << (8 - offset - leading_shifts)); - - group++; - - // prevent unsigned overflow - for (uint32_t i = 0; group_count !=0 && i < group_count - 1; i++, group++) { - pm_bitmap[group] = 0; + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { + pm_table[i].ref_counts = 0; } - - pm_bitmap[group] &= - ~(((1U << (page_count > 8 ? remainder : 0)) - 1) << (8 - remainder)); } void -pmm_mark_chunk_occupied(uint32_t start_ppn, size_t page_count) +pmm_mark_chunk_occupied(u32_t start_ppn, + size_t page_count, + pp_attr_t attr) { - MARK_CHUNK_AUX_VAR(start_ppn, page_count) - - pm_bitmap[group] |= (((1U << leading_shifts) - 1) << (8 - offset - leading_shifts)); - - group++; - - // prevent unsigned overflow - for (uint32_t i = 0; group_count !=0 && i < group_count - 1; i++, group++) { - pm_bitmap[group] = 0xFFU; + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { + pm_table[i] = + (struct pp_struct){ .ref_counts = 1, .attr = attr }; } - - pm_bitmap[group] |= - (((1U << (page_count > 8 ? remainder : 0)) - 1) << (8 - remainder)); } // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。 #define LOOKUP_START 1 -size_t pg_lookup_ptr; +volatile size_t pg_lookup_ptr; void -pmm_init(uintptr_t mem_upper_lim) +pmm_init(ptr_t mem_upper_lim) { max_pg = (PG_ALIGN(mem_upper_lim) >> 12); @@ -85,32 +55,48 @@ pmm_init(uintptr_t mem_upper_lim) // mark all as occupied for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) { - pm_bitmap[i] = 0xFFU; + pm_table[i] = + (struct pp_struct){ .attr = 0, .ref_counts = 1 }; } } -void* -pmm_alloc_page() +ptr_t +pmm_alloc_cpage(size_t num_pages, pp_attr_t attr) +{ + size_t p1 = 0; + size_t p2 = 0; + + while (p2 < max_pg && p2 - p1 < num_pages) { + (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = ++p2); + } + + if (p2 == max_pg && p2 - p1 < num_pages) { + return NULLPTR; + } + + pmm_mark_chunk_occupied(p1, num_pages, attr); + + return p1 << 12; +} + +ptr_t +pmm_alloc_page(pp_attr_t attr) { // Next fit approach. Maximize the throughput! - uintptr_t good_page_found = (uintptr_t)NULL; + ptr_t good_page_found = (ptr_t)NULL; size_t old_pg_ptr = pg_lookup_ptr; size_t upper_lim = max_pg; - uint8_t chunk = 0; + struct pp_struct* pm; while (!good_page_found && pg_lookup_ptr < upper_lim) { - chunk = pm_bitmap[pg_lookup_ptr >> 3]; - - // skip the fully occupied chunk, reduce # of iterations - if (chunk != 0xFFU) { - for (size_t i = pg_lookup_ptr % 8; i < 8; i++, pg_lookup_ptr++) { - if (!(chunk & (0x80U >> i))) { - pmm_mark_page_occupied(pg_lookup_ptr); - good_page_found = pg_lookup_ptr << 12; - break; - } - } + pm = &pm_table[pg_lookup_ptr]; + + if (!pm->ref_counts) { + *pm = (struct pp_struct){ .attr = attr, + .ref_counts = 1 }; + good_page_found = pg_lookup_ptr << 12; + break; } else { - pg_lookup_ptr += 8; + pg_lookup_ptr++; // We've searched the interval [old_pg_ptr, max_pg) but failed // may be chances in [1, old_pg_ptr) ? @@ -122,18 +108,56 @@ pmm_alloc_page() } } } - return (void*)good_page_found; + return good_page_found; +} + +int +pmm_free_page(ptr_t page) +{ + struct pp_struct* pm = &pm_table[page >> 12]; + + // Is this a MMIO mapping or double free? + if ((page >> 12) >= max_pg || !(pm->ref_counts)) { + return 0; + } + + // 如果是锁定页,则不作处理 + if ((pm->attr & PP_FGLOCKED)) { + return 0; + } + + // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; + // 2) 内核可释放所有页。 + pm->ref_counts--; + return 1; } int -pmm_free_page(void* page) +pmm_ref_page(ptr_t page) { - // TODO: Add kernel reserved memory page check - uint32_t pg = (uintptr_t)page >> 12; - if (pg && pg < max_pg) - { - pmm_mark_page_free(pg); - return 1; + u32_t ppn = page >> 12; + + if (ppn >= PM_BMP_MAX_SIZE) { + return 0; + } + + struct pp_struct* pm = &pm_table[ppn]; + if (ppn >= max_pg || !pm->ref_counts) { + return 0; + } + + pm->ref_counts++; + return 1; +} + +struct pp_struct* +pmm_query(ptr_t pa) +{ + u32_t ppn = pa >> 12; + + if (ppn >= PM_BMP_MAX_SIZE) { + return NULL; } - return 0; + + return &pm_table[ppn]; } \ No newline at end of file