fix dependency check logic cause config always disabled
[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 #include <lunaix/owloysius.h>
5 #include <lunaix/syslog.h>
6
7 #include "pmm_internal.h"
8
9 LOG_MODULE("pmm")
10
11 static inline bool
12 __check_typemask(struct ppage* page, ppage_type_t typemask)
13 {
14     return !page->type || (page->type & typemask);
15 }
16
17 static struct pmem memory;
18 export_symbol(debug, pmm, memory);
19
20 void
21 pmm_init(struct boot_handoff* bctx)
22 {
23     ptr_t pplist_pa;
24
25     llist_init_head(&memory.reserved);
26
27     pplist_pa = pmm_arch_init_remap(&memory, bctx);
28     
29     if (!pplist_pa) {
30         spin();
31     }
32
33     pmm_arch_init_pool(&memory);
34
35     pmm_allocator_init(&memory);
36
37     for (size_t i = 0; i < POOL_COUNT; i++)
38     {
39         pmm_allocator_init_pool(&memory.pool[i]);
40     }
41
42     pfn_t pplist_size = memory.list_len * sizeof(struct ppage);
43     pmm_onhold_range(pfn(pplist_pa), leaf_count(pplist_size));
44 }
45
46 static inline bool must_inline optimize("-fipa-cp-clone")
47 __pmm_mark_range(pfn_t start, size_t npages, const bool hold)
48 {
49     if (start >= memory.list_len) {
50         return true;
51     }
52
53     struct ppage *_start, *_end, 
54                  *_mark_start, *_mark_end;
55
56     _start = ppage(start);
57     _end = ppage(start + npages - 1);
58     
59     struct pmem_pool* pool;
60     for (int i = 0; npages && i < POOL_COUNT; i++) {
61         pool = &memory.pool[i];
62
63         _mark_start = MAX(pool->pool_start, _start);
64         _mark_end   = MIN(pool->pool_end, _end);
65         if (pool->pool_end < _mark_start || _mark_end < pool->pool_start) {
66             continue;
67         }
68
69         bool _r;
70         if (hold) {
71             _r = pmm_allocator_trymark_onhold(pool, _mark_start, _mark_end);
72         } else {
73             _r = pmm_allocator_trymark_unhold(pool, _mark_start, _mark_end);
74         }
75
76         if (_r)
77         {
78             npages -= (ppfn(_mark_end) - ppfn(_mark_start)) + 1;
79         }
80     }
81
82     return !npages;
83 }
84
85 bool
86 pmm_onhold_range(pfn_t start, size_t npages)
87 {
88     return __pmm_mark_range(start, npages, true);
89 }
90
91 bool
92 pmm_unhold_range(pfn_t start, size_t npages)
93 {
94     return __pmm_mark_range(start, npages, false);
95 }
96
97 struct pmem_pool*
98 pmm_pool_get(int pool_index)
99 {
100     assert(pool_index < POOL_COUNT);
101
102     return &memory.pool[pool_index];
103 }
104
105 struct pmem_pool*
106 pmm_declare_pool(int pool, pfn_t start, pfn_t size)
107 {
108     struct pmem_pool* _pool = &memory.pool[pool];
109
110     _pool->type = POOL_UNIFIED;
111     _pool->pool_end = ppage(start + size - 1);
112     _pool->pool_start = ppage(start);
113
114     return _pool;
115 }
116
117 static void
118 pmm_log_summary()
119 {
120     pfn_t len;
121     struct pmem_pool* _pool;
122
123     INFO("init: nr_pages=%ld, gran=0x%lx", memory.list_len, 1 << PAGE_SHIFT);
124
125     for (int i = 0; i < POOL_COUNT; i++)
126     {
127         _pool = &memory.pool[i];
128         len   = ppfn(_pool->pool_end) - ppfn(_pool->pool_start) + 1;
129         
130         INFO("pool #%d (%d), %ld-%ld(0x%lx)", 
131                 i , _pool->type, 
132                 ppfn(_pool->pool_start), ppfn(_pool->pool_end), len);
133     }
134 }
135 owloysius_fetch_init(pmm_log_summary, on_sysconf);