aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/mem_regions.c8
-rw-r--r--common/tcb.c10
-rw-r--r--common/uapi/ipc.c5
-rw-r--r--common/uapi/mem.c47
-rw-r--r--common/vmem.c10
5 files changed, 34 insertions, 46 deletions
diff --git a/common/mem_regions.c b/common/mem_regions.c
index 8d066e7..eee9230 100644
--- a/common/mem_regions.c
+++ b/common/mem_regions.c
@@ -185,13 +185,15 @@ stat_t destroy_region(struct mem_region_root *r)
* */
struct mem_region *find_used_region(struct mem_region_root *r, vm_t start)
{
+ /** @todo check that start is aligned to page boundary? */
+ vm_t ref = __page(start);
struct sp_node *n = sp_root(&r->used_regions);
while (n) {
struct mem_region *t = mem_container(n);
- if (start == t->start)
+ if (ref == t->start)
return t;
- if (start < t->start)
+ if (ref < t->start)
n = sp_left(n);
else
n = sp_right(n);
@@ -500,7 +502,7 @@ stat_t free_region(struct mem_region_root *r, vm_t start)
if (!is_aligned(start, BASE_PAGE_SIZE))
return ERR_ALIGN;
- struct mem_region *m = find_used_region(r, __page(start));
+ struct mem_region *m = find_used_region(r, start);
if (!m)
return ERR_NF;
diff --git a/common/tcb.c b/common/tcb.c
index ef15788..fb2f934 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -435,7 +435,7 @@ struct call_ctx {
id_t pid;
};
-void save_context(struct tcb *t)
+void enter_rpc(struct tcb *t)
{
vm_t rpc_stack = t->rpc_stack;
if (is_rpc(t))
@@ -447,6 +447,10 @@ void save_context(struct tcb *t)
rpc_stack = align_down(get_stack(t), BASE_PAGE_SIZE);
+ /* make sure updates are visible when swapping to the new virtual memory */
+ mark_rpc_inaccessible(t, rpc_stack, t->rpc_stack);
+ use_vmem(t->rpc.vmem);
+
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
ctx->exec = t->exec;
ctx->pid = t->pid;
@@ -468,12 +472,12 @@ void save_context(struct tcb *t)
* we'll handle it separately and if the process isn't going over the
* limit just give it more.
* */
- mark_rpc_inaccessible(t, rpc_stack, t->rpc_stack);
t->rpc_stack = rpc_stack;
t->regs = (vm_t)ctx;
+ set_stack(t, rpc_stack);
}
-void load_context(struct tcb *t)
+void leave_rpc(struct tcb *t)
{
vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
index 93717e4..70f5fe7 100644
--- a/common/uapi/ipc.c
+++ b/common/uapi/ipc.c
@@ -60,8 +60,7 @@ static void do_ipc(struct tcb *t,
return_args(t, SYS_RET1(ERR_NOINIT));
clone_uvmem(r->proc.vmem, t->rpc.vmem);
- use_vmem(t->rpc.vmem);
- save_context(t);
+ enter_rpc(t);
set_return(t, r->callback);
attach_rpc(r, t);
@@ -122,7 +121,7 @@ SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1,
sys_arg_t d3)
{
struct tcb *r = get_cproc(t);
- load_context(t);
+ leave_rpc(t);
detach_rpc(r, t);
if (is_rpc(t))
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
index 1de63f1..374bcbe 100644
--- a/common/uapi/mem.c
+++ b/common/uapi/mem.c
@@ -25,7 +25,8 @@ SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
{
struct tcb *r = get_cproc(t);
vm_t start = 0;
- if ((start = alloc_uvmem(r, size, flags)))
+ /** @todo expose flags to users */
+ if (!(start = alloc_uvmem(r, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
@@ -46,7 +47,7 @@ SYSCALL_DEFINE3(req_fixmem)(struct tcb *t, sys_arg_t fixed, sys_arg_t size,
{
struct tcb *r = get_cproc(t);
vm_t start = 0;
- if ((start = alloc_fixed_uvmem(r, fixed, size, flags)))
+ if (!(start = alloc_fixed_uvmem(r, fixed, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
@@ -65,15 +66,15 @@ SYSCALL_DEFINE1(free_mem)(struct tcb *t, sys_arg_t start)
vm_t vm_start = (vm_t)start;
stat_t status = OK;
- if (vm_start > __pre_top && vm_start < __post_base)
- status = free_uvmem(r, vm_start);
- else
- status = free_devmem(r, vm_start);
+ /* try freeing normal user memory first, if that fails, try device
+ * memory, otherwise just assume the address is borked. */
+ if (!(status = free_uvmem(r, vm_start)))
+ return_args(t, SYS_RET1(OK));
- if (status)
- return_args(t, SYS_RET1(ERR_NF));
+ if (!(status = free_devmem(r, vm_start)))
+ return_args(t, SYS_RET1(OK));
- return_args(t, SYS_RET1(OK));
+ return_args(t, SYS_RET1(status));
}
/**
@@ -96,7 +97,7 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
*/
struct tcb *r = get_cproc(t);
vm_t start = 0;
- if ((start = alloc_devmem(r, paddr, size, flags)))
+ if (!(start = alloc_devmem(r, paddr, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
@@ -110,34 +111,16 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
* @param flags Flags of allocation.
* @return \ref OK and start of allocation when succesful,
* \ref ERR_OOMEM and \c NULL otherwise.
+ *
+ * @todo should we also take the thread who should get the other end of the
+ * memory?
*/
SYSCALL_DEFINE2(req_sharedmem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
{
/** \todo check that requester is server */
struct tcb *r = get_cproc(t);
vm_t start = 0;
- if ((start = alloc_shared_uvmem(r, size, flags)))
- return_args(t, SYS_RET1(ERR_OOMEM));
-
- return_args(t, SYS_RET2(OK, start));
-}
-
-/**
- * Reference shared memory syscall handler.
- *
- * @param t Current tcb.
- * @param tid Thread ID of shared memory owner.
- * @param va Start of shared memory in \c tid.
- * @param flags Flags of reference.
- * @return \ref OK and start of reference when succesful,
- * \ref ERR_OOMEM and \c NULL otherwise.
- */
-SYSCALL_DEFINE3(ref_sharedmem)(struct tcb *t, sys_arg_t tid, sys_arg_t va,
- sys_arg_t flags)
-{
- struct tcb *t2 = get_tcb(tid);
- vm_t start = 0;
- if ((start = ref_shared_uvmem(t, t2, va, flags)))
+ if (!(start = alloc_shared_uvmem(r, size, flags)))
return_args(t, SYS_RET1(ERR_OOMEM));
return_args(t, SYS_RET2(OK, start));
diff --git a/common/vmem.c b/common/vmem.c
index 56bc01a..a53ce6c 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -58,8 +58,10 @@ static stat_t __clone_mapped_region(struct tcb *d, struct tcb *s,
static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m)
{
stat_t status = OK;
- pm_t pa = __addr(m->end - m->start);
- if (unmap_freed_region(t->proc.vmem, m->start, pa, m->flags, &status))
+ pm_t start = __addr(m->start);
+ pm_t end = __addr(m->end);
+ if (!unmap_freed_region(t->proc.vmem, start, end - start, m->flags,
+ &status))
return ERR_MISC;
return status;
@@ -196,13 +198,11 @@ stat_t free_uvmem(struct tcb *r, vm_t va)
if (!m)
return ERR_NF;
- free_region(&r->sp_r, va);
-
stat_t status = __free_mapped_region(r, m);
if (is_rpc(r) && status == INFO_SEFF)
return clone_rpc_maps(r);
- return status;
+ return free_known_region(&r->sp_r, m);
}
stat_t alloc_uvmem_wrapper(struct vmem *b, pm_t *offset, vm_t vaddr,