aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/mm/page.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/include/mm/page.h')
-rw-r--r--kernel/include/mm/page.h124
1 files changed, 124 insertions, 0 deletions
diff --git a/kernel/include/mm/page.h b/kernel/include/mm/page.h
new file mode 100644
index 0000000..5230a85
--- /dev/null
+++ b/kernel/include/mm/page.h
@@ -0,0 +1,124 @@
+#pragma once
+
+#ifdef __KERNEL__
+#include "types.h"
+#else
+#include "sys/types.h"
+#endif
+
+/* This header file contains the functions for allocating
+ * and freeing page-aligned chunks of data which are a
+ * multiple of a page in size. These are the lowest level
+ * memory allocation functions. In general code should
+ * use the slab allocator functions in mm/slab.h unless
+ * they require page-aligned buffers. */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE ((uintptr_t)(1UL << PAGE_SHIFT))
+#define PAGE_MASK (0xffffffffffffffff << PAGE_SHIFT)
+
+#define PAGE_ALIGN_DOWN(x) ((void *)(((uintptr_t)(x)&PAGE_MASK)))
+#define PAGE_ALIGN_UP(x) \
+ ((void *)((((uintptr_t)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)))
+
+#define PAGE_OFFSET(x) (((uintptr_t)(x)) & ~PAGE_MASK)
+#define PAGE_ALIGNED(x) (!PAGE_OFFSET(x))
+
+#define PN_TO_ADDR(x) ((void *)(((uintptr_t)(x)) << PAGE_SHIFT))
+#define ADDR_TO_PN(x) (((uintptr_t)(x)) >> PAGE_SHIFT)
+
+#define PAGE_SAME(x, y) (PAGE_ALIGN_DOWN(x) == PAGE_ALIGN_DOWN(y))
+
+#define PAGE_NSIZES 8
+
+#define USE_2MB_PAGES 1
+#define USE_1GB_PAGES 1
+
+#define PAGE_SHIFT_2MB 21
+#define PAGE_SIZE_2MB ((uintptr_t)(1UL << PAGE_SHIFT_2MB))
+#define PAGE_MASK_2MB (0xffffffffffffffff << PAGE_SHIFT_2MB)
+#define PAGE_ALIGN_DOWN_2MB(x) (((uintptr_t)(x)) & PAGE_MASK_2MB)
+#define PAGE_ALIGN_UP_2MB(x) (PAGE_ALIGN_DOWN_2MB((x)-1) + PAGE_SIZE_2MB)
+#define PAGE_OFFSET_2MB(x) (((uintptr_t)(x)) & ~PAGE_MASK_2MB)
+#define PAGE_ALIGNED_2MB(x) ((x) == PAGE_ALIGN_DOWN_2MB(x))
+#define PAGE_SAME_2MB(x, y) (PAGE_ALIGN_DOWN_2MB(x) == PAGE_ALIGN_DOWN_2MB(y))
+
+#define PAGE_SHIFT_1GB 30
+#define PAGE_MASK_1GB (0xffffffffffffffff << PAGE_SHIFT_1GB)
+#define PAGE_SIZE_1GB ((uintptr_t)(1UL << PAGE_SHIFT_1GB))
+#define PAGE_ALIGN_DOWN_1GB(x) (((uintptr_t)(x)) & PAGE_MASK_1GB)
+#define PAGE_ALIGN_UP_1GB(x) (PAGE_ALIGN_DOWN_1GB((x)-1) + PAGE_SIZE_1GB)
+#define PAGE_OFFSET_1GB(x) (((uintptr_t)(x)) & ~PAGE_MASK_1GB)
+#define PAGE_ALIGNED_1GB(x) ((x) == PAGE_ALIGN_DOWN_1GB(x))
+#define PAGE_SAME_1GB(x, y) (PAGE_ALIGN_DOWN_1GB(x) == PAGE_ALIGN_DOWN_1GB(y))
+
+#define PAGE_SHIFT_512GB 39
+#define PAGE_SIZE_512GB ((uintptr_t)(1UL << PAGE_SHIFT_512GB))
+#define PAGE_MASK_512GB (0xffffffffffffffff << PAGE_SHIFT_512GB)
+#define PAGE_ALIGN_DOWN_512GB(x) (((uintptr_t)(x)) & PAGE_MASK_512GB)
+#define PAGE_ALIGN_UP_512GB(x) (PAGE_ALIGN_DOWN_512GB((x)-1) + PAGE_SIZE_512GB)
+
+#define PAGE_CONTROL_FLAGS(x) \
+ ((x) & (PT_PRESENT | PT_WRITE | PT_USER | PT_WRITE_THROUGH | \
+ PT_CACHE_DISABLED | PT_SIZE | PT_GLOBAL))
+#define PAGE_FLAGS(x) ((x) & (~PAGE_MASK))
+
+typedef enum page_size
+{
+ ps_4kb,
+ ps_2mb,
+ ps_1gb,
+ ps_512gb,
+} page_size_t;
+
+typedef struct page_status
+{
+ page_size_t size;
+ int mapped;
+} page_status_t;
+
+/* Performs all initialization necessary for the
+ * page allocation system. This should be called
+ * only once at boot time before any other functions
+ * in this header are called. */
+void page_init();
+
+void *physmap_start();
+
+void *physmap_end();
+
+/* These functions allocate and free one page-aligned,
+ * page-sized block of memory. Values passed to
+ * page_free MUST have been returned by page_alloc
+ * at some previous point. There should be only one
+ * call to page_free for each value returned by
+ * page_alloc. If the system is out of memory page_alloc
+ * will return NULL. */
+void *page_alloc(void);
+
+void *page_alloc_bounded(void *max_paddr);
+
+void page_free(void *addr);
+
+/* These functions allocate and free a page-aligned
+ * block of memory which are npages pages in length.
+ * A call to page_alloc_n will allocate a block, to free
+ * that block a call should be made to page_free_n with
+ * npages set to the same as it was when the block was
+ * allocated */
+void *page_alloc_n(size_t npages);
+
+void *page_alloc_n_bounded(size_t npages, void *max_paddr);
+
+void page_free_n(void *start, size_t npages);
+
+void page_add_range(void *start, void *end);
+
+void page_mark_reserved(void *paddr);
+
+void page_init_finish();
+
+/* Returns the number of free pages remaining in the
+ * system. Note that calls to page_alloc_n(npages) may
+ * fail even if page_free_count() >= npages. */
+size_t page_free_count();