From aa54761c77a565d2cdf714422f31fa882fa519da Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 28 Dec 2025 17:02:25 -0500 Subject: [PATCH] process: track ownership of pages in a more flexible way --- src/kernel/process.c | 33 ++++++++++++++++++++++++--------- src/kernel/process.h | 6 +++++- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/kernel/process.c b/src/kernel/process.c index 25eb148..6eeee44 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -58,6 +58,7 @@ void create_process(struct process *process_out) { process_out->p3_virtual_base[i] = 0; process_out->p2_virtual_bases[i] = 0; process_out->p1_virtual_bases[i] = 0; + process_out->owned_pages_bitmaps[i] = 0; } process_out->n_threads = 0; @@ -67,7 +68,7 @@ void create_process(struct process *process_out) { void map_page_for_process( struct process *process, uint64_t physical_base, - void *virtual_base, int writable, int executable) { + void *virtual_base, int writable, int executable, int owned) { assert(physical_base % 4096 == 0) @@ -87,9 +88,11 @@ void map_page_for_process( process->p3_virtual_base[p3i] = p2_pma | 0x7; process->p2_virtual_bases[p3i] = p2_vma; process->p1_virtual_bases[p3i] = heap_alloc(4096); + process->owned_pages_bitmaps[p3i] = heap_alloc(4096); for (int i = 0; i < 512; ++i) { p2_vma[i] = 0; process->p1_virtual_bases[p3i][i] = 0; + process->owned_pages_bitmaps[p3i][i] = 0; } } @@ -99,8 +102,11 @@ void map_page_for_process( map_in_kernel_page_table(p1_pma, p1_vma, 1, 0); process->p2_virtual_bases[p3i][p2i] = p1_pma | 0x7; process->p1_virtual_bases[p3i][p2i] = p1_vma; + process->owned_pages_bitmaps[p3i][p2i] = heap_alloc(64); for (int i = 0; i < 512; ++i) p1_vma[i] = 0; + for (int i = 0; i < 64; ++i) + process->owned_pages_bitmaps[p3i][p2i][i] = 0; } assert(process->p1_virtual_bases[p3i][p2i][p1i] == 0) @@ -109,6 +115,9 @@ void map_page_for_process( physical_base | 0x5 | (writable ? 0x2 : 0x0) | (executable ? 0 : 0x8000000000000000); + if (owned) + process->owned_pages_bitmaps[p3i][p2i][p1i / 8] |= 1 << (p1i % 8); + } void unmap_page_for_process( @@ -128,6 +137,12 @@ void unmap_page_for_process( process->p1_virtual_bases[p3i][p2i] && process->p1_virtual_bases[p3i][p2i][p1i]) + if (process->owned_pages_bitmaps[p3i][p2i][p1i / 8] & (1 << (p1i % 8))) { + process->owned_pages_bitmaps[p3i][p2i][p1i / 8] &= ~(1 << (p1i % 8)); + uint64_t pma = process->p1_virtual_bases[p3i][p2i][p1i] & 0x7ffffffffffff000; + mark_physical_memory_free(pma, 4096); + } + process->p1_virtual_bases[p3i][p2i][p1i] = 0; } @@ -286,7 +301,7 @@ int load_elf( uint64_t pma = take_free_physical_page(); map_page_for_process( - process, pma, virtual_start + i, writable, executable); + process, pma, virtual_start + i, writable, executable, 1); void *kvma = find_free_kernel_region(4096); map_in_kernel_page_table(pma, kvma, 1, 0); @@ -377,15 +392,15 @@ void destroy_process(struct process *process) { for (int p1i = 0; p1i < 512; ++p1i) { uint64_t pma = process->p1_virtual_bases[p3i][p2i][p1i] & 0x7ffffffffffff000; - if (pma >= fb_physical_base && - pma < fb_physical_base + fb_pitch * fb_height) - continue; - mark_physical_memory_free(pma, 4096); + if (process->owned_pages_bitmaps[p3i][p2i][p1i / 8] & (1 << (p1i % 8))) + mark_physical_memory_free(pma, 4096); } unmap_and_free_kernel_page(process->p1_virtual_bases[p3i][p2i]); + heap_dealloc(process->owned_pages_bitmaps[p3i][p2i], 64); } unmap_and_free_kernel_page(process->p2_virtual_bases[p3i]); heap_dealloc(process->p1_virtual_bases[p3i], 4096); + heap_dealloc(process->owned_pages_bitmaps[p3i], 4096); } unmap_and_free_kernel_page(process->p3_virtual_base); unmap_and_free_kernel_page(process->p4_virtual_base); @@ -426,7 +441,7 @@ void create_thread(struct process *process, struct thread *thread_out) { uint64_t pma = take_free_physical_page(); map_page_for_process( - process, pma, stack_bottom_vma + i * 4096, 1, 0); + process, pma, stack_bottom_vma + i * 4096, 1, 0, 1); void *kvma = find_free_kernel_region(4096); map_in_kernel_page_table(pma, kvma, 1, 0); @@ -478,7 +493,7 @@ void syscall_map_framebuffer(struct framebuffer_info *info_out) { map_page_for_process( running_thread->process, fb_physical_base + i * 4096, - base + i * 4096, 1, 0); + base + i * 4096, 1, 0, 0); info_out->fb_base = base; info_out->fb_pitch = fb_pitch; @@ -605,7 +620,7 @@ void *syscall_map_pages(uint64_t count) { map_page_for_process( running_thread->process, pma, vma + i * 4096, - 1, 0); + 1, 0, 1); } return vma; diff --git a/src/kernel/process.h b/src/kernel/process.h index e2a2a40..24659c0 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -46,6 +46,10 @@ struct process { uint64_t *p2_virtual_bases[512]; uint64_t **p1_virtual_bases[512]; + //also just bottom p3. bit set indicates we should free + //the physical page when we clean up this process. + uint8_t **owned_pages_bitmaps[512]; + }; //returns 0 if that handle is not used. @@ -71,7 +75,7 @@ void create_thread(struct process *process, struct thread *thread_out); //virtual base must be in bottom p3 and not zero. void map_page_for_process( struct process *process, uint64_t physical_base, - void *virtual_base, int writable, int executable); + void *virtual_base, int writable, int executable, int owned); //virtual base must be page-aligned, in bottom p3, and not zero. void unmap_page_for_process(