diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-24 21:18:55 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-05-24 21:18:55 +0300 |
| commit | e033569910aecb4d8fb437a622e542b8803834ec (patch) | |
| tree | b7e31d1b266dfbd3b1aa79ae4db47d584541c8bc | |
| parent | 12be40e22aae582cca9abbd151031edaab800cae (diff) | |
| download | kmi-e033569910aecb4d8fb437a622e542b8803834ec.tar.gz kmi-e033569910aecb4d8fb437a622e542b8803834ec.zip | |
initial musings about exec
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | arch/riscv64/include/vmem.h | 4 | ||||
| -rw-r--r-- | common/elf.c | 8 | ||||
| -rw-r--r-- | common/proc.c | 2 | ||||
| -rw-r--r-- | common/timer.c | 2 | ||||
| -rw-r--r-- | common/uapi/proc.c | 31 | ||||
| -rw-r--r-- | common/vmem.c | 17 | ||||
| -rw-r--r-- | include/apos/elf.h | 2 | ||||
| -rw-r--r-- | include/apos/mem.h | 10 | ||||
| -rw-r--r-- | include/apos/mem_regions.h | 6 | ||||
| -rw-r--r-- | include/apos/vmem.h | 6 | ||||
| -rw-r--r-- | include/libfdt.h | 2 |
12 files changed, 73 insertions, 18 deletions
@@ -3,6 +3,7 @@ *.bin *.elf *.ld +*/kernel/gen/* docs/output deps.mk *.img diff --git a/arch/riscv64/include/vmem.h b/arch/riscv64/include/vmem.h index fc3df00..46c12b1 100644 --- a/arch/riscv64/include/vmem.h +++ b/arch/riscv64/include/vmem.h @@ -16,10 +16,10 @@ * riscv64. */ #if __riscv_xlen == 64 - /** When running riscv64, each page table has 512 8byte entries. */ +/** When running riscv64, each page table has 512 8byte entries. */ #define RISCV_NUM_LEAVES 512 #else - /** When running riscv32, each page table has 1024 4byte entries. */ +/** When running riscv32, each page table has 1024 4byte entries. */ #define RISCV_NUM_LEAVES 1024 #endif diff --git a/common/elf.c b/common/elf.c index 97d8fd7..b88be89 100644 --- a/common/elf.c +++ b/common/elf.c @@ -76,7 +76,7 @@ static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, * hacky, I know.*/ } -static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) +static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf, vm_t interp) { short e_type = elf_header_prop(ei_c, elf, e_type); if (e_type != ET_DYN && e_type != ET_EXEC) @@ -97,9 +97,9 @@ static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) } /* sets up all memory regions etc, returns the entry address */ -vm_t load_elf(struct tcb *t, vm_t b) +vm_t load_elf(struct tcb *t, vm_t elf, vm_t interp) { - struct elf_ident *i = (struct elf_ident *)b; + struct elf_ident *i = (struct elf_ident *)elf; if (i->ei_magic != cpu_to_be32(EI_MAGIC)) return 0; @@ -107,5 +107,5 @@ vm_t load_elf(struct tcb *t, vm_t b) return 0; /* more sanity checks? */ - return __prepare_proc(t, i->ei_class, b); + return __prepare_proc(t, i->ei_class, elf, interp); } diff --git a/common/proc.c b/common/proc.c index e88d37d..f09e7c1 100644 --- a/common/proc.c +++ b/common/proc.c @@ -45,7 +45,7 @@ stat_t init_proc(void *fdt, struct vmem *b) /* TODO: this stuff should be placed in __sys_exec */ /* the binary gets to choose first what memory regions it requires */ - t->entry = load_elf(t, get_init_base(fdt)); + t->entry = load_elf(t, get_init_base(fdt), 0); if (!t->entry) return ERR_ADDR; diff --git a/common/timer.c b/common/timer.c index f36c90d..dadb88d 100644 --- a/common/timer.c +++ b/common/timer.c @@ -136,7 +136,7 @@ struct timer *find_timer(id_t cid) stat_t remove_timer(struct timer *t) { if (!t) - return; + return ERR_INVAL; struct sp_node *n = &timer_node_container(t)->sp_n; sp_remove(&sp_root(__cpu_timers()), n); diff --git a/common/uapi/proc.c b/common/uapi/proc.c index e36c62e..3f715af 100644 --- a/common/uapi/proc.c +++ b/common/uapi/proc.c @@ -4,6 +4,8 @@ */ #include <apos/uapi.h> +#include <apos/bits.h> +#include <apos/mem_regions.h> SYSCALL_DEFINE0(create)(){ return (struct sys_ret){ OK, 0 }; @@ -23,8 +25,35 @@ SYSCALL_DEFINE0(fork)(){ return (struct sys_ret){ OK, 0 }; } -SYSCALL_DEFINE3(exec)(sys_arg_t bin, sys_arg_t argc, sys_arg_t argv){ +SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){ /* TODO: execute new process, probably with more sensible argc passing */ + struct tcb *r = cur_tcb(); + + /* mark binary to be kept */ + struct mem_region *b = find_used_region(&r->sp_r, bin); + if (!b) + return (struct sys_ret){ERR_INVAL, 0}; + __set_bit(b->flags, MR_KEEP); + + struct mem_region *i = 0; + if (interp) { + /* mark interpreter to be kept */ + i = find_used_region(&r->sp_r, interp); + if (!i) + return (struct sys_ret){ERR_INVAL, 1}; + __set_bit(i->flags, MR_KEEP); + } + + /* free everything except regions to be kept */ + clear_uvmem(r, false); + + /* restore to normal */ + __clear_bit(b->flags, MR_KEEP); + if (interp) + __clear_bit(b->flags, MR_KEEP); + + /* TODO: set entry? */ + load_elf(r, b, i); return (struct sys_ret){ OK, 0 }; } diff --git a/common/vmem.c b/common/vmem.c index ae40748..3ea9ed7 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -25,15 +25,26 @@ static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m) return status; } -stat_t destroy_uvmem(struct tcb *t) +stat_t clear_uvmem(struct tcb *t, bool force) { struct mem_region *m = find_first_region(&t->sp_r); while (m) { - /* free all memory associated with used regions */ - if (is_region_used(m)) + /* if force is not set, free only regions that are not marked to + * be kept and are owned. + * + * if force is set, free all owned regions. + */ + if (is_region_owned(m) && (force || !is_region_kept(m))) __free_mapped_region(t, m); } + return OK; +} + +stat_t destroy_uvmem(struct tcb *t) +{ + /* force clear all regions */ + clear_uvmem(t, true); /* destroy region tree itself */ return destroy_region(&t->sp_r); } diff --git a/include/apos/elf.h b/include/apos/elf.h index cea504e..1e9a4aa 100644 --- a/include/apos/elf.h +++ b/include/apos/elf.h @@ -194,6 +194,6 @@ struct __packed section64_header { #define section_header_prop(c, e, p) \ (c == ELFCLASS64 ? section64_header(e)->p : section32_header(e)->p) -vm_t load_elf(struct tcb *t, vm_t b); +vm_t load_elf(struct tcb *t, vm_t binary, vm_t interp); #endif /* APOS_ELF_H */ diff --git a/include/apos/mem.h b/include/apos/mem.h index 7d24e0e..b6d76c1 100644 --- a/include/apos/mem.h +++ b/include/apos/mem.h @@ -48,14 +48,16 @@ __page((x) + BASE_PAGE_SIZE)) #define __bytes(x) (__addr(x)) -/* if memory region is used or not */ +/** If memory region is used or not */ #define MR_USED (1 << 8) -/* if memory region is shared */ +/** If memory region is shared */ #define MR_SHARED (1 << 9) -/* owner of shared region */ +/** Owner of shared region */ #define MR_OWNED (1 << 10) -/* copy on write */ +/** Copy on write. */ #define MR_COW (1 << 11) +/** Don't free memory on flush. */ +#define MR_KEEP (1 << 12) extern size_t __mm_shifts[10]; extern size_t __mm_widths[10]; diff --git a/include/apos/mem_regions.h b/include/apos/mem_regions.h index 8e9125f..bd1ce2b 100644 --- a/include/apos/mem_regions.h +++ b/include/apos/mem_regions.h @@ -14,6 +14,9 @@ #define mem_container(ptr) container_of(ptr, struct mem_region, sp_n) #define is_region_used(r) __is_set(r->flags, MR_USED) +#define is_region_owned(r) __is_set(r->flags, MR_OWNED) +#define is_region_shared(r) __is_set(r->flags, MR_SHARED) +#define is_region_kept(r) __is_set(r->flags, MR_KEEP) struct mem_region_root { struct sp_root free_regions; @@ -54,6 +57,9 @@ typedef stat_t region_callback_t(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); +stat_t stat_region(struct mem_region_root *r, vm_t va, vmflags_t *flags); +stat_t mod_region(struct mem_region_root *r, vm_t va, vmflags_t flags); + vm_t map_fill_region(struct vmem *b, region_callback_t *mem_handler, pm_t offset, vm_t start, size_t bytes, vmflags_t flags, void *data); diff --git a/include/apos/vmem.h b/include/apos/vmem.h index 663b2ab..1451c82 100644 --- a/include/apos/vmem.h +++ b/include/apos/vmem.h @@ -16,6 +16,7 @@ vm_t alloc_fixed_uvmem(struct tcb *r, vm_t start, size_t size, vmflags_t flags); vm_t alloc_shared_uvmem(struct tcb *r, size_t size, vmflags_t flags); vm_t ref_shared_uvmem(struct tcb *r1, struct tcb *r2, vm_t va, vmflags_t flags); +stat_t clear_uvmem(struct tcb *r, bool force); stat_t free_uvmem(struct tcb *r, vm_t a); stat_t init_uvmem(struct tcb *r, vm_t base, vm_t top); @@ -25,6 +26,8 @@ stat_t alloc_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); stat_t alloc_shared_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); +stat_t clone_allocd_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, + vmflags_t flags, enum mm_order order, void *data); stat_t free_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, vmflags_t flags, enum mm_order order, void *data); @@ -34,6 +37,9 @@ stat_t free_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr, #define map_shared_region(b, start, bytes, flags, data) \ map_fill_region(b, &alloc_shared_wrapper, 0, start, bytes, flags, data) +#define clone_allocd_region(b, start, bytes, flags, data) \ + map_fill_region(b, &clone_allocd_wrapper, 0, start, bytes, flags, data) + #define unmap_freed_region(b, start, bytes, flags, data) \ map_fill_region(b, &free_uvmem_wrapper, 0, start, bytes, flags, data) diff --git a/include/libfdt.h b/include/libfdt.h index a1266c9..f6e159d 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -83,7 +83,7 @@ void __dbg_fdt(const void *fdt, int node_offset, int depth); /** * Load int{32,64} from FDT at location specified by pointer. - * + * * @param c Size of int, where 2 == int64 and everything else int32. Query int * size from FDT with \ref get_cellinfo() and \ref get_reginfo(). * @param p Pointer to int{32,64} inside the global FDT. |
