From 55564101a2263650f05502aa43f0d238e3d91e03 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Mon, 18 Nov 2019 17:56:38 +0900 Subject: [PATCH] Make use of pg_dir_foreach_region() function in process_create() function to clone or map memory regions of the parent process, where necessary --- kernel/core/process.c | 78 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/kernel/core/process.c b/kernel/core/process.c index d1c860f..118b977 100644 --- a/kernel/core/process.c +++ b/kernel/core/process.c @@ -159,6 +159,70 @@ static inline int DQ(process_t *p) return(ret_val); } +int _fork_region(pg_dir_t *parent_dir, region_t *reg, void *data) +{ + pg_dir_t *child_dir; + int ret_val; + + ret_val = 0; + child_dir = (pg_dir_t*)data; + + if(!(reg->reg_flags & REGION_PRIV)) { + /* skip regions that are private to the parent */ + + switch(reg->reg_type) { + case REGION_TEXT: + case REGION_BSS: + case REGION_DATA: + case REGION_RODATA: + /* copy the region and its contents */ + ret_val = pg_dir_clone_region(child_dir, parent_dir, reg); + break; + + case REGION_KSTACK: + case REGION_STACK: + case REGION_HEAP: + /* don't clone KSTACK/STACK/HEAP regions */ + default: + break; + } + } + + return(ret_val); +} + +int _vfork_region(pg_dir_t *parent_dir, region_t *reg, void *data) +{ + pg_dir_t *child_dir; + int ret_val; + + ret_val = 0; + child_dir = (pg_dir_t*)data; + + if(!(reg->reg_flags & REGION_PRIV)) { + /* skip private regions */ + + switch(reg->reg_type) { + case REGION_TEXT: + case REGION_BSS: + case REGION_DATA: + case REGION_RODATA: + /* directly map the region into the new page directory */ + ret_val = pg_dir_map_region(child_dir, parent_dir, reg); + break; + + case REGION_KSTACK: + case REGION_STACK: + case REGION_HEAP: + /* don't map these */ + default: + break; + } + } + + return(ret_val); +} + int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry) { int ret_val; @@ -206,6 +270,10 @@ int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry) goto cleanup; } + /* + * The new page directory contains only the kernel regions. + */ + pdbr = pg_dir_get_pdbr(proc->p_pgdir); kstack = pg_dir_get_kstack(proc->p_pgdir); ustack = pg_dir_get_ustack(proc->p_pgdir); @@ -269,6 +337,16 @@ int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry) cproc = (process_t*)ctask->t_proc; custack = pg_dir_get_ustack(cproc->p_pgdir); + /* + * The address space of the new process doesn't contain any memory segments + * but those relevant for the kernel. If the process is a fork, clone all non-kernel + * memory segments that are present in the parent's page directory. If it is a vfork, + * directly map the segments into this address space. + */ + pg_dir_foreach_region(cproc->p_pgdir, + entry == PROC_ENTRY_FORK ? _fork_region : _vfork_region, + proc->p_pgdir); + /* * In the case of fork() and vfork() we have to get the address that the * interrupt is supposed to return to. The stack that the address was pushed -- 2.47.3