diff options
author | dzwdz | 2021-07-26 18:17:01 +0200 |
---|---|---|
committer | dzwdz | 2021-07-26 18:17:01 +0200 |
commit | 2ae4e31b74efa29cc92554647d5c9dce077971c4 (patch) | |
tree | cb87d1979ead008b49839ba52245960d81669db5 /src/kernel/arch/i386/pagedir.c | |
parent | bfe381768bf9fde9595a7fdacfb8037458fc0f6a (diff) |
fork() pt 1: cloning process memory
Diffstat (limited to 'src/kernel/arch/i386/pagedir.c')
-rw-r--r-- | src/kernel/arch/i386/pagedir.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/kernel/arch/i386/pagedir.c b/src/kernel/arch/i386/pagedir.c index 02361e6..61ad170 100644 --- a/src/kernel/arch/i386/pagedir.c +++ b/src/kernel/arch/i386/pagedir.c @@ -1,5 +1,6 @@ #include <kernel/arch/generic.h> #include <kernel/mem.h> +#include <kernel/util.h> #include <stdint.h> /* <heat> nitpick: I highly recommend you dont use bitfields for paging @@ -92,6 +93,38 @@ void pagedir_switch(struct pagedir *dir) { asm volatile("mov %0, %%cr3;" : : "r" (dir) : "memory"); } +// creates a new pagedir with exact copies of the user pages +struct pagedir *pagedir_copy(const struct pagedir *orig) { + struct pagedir *clone = page_alloc(1); + struct pagetable_entry *orig_pt, *clone_pt; + void *orig_page, *clone_page; + + for (int i = 0; i < 1024; i++) { + clone->e[i] = orig->e[i]; + if (!orig->e[i].present) continue; + if (!orig->e[i].user) continue; // not really needed + + orig_pt = (void*)(orig->e[i].address << 11); + clone_pt = page_alloc(1); + clone->e[i].address = (uintptr_t) clone_pt >> 11; + + for (int j = 0; j < 1024; j++) { + clone_pt[j] = orig_pt[j]; + if (!orig_pt[j].present) continue; + if (!orig_pt[j].user) continue; + // i could use .global? + + orig_page = (void*)(orig_pt[j].address << 11); + clone_page = page_alloc(1); + clone_pt[j].address = (uintptr_t) clone_page >> 11; + + memcpy(clone_page, orig_page, PAGE_SIZE); + } + } + + return clone; +} + void *pagedir_virt2phys(struct pagedir *dir, const void *virt, bool user, bool writeable) { |