1 #include <lunaix/mm/page.h>
2 #include <lunaix/mm/pmm.h>
3 #include <lunaix/status.h>
5 // This is a very large array...
6 static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
8 static uintptr_t max_pg;
11 pmm_mark_page_free(uintptr_t ppn)
13 pm_table[ppn].ref_counts = 0;
17 pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr)
19 pm_table[ppn] = (struct pp_struct) {
27 pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count)
29 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
31 pm_table[i].ref_counts = 0;
36 pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr)
38 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++)
40 pm_table[i] = (struct pp_struct) {
48 // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
49 #define LOOKUP_START 1
54 pmm_init(uintptr_t mem_upper_lim)
56 max_pg = (PG_ALIGN(mem_upper_lim) >> 12);
58 pg_lookup_ptr = LOOKUP_START;
60 // mark all as occupied
61 for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
62 pm_table[i] = (struct pp_struct) {
71 pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) {
75 while (p2 < max_pg && p2 - p1 < num_pages)
77 (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2);
84 pmm_mark_chunk_occupied(owner, p1, num_pages, attr);
90 pmm_alloc_page(pid_t owner, pp_attr_t attr)
92 // Next fit approach. Maximize the throughput!
93 uintptr_t good_page_found = (uintptr_t)NULL;
94 size_t old_pg_ptr = pg_lookup_ptr;
95 size_t upper_lim = max_pg;
97 while (!good_page_found && pg_lookup_ptr < upper_lim) {
98 pm = &pm_table[pg_lookup_ptr];
100 if (!pm->ref_counts) {
101 *pm = (struct pp_struct) {
106 good_page_found = pg_lookup_ptr << 12;
111 // We've searched the interval [old_pg_ptr, max_pg) but failed
112 // may be chances in [1, old_pg_ptr) ?
114 if (pg_lookup_ptr >= upper_lim && old_pg_ptr != LOOKUP_START) {
115 upper_lim = old_pg_ptr;
116 pg_lookup_ptr = LOOKUP_START;
117 old_pg_ptr = LOOKUP_START;
121 if (!good_page_found) {
122 __current->k_status = LXOUTOFMEM;
124 return (void*)good_page_found;
128 pmm_free_page(pid_t owner, void* page)
130 struct pp_struct* pm = &pm_table[(intptr_t)page >> 12];
132 // Is this a MMIO mapping or double free?
133 if (((intptr_t)page >> 12) >= max_pg || !(pm->ref_counts)) {
137 // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; 2) 内核可释放所有页。
142 int pmm_ref_page(pid_t owner, void* page) {
143 (void*) owner; // TODO: do smth with owner
145 uint32_t ppn = (uintptr_t)page >> 12;
147 if (ppn >= PM_BMP_MAX_SIZE) {
151 struct pp_struct* pm = &pm_table[ppn];
152 if (ppn >= max_pg || !pm->ref_counts) {
160 struct pp_struct* pmm_query(void* pa) {
161 uint32_t ppn = (uintptr_t)pa >> 12;
163 if (ppn >= PM_BMP_MAX_SIZE) {
167 return &pm_table[ppn];