X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/df61e9d0fec3d5e75820e27e7a2459d132364585..refs/heads/feat/user_model:/lunaix-os/kernel/mm/pmm.c diff --git a/lunaix-os/kernel/mm/pmm.c b/lunaix-os/kernel/mm/pmm.c index 4503535..f00f9c8 100644 --- a/lunaix-os/kernel/mm/pmm.c +++ b/lunaix-os/kernel/mm/pmm.c @@ -1,168 +1,111 @@ -#include -#include #include +#include +#include -// This is a very large array... -static struct pp_struct pm_table[PM_BMP_MAX_SIZE]; +#include "pmm_internal.h" -static uintptr_t max_pg; - -void -pmm_mark_page_free(uintptr_t ppn) +static inline bool +__check_typemask(struct ppage* page, ppage_type_t typemask) { - pm_table[ppn].ref_counts = 0; + return !page->type || (page->type & typemask); } -void -pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr) -{ - pm_table[ppn] = - (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr }; -} +static struct pmem memory; +export_symbol(debug, pmm, memory); void -pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count) +pmm_init(struct boot_handoff* bctx) { - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { - pm_table[i].ref_counts = 0; - } -} + ptr_t pplist_pa; -void -pmm_mark_chunk_occupied(pid_t owner, - uint32_t start_ppn, - size_t page_count, - pp_attr_t attr) -{ - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { - pm_table[i] = - (struct pp_struct){ .owner = owner, .ref_counts = 1, .attr = attr }; - } -} - -// 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。 -#define LOOKUP_START 1 + llist_init_head(&memory.reserved); -size_t pg_lookup_ptr; + pplist_pa = pmm_arch_init_remap(&memory, bctx); + + if (!pplist_pa) { + spin(); + } -void -pmm_init(uintptr_t mem_upper_lim) -{ - max_pg = (PG_ALIGN(mem_upper_lim) >> 12); + pmm_arch_init_pool(&memory); - pg_lookup_ptr = LOOKUP_START; + pmm_allocator_init(&memory); - // mark all as occupied - for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) { - pm_table[i] = - (struct pp_struct){ .owner = 0, .attr = 0, .ref_counts = 1 }; + for (size_t i = 0; i < POOL_COUNT; i++) + { + pmm_allocator_init_pool(&memory.pool[i]); } + + pfn_t pplist_size = memory.list_len * sizeof(struct ppage); + pmm_onhold_range(pfn(pplist_pa), leaf_count(pplist_size)); } -void* -pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) +static inline bool must_inline optimize("-fipa-cp-clone") +__pmm_mark_range(pfn_t start, size_t npages, const bool hold) { - 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 (start >= memory.list_len) { + return true; } - if (p2 == max_pg && p2 - p1 < num_pages) { - return NULL; - } + struct ppage *_start, *_end, + *_mark_start, *_mark_end; - pmm_mark_chunk_occupied(owner, p1, num_pages, attr); + _start = ppage(start); + _end = ppage(start + npages - 1); + + struct pmem_pool* pool; + for (int i = 0; npages && i < POOL_COUNT; i++) { + pool = &memory.pool[i]; - return p1 << 12; -} + _mark_start = MAX(pool->pool_start, _start); + _mark_end = MIN(pool->pool_end, _end); + if (pool->pool_end < _mark_start || _mark_end < pool->pool_start) { + continue; + } -void* -pmm_alloc_page(pid_t owner, pp_attr_t attr) -{ - // Next fit approach. Maximize the throughput! - uintptr_t good_page_found = (uintptr_t)NULL; - size_t old_pg_ptr = pg_lookup_ptr; - size_t upper_lim = max_pg; - struct pp_struct* pm; - while (!good_page_found && pg_lookup_ptr < upper_lim) { - pm = &pm_table[pg_lookup_ptr]; - - if (!pm->ref_counts) { - *pm = (struct pp_struct){ .attr = attr, - .owner = owner, - .ref_counts = 1 }; - good_page_found = pg_lookup_ptr << 12; - break; + bool _r; + if (hold) { + _r = pmm_allocator_trymark_onhold(pool, _mark_start, _mark_end); } else { - pg_lookup_ptr++; - - // We've searched the interval [old_pg_ptr, max_pg) but failed - // may be chances in [1, old_pg_ptr) ? - // Let's find out! - if (pg_lookup_ptr >= upper_lim && old_pg_ptr != LOOKUP_START) { - upper_lim = old_pg_ptr; - pg_lookup_ptr = LOOKUP_START; - old_pg_ptr = LOOKUP_START; - } + _r = pmm_allocator_trymark_unhold(pool, _mark_start, _mark_end); } - } - if (!good_page_found) { - __current->k_status = LXOUTOFMEM; - } - return (void*)good_page_found; -} - -int -pmm_free_page(pid_t owner, void* page) -{ - struct pp_struct* pm = &pm_table[(intptr_t)page >> 12]; - - // Is this a MMIO mapping or double free? - if (((intptr_t)page >> 12) >= max_pg || !(pm->ref_counts)) { - return 0; - } - // 如果是锁定页,则不作处理 - if ((pm->attr & PP_FGLOCKED)) { - return 0; + if (_r) + { + npages -= (ppfn(_mark_end) - ppfn(_mark_start)) + 1; + } } - // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; - // 2) 内核可释放所有页。 - pm->ref_counts--; - return 1; + return !npages; } -int -pmm_ref_page(pid_t owner, void* page) +bool +pmm_onhold_range(pfn_t start, size_t npages) { - (void*)owner; // TODO: do smth with owner - - uint32_t ppn = (uintptr_t)page >> 12; + return __pmm_mark_range(start, npages, true); +} - if (ppn >= PM_BMP_MAX_SIZE) { - return 0; - } +bool +pmm_unhold_range(pfn_t start, size_t npages) +{ + return __pmm_mark_range(start, npages, false); +} - struct pp_struct* pm = &pm_table[ppn]; - if (ppn >= max_pg || !pm->ref_counts) { - return 0; - } +struct pmem_pool* +pmm_pool_get(int pool_index) +{ + assert(pool_index < POOL_COUNT); - pm->ref_counts++; - return 1; + return &memory.pool[pool_index]; } -struct pp_struct* -pmm_query(void* pa) +struct pmem_pool* +pmm_declare_pool(int pool, pfn_t start, pfn_t size) { - uint32_t ppn = (uintptr_t)pa >> 12; + struct pmem_pool* _pool = &memory.pool[pool]; - if (ppn >= PM_BMP_MAX_SIZE) { - return NULL; - } + _pool->type = POOL_UNIFIED; + _pool->pool_end = ppage(start + size - 1); + _pool->pool_start = ppage(start); - return &pm_table[ppn]; + return _pool; } \ No newline at end of file