X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/69777bdcab284335651a8002e2896f3862fa423d..a136ca38d83fae60994a54f5da88120e545895e1:/lunaix-os/includes/lunaix/mm/pmm.h diff --git a/lunaix-os/includes/lunaix/mm/pmm.h b/lunaix-os/includes/lunaix/mm/pmm.h index fa22f7b..bd55eb1 100644 --- a/lunaix-os/includes/lunaix/mm/pmm.h +++ b/lunaix-os/includes/lunaix/mm/pmm.h @@ -2,87 +2,108 @@ #define __LUNAIX_PMM_H // Physical memory manager +#include +#include #include -#include -#include +#include -#define PM_PAGE_SIZE 4096 -#define PM_BMP_MAX_SIZE (1024 * 1024) +enum { + POOL_UNIFIED, + POOL_COUNT +}; -/** - * @brief 长久页:不会被缓存,但允许释放 - * - */ -#define PP_FGPERSIST 0b00001 +typedef unsigned int ppage_type_t; -/** - * @brief 锁定页:不会被缓存,不能被释放 - * - */ -#define PP_FGLOCKED 0b00011 +// Maximum non-huge page order. +#define MAX_PAGE_ORDERS ( LEVEL_SHIFT - 1 ) -typedef u32_t pp_attr_t; +#define RESERVE_MARKER 0xf0f0f0f0 -struct pp_struct +struct pmem_pool { - u32_t ref_counts; - pp_attr_t attr; + int type; + struct ppage* pool_start; + struct ppage* pool_end; + +#if defined(CONFIG_PMALLOC_METHOD_NCONTIG) + + struct llist_header idle_page; + struct llist_header busy_page; + +#elif defined(CONFIG_PMALLOC_METHOD_BUDDY) + + struct llist_header idle_order[MAX_PAGE_ORDERS]; + +#elif defined(CONFIG_PMALLOC_METHOD_SIMPLE) + + struct llist_header idle_order[MAX_PAGE_ORDERS]; + int count[MAX_PAGE_ORDERS]; + +#endif }; -/** - * @brief 标注物理页为可使用 - * - * @param ppn page number - */ -void -pmm_mark_page_free(ptr_t ppn); +struct pmem +{ + struct pmem_pool pool[POOL_COUNT]; -/** - * @brief 标注物理页为已占用 - * - * @param ppn - */ -void -pmm_mark_page_occupied(ptr_t ppn, pp_attr_t attr); + pfn_t list_len; + struct ppage* pplist; + struct llist_header reserved; +}; -/** - * @brief 标注多个连续的物理页为可用 - * - * @param start_ppn 起始PPN - * @param page_count 数量 - */ -void -pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count); +static inline struct ppage* +ppage(pfn_t pfn) +{ + return (struct ppage*)(PPLIST_STARTVM) + pfn; +} -/** - * @brief 标注多个连续的物理页为已占用 - * - * @param start_ppn 起始PPN - * @param page_count 数量 - */ -void -pmm_mark_chunk_occupied(u32_t start_ppn, - size_t page_count, - pp_attr_t attr); +static inline struct ppage* +leading_page(struct ppage* page) { + return page - page->companion; +} -/** - * @brief 分配一个可用的物理页 - * - * @return void* 可用的页地址,否则为 NULL - */ -ptr_t -pmm_alloc_page(pp_attr_t attr); +static inline struct ppage* +ppage_of(struct pmem_pool* pool, pfn_t pfn) +{ + return pool->pool_start + pfn; +} + +static inline pfn_t +ppfn(struct ppage* page) +{ + return (pfn_t)((ptr_t)page - PPLIST_STARTVM) / sizeof(struct ppage); +} + +static inline pfn_t +ppfn_of(struct pmem_pool* pool, struct ppage* page) +{ + return (pfn_t)((ptr_t)page - (ptr_t)pool->pool_start) / sizeof(struct ppage); +} + +static inline ptr_t +ppage_addr(struct ppage* page) { + return ppfn(page) * PAGE_SIZE; +} + +static inline unsigned int +count_order(size_t page_count) { + unsigned int po = ilog2(page_count); + assert(!(page_count % (1 << po))); + return po; +} + +static inline unsigned int +ppage_order(struct ppage* page) { + return page->order; +} + + +static inline bool +reserved_page(struct ppage* page) +{ + return page->refs == RESERVE_MARKER && page->type == PP_RESERVED; +} -/** - * @brief 分配一个连续的物理内存区域 - * - * @param owner - * @param num_pages 区域大小,单位为页 - * @param attr - * @return ptr_t - */ -ptr_t -pmm_alloc_cpage(size_t num_pages, pp_attr_t attr); /** * @brief 初始化物理内存管理器 @@ -90,48 +111,60 @@ pmm_alloc_cpage(size_t num_pages, pp_attr_t attr); * @param mem_upper_lim 最大可用内存地址 */ void -pmm_init(ptr_t mem_upper_lim); +pmm_init(struct boot_handoff* bctx); -struct pp_struct* -pmm_query(ptr_t pa); +ptr_t +pmm_arch_init_remap(struct pmem* memory, struct boot_handoff* bctx); -/** - * @brief Free physical page with given attributes - * - * @param page - * @return int - */ -int -pmm_free_one(ptr_t page, pp_attr_t attr_mask); +struct pmem_pool* +pmm_pool_get(int pool_index); -/** - * @brief Free a normal physical page - * - * @param page 页地址 - * @return 是否成功 - */ -static inline int -pmm_free_page(ptr_t page) +void +pmm_arch_init_pool(struct pmem* memory); + +bool +pmm_onhold_range(pfn_t start, size_t npages); + +bool +pmm_unhold_range(pfn_t start, size_t npages); + + +struct pmem_pool* +pmm_declare_pool(int pool, pfn_t start, pfn_t size); + +// ---- allocator specific ---- + +void +pmm_free_one(struct ppage* page, int type_mask); + +struct ppage* +pmm_alloc_napot_type(int pool, size_t order, ppage_type_t type); + +// ---- + +static inline struct ppage* +pmm_alloc_normal(size_t order) { - return pmm_free_one(page, 0); + return pmm_alloc_napot_type(POOL_UNIFIED, order, 0); } -/** - * @brief Free physical page regardless of it's attribute - * - * @param page - * @return int - */ -static inline int -pmm_free_any(ptr_t page) +static inline struct ppage* +pmm_alloc_locked(size_t order) +{ + return pmm_alloc_napot_type(POOL_UNIFIED, order, PP_FGLOCKED); +} + +static inline void +change_page_type(struct ppage* page, ppage_type_t type) { - return pmm_free_one(page, -1); + page->type = type; } -int -pmm_ref_page(ptr_t page); +static inline struct pmem_pool* +pmm_pool_lookup(struct ppage* page) +{ + return pmm_pool_get(page->pool); +} -void -pmm_set_attr(ptr_t page, pp_attr_t attr); #endif /* __LUNAIX_PMM_H */