Second Extended Filesystem (ext2) and other improvements (#33)
[lunaix-os.git] / lunaix-os / includes / lunaix / mm / pmm.h
index d45af82653481d13ed7247ea1f91b0e2193b86f3..bd55eb1e46435d4140a03318d496696b75a06cbf 100644 (file)
 #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_METHOD_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_METHOD_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_METHOD_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 */