Boot framework rework (#45)
[lunaix-os.git] / lunaix-os / kernel / mm / pmm.c
1 #include <lunaix/status.h>
2 #include <lunaix/mm/pagetable.h>
3 #include <lunaix/spike.h>
4
5 #include "pmm_internal.h"
6
7 static inline bool
8 __check_typemask(struct ppage* page, ppage_type_t typemask)
9 {
10     return !page->type || (page->type & typemask);
11 }
12
13 static struct pmem memory;
14 export_symbol(debug, pmm, memory);
15
16 void
17 pmm_init(struct boot_handoff* bctx)
18 {
19     ptr_t pplist_pa;
20
21     llist_init_head(&memory.reserved);
22
23     pplist_pa = pmm_arch_init_remap(&memory, bctx);
24     
25     if (!pplist_pa) {
26         spin();
27     }
28
29     pmm_arch_init_pool(&memory);
30
31     pmm_allocator_init(&memory);
32
33     for (size_t i = 0; i < POOL_COUNT; i++)
34     {
35         pmm_allocator_init_pool(&memory.pool[i]);
36     }
37
38     pfn_t pplist_size = memory.list_len * sizeof(struct ppage);
39     pmm_onhold_range(pfn(pplist_pa), leaf_count(pplist_size));
40 }
41
42 static inline bool must_inline optimize("-fipa-cp-clone")
43 __pmm_mark_range(pfn_t start, size_t npages, const bool hold)
44 {
45     if (start >= memory.list_len) {
46         return true;
47     }
48
49     struct ppage *_start, *_end, 
50                  *_mark_start, *_mark_end;
51
52     _start = ppage(start);
53     _end = ppage(start + npages - 1);
54     
55     struct pmem_pool* pool;
56     for (int i = 0; npages && i < POOL_COUNT; i++) {
57         pool = &memory.pool[i];
58
59         _mark_start = MAX(pool->pool_start, _start);
60         _mark_end   = MIN(pool->pool_end, _end);
61         if (pool->pool_end < _mark_start || _mark_end < pool->pool_start) {
62             continue;
63         }
64
65         bool _r;
66         if (hold) {
67             _r = pmm_allocator_trymark_onhold(pool, _mark_start, _mark_end);
68         } else {
69             _r = pmm_allocator_trymark_unhold(pool, _mark_start, _mark_end);
70         }
71
72         if (_r)
73         {
74             npages -= (ppfn(_mark_end) - ppfn(_mark_start)) + 1;
75         }
76     }
77
78     return !npages;
79 }
80
81 bool
82 pmm_onhold_range(pfn_t start, size_t npages)
83 {
84     return __pmm_mark_range(start, npages, true);
85 }
86
87 bool
88 pmm_unhold_range(pfn_t start, size_t npages)
89 {
90     return __pmm_mark_range(start, npages, false);
91 }
92
93 struct pmem_pool*
94 pmm_pool_get(int pool_index)
95 {
96     assert(pool_index < POOL_COUNT);
97
98     return &memory.pool[pool_index];
99 }
100
101 struct pmem_pool*
102 pmm_declare_pool(int pool, pfn_t start, pfn_t size)
103 {
104     struct pmem_pool* _pool = &memory.pool[pool];
105
106     _pool->type = POOL_UNIFIED;
107     _pool->pool_end = ppage(start + size - 1);
108     _pool->pool_start = ppage(start);
109
110     return _pool;
111 }