process: track ownership of pages in a more flexible way

This commit is contained in:
Benji Dial 2025-12-28 17:02:25 -05:00
parent f5ccce54a4
commit aa54761c77
2 changed files with 29 additions and 10 deletions

View file

@ -58,6 +58,7 @@ void create_process(struct process *process_out) {
process_out->p3_virtual_base[i] = 0; process_out->p3_virtual_base[i] = 0;
process_out->p2_virtual_bases[i] = 0; process_out->p2_virtual_bases[i] = 0;
process_out->p1_virtual_bases[i] = 0; process_out->p1_virtual_bases[i] = 0;
process_out->owned_pages_bitmaps[i] = 0;
} }
process_out->n_threads = 0; process_out->n_threads = 0;
@ -67,7 +68,7 @@ void create_process(struct process *process_out) {
void map_page_for_process( void map_page_for_process(
struct process *process, uint64_t physical_base, 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) assert(physical_base % 4096 == 0)
@ -87,9 +88,11 @@ void map_page_for_process(
process->p3_virtual_base[p3i] = p2_pma | 0x7; process->p3_virtual_base[p3i] = p2_pma | 0x7;
process->p2_virtual_bases[p3i] = p2_vma; process->p2_virtual_bases[p3i] = p2_vma;
process->p1_virtual_bases[p3i] = heap_alloc(4096); process->p1_virtual_bases[p3i] = heap_alloc(4096);
process->owned_pages_bitmaps[p3i] = heap_alloc(4096);
for (int i = 0; i < 512; ++i) { for (int i = 0; i < 512; ++i) {
p2_vma[i] = 0; p2_vma[i] = 0;
process->p1_virtual_bases[p3i][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); map_in_kernel_page_table(p1_pma, p1_vma, 1, 0);
process->p2_virtual_bases[p3i][p2i] = p1_pma | 0x7; process->p2_virtual_bases[p3i][p2i] = p1_pma | 0x7;
process->p1_virtual_bases[p3i][p2i] = p1_vma; process->p1_virtual_bases[p3i][p2i] = p1_vma;
process->owned_pages_bitmaps[p3i][p2i] = heap_alloc(64);
for (int i = 0; i < 512; ++i) for (int i = 0; i < 512; ++i)
p1_vma[i] = 0; 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) assert(process->p1_virtual_bases[p3i][p2i][p1i] == 0)
@ -109,6 +115,9 @@ void map_page_for_process(
physical_base | 0x5 | (writable ? 0x2 : 0x0) | physical_base | 0x5 | (writable ? 0x2 : 0x0) |
(executable ? 0 : 0x8000000000000000); (executable ? 0 : 0x8000000000000000);
if (owned)
process->owned_pages_bitmaps[p3i][p2i][p1i / 8] |= 1 << (p1i % 8);
} }
void unmap_page_for_process( 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] &&
process->p1_virtual_bases[p3i][p2i][p1i]) 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; process->p1_virtual_bases[p3i][p2i][p1i] = 0;
} }
@ -286,7 +301,7 @@ int load_elf(
uint64_t pma = take_free_physical_page(); uint64_t pma = take_free_physical_page();
map_page_for_process( 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); void *kvma = find_free_kernel_region(4096);
map_in_kernel_page_table(pma, kvma, 1, 0); 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) { for (int p1i = 0; p1i < 512; ++p1i) {
uint64_t pma = uint64_t pma =
process->p1_virtual_bases[p3i][p2i][p1i] & 0x7ffffffffffff000; process->p1_virtual_bases[p3i][p2i][p1i] & 0x7ffffffffffff000;
if (pma >= fb_physical_base && if (process->owned_pages_bitmaps[p3i][p2i][p1i / 8] & (1 << (p1i % 8)))
pma < fb_physical_base + fb_pitch * fb_height)
continue;
mark_physical_memory_free(pma, 4096); mark_physical_memory_free(pma, 4096);
} }
unmap_and_free_kernel_page(process->p1_virtual_bases[p3i][p2i]); 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]); unmap_and_free_kernel_page(process->p2_virtual_bases[p3i]);
heap_dealloc(process->p1_virtual_bases[p3i], 4096); 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->p3_virtual_base);
unmap_and_free_kernel_page(process->p4_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(); uint64_t pma = take_free_physical_page();
map_page_for_process( 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); void *kvma = find_free_kernel_region(4096);
map_in_kernel_page_table(pma, kvma, 1, 0); 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( map_page_for_process(
running_thread->process, running_thread->process,
fb_physical_base + i * 4096, fb_physical_base + i * 4096,
base + i * 4096, 1, 0); base + i * 4096, 1, 0, 0);
info_out->fb_base = base; info_out->fb_base = base;
info_out->fb_pitch = fb_pitch; info_out->fb_pitch = fb_pitch;
@ -605,7 +620,7 @@ void *syscall_map_pages(uint64_t count) {
map_page_for_process( map_page_for_process(
running_thread->process, running_thread->process,
pma, vma + i * 4096, pma, vma + i * 4096,
1, 0); 1, 0, 1);
} }
return vma; return vma;

View file

@ -46,6 +46,10 @@ struct process {
uint64_t *p2_virtual_bases[512]; uint64_t *p2_virtual_bases[512];
uint64_t **p1_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. //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. //virtual base must be in bottom p3 and not zero.
void map_page_for_process( void map_page_for_process(
struct process *process, uint64_t physical_base, 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. //virtual base must be page-aligned, in bottom p3, and not zero.
void unmap_page_for_process( void unmap_page_for_process(