From 8da0171e5ca3492cdb34422184a1c96acd0b5165 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 21 May 2022 21:02:17 +0300 Subject: add status info to memory mappings + next up would probably be to start working on process/thread relationships, largely as documented. Still not entirely sure about how I want to handle fork, but I suppose I might figure it out at some point. --- common/dmem.c | 17 +++++++------ common/elf.c | 2 +- common/mem_regions.c | 5 ++-- common/tcb.c | 15 +++++++++++ common/uapi/ipc.c | 2 +- common/vmem.c | 71 ++++++++++++++++++++++++++++++++++++++-------------- 6 files changed, 82 insertions(+), 30 deletions(-) (limited to 'common') diff --git a/common/dmem.c b/common/dmem.c index 59ea666..6c207c1 100644 --- a/common/dmem.c +++ b/common/dmem.c @@ -27,15 +27,17 @@ stat_t init_devmem(pm_t ram_base, pm_t ram_top) } stat_t dev_alloc_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, - vmflags_t flags, enum mm_order order) + vmflags_t flags, enum mm_order order, void *data) { - map_vpage(b, *offset, vaddr, flags, order); + stat_t *status = (stat_t *)data; + /* TODO: remember to do something with this status info */ + *status = map_vpage(b, *offset, vaddr, flags, order); *offset += __o_size(order); return OK; } stat_t dev_free_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, - vmflags_t flags, enum mm_order order) + vmflags_t flags, enum mm_order order, void *data) { UNUSED(offset); UNUSED(flags); @@ -43,9 +45,10 @@ stat_t dev_free_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, enum mm_order v_order = 0; stat_vpage(b, vaddr, &paddr, &v_order, 0); if (order != v_order) - return REGION_TRY_AGAIN; + return INFO_TRGN; - unmap_vpage(b, vaddr); + stat_t *status = (stat_t *)data; + *status = unmap_vpage(b, vaddr); return OK; } @@ -62,7 +65,7 @@ vm_t alloc_devmem(struct tcb *t, pm_t dev_start, size_t bytes, vmflags_t flags) return 0; return map_fill_region(t->b_r, &dev_alloc_wrapper, dev_start, region, - bytes, flags); + bytes, flags, 0); } stat_t free_devmem(struct tcb *t, vm_t dev_start) @@ -85,7 +88,7 @@ stat_t free_devmem(struct tcb *t, vm_t dev_start) size_t region_size = __addr(m->end - m->start); map_fill_region(t->b_r, &dev_free_wrapper, dev_paddr, dev_start, - region_size, 0); + region_size, 0, 0); if (dev_paddr < __pre_top) free_region(&pre_ram, dev_paddr); diff --git a/common/elf.c b/common/elf.c index 459cacf..9af4f08 100644 --- a/common/elf.c +++ b/common/elf.c @@ -46,7 +46,7 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, uint8_t elf_flags = program_header_prop(ei_c, runner, p_flags); uint8_t uvflags = __elf_to_uvflags(elf_flags); - map_allocd_region(t->b_r, start, vsz, default_flags); + map_allocd_region(t->b_r, start, vsz, default_flags, 0); vm_t vo = bin + program_header_prop(ei_c, runner, p_offset); vm_t vfz = program_header_prop(ei_c, runner, p_filesz); diff --git a/common/mem_regions.c b/common/mem_regions.c index b0cbe0e..bbc894e 100644 --- a/common/mem_regions.c +++ b/common/mem_regions.c @@ -426,7 +426,8 @@ stat_t free_known_region(struct mem_region_root *r, struct mem_region *m) * permutations etc. which would be slow and I don't want to implement it. */ vm_t map_fill_region(struct vm_branch *b, region_callback_t *mem_handler, - pm_t offset, vm_t start, size_t bytes, vmflags_t flags) + pm_t offset, vm_t start, size_t bytes, vmflags_t flags, + void *data) { pm_t runner = __page(start); size_t pages = __pages(bytes); @@ -447,7 +448,7 @@ vm_t map_fill_region(struct vm_branch *b, region_callback_t *mem_handler, while (pages >= o_pages) { stat_t res = mem_handler(b, &offset, __addr(runner), - flags, top); + flags, top, data); if (res > 0) break; diff --git a/common/tcb.c b/common/tcb.c index bb1bcec..212e20f 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include /* arguably exessively many globals... */ static id_t start_tid; @@ -98,3 +100,16 @@ struct tcb *get_tcb(id_t tid) return tcbs[tid]; } + +stat_t clone_tcb_maps(struct tcb *r) +{ + hard_assert(r && !r->parent, ERR_INVAL); + struct tcb *t = r; + while ((t = t->next)) { + stat_t ret = clone_vmbranch(r->b_r, t->b_r); + if (ret) + return ret; + } + + return OK; +} diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c index bef9665..d7c9d16 100644 --- a/common/uapi/ipc.c +++ b/common/uapi/ipc.c @@ -14,7 +14,7 @@ SYSCALL_DEFINE1(ipc_server)(sys_arg_t callback) SYSCALL_DEFINE3(ipc_req)(sys_arg_t tid, sys_arg_t d0, sys_arg_t d1) { struct tcb *r = get_tcb(tid); - /* something like jump_to_callback(t, d0, d1) */ + /* something like jump_to_callback(t) */ return (struct sys_ret){ d0, d1 }; } diff --git a/common/vmem.c b/common/vmem.c index 989029a..817f851 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -10,23 +12,46 @@ stat_t init_uvmem(struct tcb *t, vm_t base, vm_t top) vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags) { - vm_t v = alloc_region(&t->sp_r, size, &size, flags); - return map_allocd_region(t->b_r, v, size, flags); + /* t exists and is the root tcb of the current process */ + hard_assert(t && !t->parent, ERR_INVAL); + + stat_t status = OK; + const vm_t v = alloc_region(&t->sp_r, size, &size, flags); + const vm_t w = map_allocd_region(t->b_r, v, size, flags, &status); + if (status == INFO_SEFF) + clone_tcb_maps(t); + + return w; } vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) { - vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size, flags); - return map_allocd_region(t->b_r, v, size, flags); + hard_assert(t && !t->parent, ERR_INVAL); + + stat_t status = OK; + const vm_t v = alloc_fixed_region(&t->sp_r, start, size, &size, flags); + const vm_t w = map_allocd_region(t->b_r, v, size, flags, &status); + + if (status == INFO_SEFF) + clone_tcb_maps(t); + + return w; } /* free_shared_uvmem shouldn't be needed, likely to work with free_uvmem */ vm_t alloc_shared_uvmem(struct tcb *t, size_t size, vmflags_t flags) { - /* TODO: proper error handling */ - vm_t v = alloc_region(&t->sp_r, size, &size, - flags | MR_SHARED | MR_OWNED); - return map_shared_region(t->b_r, v, size, flags); + hard_assert(t && t->parent, ERR_INVAL); + + stat_t status = OK; + const vm_t v = alloc_region(&t->sp_r, size, &size, + flags | MR_SHARED | MR_OWNED); + const vm_t w = map_shared_region(t->b_r, v, size, flags, &status); + + if (status == INFO_SEFF) + clone_tcb_maps(t); + + return w; } vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags) @@ -54,6 +79,7 @@ vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags) return v; } +/* TODO: assume tcb is root tcb? */ stat_t free_uvmem(struct tcb *t, vm_t va) { struct mem_region *m = find_used_region(&t->sp_r, va); @@ -64,26 +90,31 @@ stat_t free_uvmem(struct tcb *t, vm_t va) vmflags_t flags = m->flags; free_region(&t->sp_r, va); - unmap_freed_region(t->b_r, va, pa, flags); - return 0; + + stat_t status = OK; + unmap_freed_region(t->b_r, va, pa, flags, &status); + if (status == INFO_SEFF) + return clone_tcb_maps(t); + + return status; } stat_t alloc_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, - vmflags_t flags, enum mm_order order) + vmflags_t flags, enum mm_order order, void *data) { *offset = alloc_page(order, *offset); if (!*offset) - return REGION_TRY_AGAIN; /* try again */ + return INFO_TRGN; /* try again */ - map_vpage(b, *offset, vaddr, flags, order); - return OK; + stat_t ret = map_vpage(b, *offset, vaddr, flags, order); + return ret; } stat_t alloc_shared_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, - vmflags_t flags, enum mm_order order) + vmflags_t flags, enum mm_order order, void *data) { if (order != MM_O0) - return REGION_TRY_AGAIN; + return INFO_TRGN; *offset = alloc_page(MM_O0, *offset); map_vpage(b, *offset, vaddr, flags, order); @@ -91,7 +122,7 @@ stat_t alloc_shared_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, } stat_t free_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, - vmflags_t flags, enum mm_order order) + vmflags_t flags, enum mm_order order, void *data) { UNUSED(flags); UNUSED(offset); @@ -100,11 +131,13 @@ stat_t free_uvmem_wrapper(struct vm_branch *b, pm_t *offset, vm_t vaddr, enum mm_order v_order = 0; stat_vpage(b, vaddr, &paddr, &v_order, 0); if (order != v_order) - return REGION_TRY_AGAIN; + return INFO_TRGN; - unmap_vpage(b, vaddr); + stat_t *status = (stat_t *)data; + *status = unmap_vpage(b, vaddr); /* don't free shared pages, unless they're owned */ if (!__is_set(flags, MR_SHARED) || __is_set(flags, MR_OWNED)) free_page(order, paddr); + return OK; } -- cgit v1.3