X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/48b4a227035048fdebcd32532deb7a857c6199ac..b60166b327a9108b07e3069fa6568a451529ffd9:/lunaix-os/kernel/mm/pmm.c diff --git a/lunaix-os/kernel/mm/pmm.c b/lunaix-os/kernel/mm/pmm.c index efb9dc8..b1cea96 100644 --- a/lunaix-os/kernel/mm/pmm.c +++ b/lunaix-os/kernel/mm/pmm.c @@ -4,54 +4,50 @@ // This is a very large array... static struct pp_struct pm_table[PM_BMP_MAX_SIZE]; +export_symbol(debug, pmm, pm_table); -static uintptr_t max_pg; +static ptr_t max_pg; +export_symbol(debug, pmm, max_pg); void -pmm_mark_page_free(uintptr_t ppn) +pmm_mark_page_free(ptr_t ppn) { pm_table[ppn].ref_counts = 0; } void -pmm_mark_page_occupied(pid_t owner, uintptr_t ppn, pp_attr_t attr) +pmm_mark_page_occupied(ptr_t ppn, pp_attr_t attr) { - pm_table[ppn] = (struct pp_struct) { - .owner = owner, - .ref_counts = 1, - .attr = attr - }; + pm_table[ppn] = + (struct pp_struct){ .ref_counts = 1, .attr = attr }; } void -pmm_mark_chunk_free(uintptr_t start_ppn, size_t page_count) +pmm_mark_chunk_free(ptr_t start_ppn, size_t page_count) { - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) - { + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { pm_table[i].ref_counts = 0; } } void -pmm_mark_chunk_occupied(pid_t owner, uint32_t start_ppn, size_t page_count, pp_attr_t attr) +pmm_mark_chunk_occupied(u32_t start_ppn, + size_t page_count, + pp_attr_t attr) { - for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) - { - pm_table[i] = (struct pp_struct) { - .owner = owner, - .ref_counts = 1, - .attr = attr - }; + for (size_t i = start_ppn; i < start_ppn + page_count && i < max_pg; i++) { + pm_table[i] = + (struct pp_struct){ .ref_counts = 1, .attr = attr }; } } // 我们跳过位于0x0的页。我们不希望空指针是指向一个有效的内存空间。 #define LOOKUP_START 1 -size_t pg_lookup_ptr; +volatile size_t pg_lookup_ptr; void -pmm_init(uintptr_t mem_upper_lim) +pmm_init(ptr_t mem_upper_lim) { max_pg = (PG_ALIGN(mem_upper_lim) >> 12); @@ -59,52 +55,46 @@ pmm_init(uintptr_t mem_upper_lim) // mark all as occupied for (size_t i = 0; i < PM_BMP_MAX_SIZE; i++) { - pm_table[i] = (struct pp_struct) { - .owner = 0, - .attr = 0, - .ref_counts = 1 - }; + pm_table[i] = + (struct pp_struct){ .attr = 0, .ref_counts = 1 }; } } -void* -pmm_alloc_cpage(pid_t owner, size_t num_pages, pp_attr_t attr) { +ptr_t +pmm_alloc_cpage(size_t num_pages, pp_attr_t attr) +{ size_t p1 = 0; size_t p2 = 0; - while (p2 < max_pg && p2 - p1 < num_pages) - { - (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = p2); + while (p2 < max_pg && p2 - p1 < num_pages) { + (!(&pm_table[p2])->ref_counts) ? (p2++) : (p1 = ++p2); } - if (p2 < max_pg) { - return NULL; + if (p2 == max_pg && p2 - p1 < num_pages) { + return NULLPTR; } - pmm_mark_chunk_occupied(owner, p1, num_pages, attr); + pmm_mark_chunk_occupied(p1, num_pages, attr); return p1 << 12; } -void* -pmm_alloc_page(pid_t owner, pp_attr_t attr) +ptr_t +pmm_alloc_page(pp_attr_t attr) { // Next fit approach. Maximize the throughput! - uintptr_t good_page_found = (uintptr_t)NULL; + ptr_t good_page_found = (ptr_t)NULL; size_t old_pg_ptr = pg_lookup_ptr; size_t upper_lim = max_pg; struct pp_struct* pm; while (!good_page_found && pg_lookup_ptr < upper_lim) { pm = &pm_table[pg_lookup_ptr]; - // skip the fully occupied chunk, reduce # of iterations if (!pm->ref_counts) { - *pm = (struct pp_struct) { - .attr = attr, - .owner = owner, - .ref_counts = 1 - }; + *pm = (struct pp_struct){ .attr = attr, + .ref_counts = 1 }; good_page_found = pg_lookup_ptr << 12; + break; } else { pg_lookup_ptr++; @@ -118,41 +108,41 @@ pmm_alloc_page(pid_t owner, pp_attr_t attr) } } } - if (!good_page_found) { - __current->k_status = LXOUTOFMEM; - } - return (void*)good_page_found; + return good_page_found; } int -pmm_free_page(pid_t owner, void* page) +pmm_free_page(ptr_t page) { - struct pp_struct* pm = &pm_table[(intptr_t)page >> 12]; - - // Oops, double free! - if (!(pm->ref_counts)) { + struct pp_struct* pm = &pm_table[page >> 12]; + + // Is this a MMIO mapping or double free? + if ((page >> 12) >= max_pg || !(pm->ref_counts)) { return 0; } - // 检查权限,保证:1) 用户只能释放用户页; 2) 内核可释放所有页。 - if ((pm->owner & owner) == pm->owner) { - pm->ref_counts--; - return 1; + // 如果是锁定页,则不作处理 + if ((pm->attr & PP_FGLOCKED)) { + return 0; } - return 0; + + // TODO: 检查权限,保证:1) 只有正在使用该页(包括被分享者)的进程可以释放; + // 2) 内核可释放所有页。 + pm->ref_counts--; + return 1; } -int pmm_ref_page(pid_t owner, void* page) { - (void*) owner; // TODO: do smth with owner - - uint32_t ppn = (uintptr_t)page >> 12; - +int +pmm_ref_page(ptr_t page) +{ + u32_t ppn = page >> 12; + if (ppn >= PM_BMP_MAX_SIZE) { return 0; } struct pp_struct* pm = &pm_table[ppn]; - if (!pm->ref_counts) { + if (ppn >= max_pg || !pm->ref_counts) { return 0; } @@ -160,9 +150,11 @@ int pmm_ref_page(pid_t owner, void* page) { return 1; } -struct pp_struct* pmm_query(void* pa) { - uint32_t ppn = (uintptr_t)pa >> 12; - +struct pp_struct* +pmm_query(ptr_t pa) +{ + u32_t ppn = pa >> 12; + if (ppn >= PM_BMP_MAX_SIZE) { return NULL; }