#define __LUNAIX_PMM_H
// Physical memory manager
-#include <stdint.h>
-#include <stddef.h>
-#include <lunaix/process.h>
+#include <lunaix/boot_generic.h>
+#include <lunaix/mm/physical.h>
+#include <lunaix/types.h>
+#include <lunaix/spike.h>
+
+enum {
+ POOL_UNIFIED,
+ POOL_COUNT
+};
-#define PM_PAGE_SIZE 4096
-#define PM_BMP_MAX_SIZE (1024 * 1024)
+typedef unsigned int ppage_type_t;
+// Maximum non-huge page order.
+#define MAX_PAGE_ORDERS ( LEVEL_SHIFT - 1 )
-#define PP_FGPERSIST 0x1
+#define RESERVE_MARKER 0xf0f0f0f0
-typedef uint32_t pp_attr_t;
+struct pmem_pool
+{
+ int type;
+ struct ppage* pool_start;
+ struct ppage* pool_end;
+
+#if defined(CONFIG_PMALLOC_NCONTIG)
-struct pp_struct {
- pid_t owner;
- uint32_t ref_counts;
- pp_attr_t attr;
-};
+ struct llist_header idle_page;
+ struct llist_header busy_page;
+
+#elif defined(CONFIG_PMALLOC_BUDDY)
-/**
- * @brief 标注物理页为可使用
- *
- * @param ppn page number
- */
-void pmm_mark_page_free(uintptr_t ppn);
+ struct llist_header idle_order[MAX_PAGE_ORDERS];
+
+#elif defined(CONFIG_PMALLOC_SIMPLE)
-/**
- * @brief 标注物理页为已占用
- *
- * @param ppn
- */
-void pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr);
+ struct llist_header idle_order[MAX_PAGE_ORDERS];
+ int count[MAX_PAGE_ORDERS];
-/**
- * @brief 标注多个连续的物理页为可用
- *
- * @param start_ppn 起始PPN
- * @param page_count 数量
- */
-void pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count);
+#endif
+};
-/**
- * @brief 标注多个连续的物理页为已占用
- *
- * @param start_ppn 起始PPN
- * @param page_count 数量
- */
-void pmm_mark_chunk_occupied(pid_t owner, uintptr_t start_ppn, size_t page_count, pp_attr_t attr);
+struct pmem
+{
+ struct pmem_pool pool[POOL_COUNT];
-/**
- * @brief 分配一个可用的物理页
- *
- * @return void* 可用的页地址,否则为 NULL
- */
-void* pmm_alloc_page(pid_t owner, pp_attr_t attr);
+ pfn_t list_len;
+ struct ppage* pplist;
+ struct llist_header reserved;
+};
+
+static inline struct ppage*
+ppage(pfn_t pfn)
+{
+ return (struct ppage*)(PPLIST_STARTVM) + pfn;
+}
+
+static inline struct ppage*
+leading_page(struct ppage* page) {
+ return page - page->companion;
+}
+
+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 void*
- */
-void*
-pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr);
/**
* @brief 初始化物理内存管理器
- *
+ *
* @param mem_upper_lim 最大可用内存地址
*/
-void pmm_init(uintptr_t mem_upper_lim);
+void
+pmm_init(struct boot_handoff* bctx);
-struct pp_struct* pmm_query(void* pa);
+ptr_t
+pmm_arch_init_remap(struct pmem* memory, struct boot_handoff* bctx);
-/**
- * @brief 释放一个已分配的物理页,假若页地址不存在,则无操作。
- *
- * @param page 页地址
- * @return 是否成功
- */
-int pmm_free_page(pid_t owner, void* page);
+struct pmem_pool*
+pmm_pool_get(int pool_index);
+
+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_alloc_napot_type(POOL_UNIFIED, order, 0);
+}
+
+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)
+{
+ page->type = type;
+}
+static inline struct pmem_pool*
+pmm_pool_lookup(struct ppage* page)
+{
+ return pmm_pool_get(page->pool);
+}
-int pmm_ref_page(pid_t owner, void* page);
#endif /* __LUNAIX_PMM_H */