1 #include <lunaix/mm/pmm.h>
2 #include <lunaix/status.h>
3 #include <lunaix/mm/pagetable.h>
4 #include <lunaix/spike.h>
6 // This is a very large array...
7 static struct pp_struct pm_table[PM_BMP_MAX_SIZE];
8 export_symbol(debug, pmm, pm_table);
11 export_symbol(debug, pmm, max_pg);
14 pmm_mark_page_free(ptr_t ppn)
16 if ((pm_table[ppn].attr & PP_FGLOCKED)) {
19 pm_table[ppn].ref_counts = 0;
23 pmm_mark_page_occupied(ptr_t ppn, pp_attr_t attr)
26 (struct pp_struct){ .ref_counts = 1, .attr = attr };
30 pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count)
32 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
33 if ((pm_table[i].attr & PP_FGLOCKED)) {
36 pm_table[i].ref_counts = 0;
41 pmm_mark_chunk_occupied(u32_t start_ppn,
45 for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) {
47 (struct pp_struct){ .ref_counts = 1, .attr = attr };
51 // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。
52 #define LOOKUP_START 1
54 volatile size_t pg_lookup_ptr;
57 pmm_init(ptr_t mem_upper_lim)
59 max_pg = pfn(mem_upper_lim);
61 pg_lookup_ptr = LOOKUP_START;
63 // mark all as occupied
64 for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) {
66 (struct pp_struct){ .attr = 0, .ref_counts = 1 };
71 pmm_alloc_cpage(size_t num_pages, pp_attr_t attr)
76 while (p2 < max_pg && p2 - p1 < num_pages) {
77 (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = ++p2);
80 if (p2 == max_pg && p2 - p1 < num_pages) {
84 pmm_mark_chunk_occupied(p1, num_pages, attr);
90 pmm_alloc_page(pp_attr_t attr)
92 // Next fit approach. Maximize the throughput!
93 ptr_t good_page_found = (ptr_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){ .attr = attr,
103 good_page_found = pg_lookup_ptr << 12;
108 // We've searched the interval [old_pg_ptr, max_pg) but failed
109 // may be chances in [1, old_pg_ptr) ?
111 if (pg_lookup_ptr >= upper_lim && old_pg_ptr != LOOKUP_START) {
112 upper_lim = old_pg_ptr;
113 pg_lookup_ptr = LOOKUP_START;
114 old_pg_ptr = LOOKUP_START;
118 return good_page_found;
122 pmm_free_one(ptr_t page, pp_attr_t attr_mask)
124 pfn_t ppfn = pfn(page);
125 struct pp_struct* pm = &pm_table[ppfn];
127 assert(ppfn < max_pg && pm->ref_counts);
128 if (pm->attr && !(pm->attr & attr_mask)) {
137 pmm_ref_page(ptr_t page)
139 u32_t ppn = pfn(page);
141 if (ppn >= PM_BMP_MAX_SIZE) {
145 struct pp_struct* pm = &pm_table[ppn];
146 assert(ppn < max_pg && pm->ref_counts);
153 pmm_set_attr(ptr_t page, pp_attr_t attr)
155 struct pp_struct* pp = &pm_table[pfn(page)];
157 if (pp->ref_counts) {
165 u32_t ppn = pa >> 12;
167 if (ppn >= PM_BMP_MAX_SIZE) {
171 return &pm_table[ppn];