aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/elf.c3
-rw-r--r--common/mem_regions.c22
-rw-r--r--common/uapi/dispatch.c1
-rw-r--r--common/uapi/mem.c28
-rw-r--r--common/vmem.c44
5 files changed, 73 insertions, 25 deletions
diff --git a/common/elf.c b/common/elf.c
index fcd6e85..f423fc5 100644
--- a/common/elf.c
+++ b/common/elf.c
@@ -54,7 +54,7 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
* segment fits into it */
/** \todo check if p_memsz is larger than p_filesz, the segment should be
* filled with zeroes. */
- /** \todo in general, make this a low more clean. */
+ /** \todo in general, make this a lot more clean. */
/* useful bit of info: all segments are sorted in ascending order of p_vaddr */
vm_t runner = phstart;
vmflags_t default_flags = VM_V | VM_R | VM_W | VM_X | VM_U;
@@ -74,6 +74,7 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart,
uint8_t uvflags = __elf_to_uvflags(elf_flags);
map_allocd_region(t->proc.vmem, start, vsz, default_flags, 0);
+ memset((void *)start, 0, vsz);
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 eee9230..17f3a1e 100644
--- a/common/mem_regions.c
+++ b/common/mem_regions.c
@@ -323,12 +323,14 @@ struct mem_region *find_first_region(struct mem_region_root *r)
* @param m Free memory region to carve used memory region out of.
* @param pages Number of base order pages to give used region.
* @param align Alignment of used region. In this case, start of used region
+ * @param pid Process ID to associate with region if shared. 0 if private.
* from start of free region.
* @param flags Flags of used region.
* @return Start address of used region.
*/
static vm_t __partition_region(struct mem_region_root *r, struct mem_region *m,
- size_t pages, size_t align, vmflags_t flags)
+ size_t pages, size_t align, vmflags_t flags,
+ id_t pid)
{
sp_remove(&sp_root(&r->free_regions), &m->sp_n);
@@ -364,6 +366,7 @@ static vm_t __partition_region(struct mem_region_root *r, struct mem_region *m,
m->end = end;
m->start = start;
m->flags = flags;
+ m->pid = pid;
mark_region_used(m->flags);
__insert_used_region(r, m);
return __addr(start);
@@ -373,8 +376,9 @@ static vm_t __partition_region(struct mem_region_root *r, struct mem_region *m,
* just ignore them for now. Note that alloc_region should only be used when
* mmap is called with MAP_ANON, all other situations should be handled in some
* fs server */
-vm_t alloc_region(struct mem_region_root *r, size_t size, size_t *actual_size,
- vmflags_t flags)
+stat_t alloc_shared_region(struct mem_region_root *r, size_t size,
+ size_t *actual_size,
+ vmflags_t flags, id_t pid)
{
size_t asize = align_up(size, BASE_PAGE_SIZE);
if (actual_size)
@@ -388,7 +392,13 @@ vm_t alloc_region(struct mem_region_root *r, size_t size, size_t *actual_size,
if (!m)
return 0;
- return __partition_region(r, m, pages, align, flags);
+ return __partition_region(r, m, pages, align, flags, pid);
+}
+
+vm_t alloc_region(struct mem_region_root *r, size_t size, size_t *actual_size,
+ vmflags_t flags)
+{
+ return alloc_shared_region(r, size, actual_size, flags, 0);
}
vm_t alloc_fixed_region(struct mem_region_root *r, vm_t start, size_t size,
@@ -406,7 +416,7 @@ vm_t alloc_fixed_region(struct mem_region_root *r, vm_t start, size_t size,
return 0;
/* locate actual region where start is between the region start and end */
- while (!((m->start <= start) && (start <= m->end))) {
+ while (!((m->start <= start) && (start < m->end))) {
if (start > m->start)
m = m->next;
else
@@ -422,7 +432,7 @@ vm_t alloc_fixed_region(struct mem_region_root *r, vm_t start, size_t size,
return 0;
/* actually start marking region used */
- return __partition_region(r, m, pages, start - m->start, flags);
+ return __partition_region(r, m, pages, start - m->start, flags, 0);
}
/**
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
index aa63170..d11e02e 100644
--- a/common/uapi/dispatch.c
+++ b/common/uapi/dispatch.c
@@ -53,6 +53,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break;
case SYS_REQ_PMEM: sys_req_pmem(t, a, b, c, d, e); break;
case SYS_REQ_FIXMEM: sys_req_fixmem(t, a, b, c, d, e); break;
+ case SYS_REQ_SHAREDMEM: sys_req_sharedmem(t, a, b, c, d, e); break;
case SYS_FREE_MEM: sys_free_mem(t, a, b, c, d, e); break;
case SYS_TIMEBASE: sys_timebase(t, a, b, c, d, e); break;
case SYS_TICKS: sys_ticks(t, a, b, c, d, e); break;
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
index 374bcbe..099028e 100644
--- a/common/uapi/mem.c
+++ b/common/uapi/mem.c
@@ -107,23 +107,33 @@ SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
* Request shared memory syscall handler.
*
* @param t Current tcb.
+ * @param tid Thread to share memory with.
* @param size Minimum size of allocation.
- * @param flags Flags of allocation.
- * @return \ref OK and start of allocation when succesful,
- * \ref ERR_OOMEM and \c NULL otherwise.
+ * @param sflags Flags of allocation for \p t.
+ * @param cflags Flags of allocation for \p tid.
+ * @return \ref OK and start of \p t allocation and start of \p tid allocation,
+ * in that order, \ref ERR_OOMEM 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)
+SYSCALL_DEFINE4(req_sharedmem)(struct tcb *t, sys_arg_t tid,
+ sys_arg_t size, sys_arg_t sflags,
+ sys_arg_t cflags)
{
- /** \todo check that requester is server */
- struct tcb *r = get_cproc(t);
- vm_t start = 0;
- if (!(start = alloc_shared_uvmem(r, size, flags)))
+ /** @todo check capability for shared memory */
+ struct tcb *u = get_tcb(tid);
+ if (!u)
+ return_args(t, SYS_RET1(ERR_INVAL));
+
+ struct tcb *s = get_cproc(t);
+ struct tcb *c = get_rproc(u);
+
+ vm_t sstart, cstart;
+ if (alloc_shared_uvmem(s, c, size, sflags, cflags, &sstart, &cstart))
return_args(t, SYS_RET1(ERR_OOMEM));
- return_args(t, SYS_RET2(OK, start));
+ return_args(t, SYS_RET3(OK, sstart, cstart));
}
/** \todo add some way to specify who gets to access the shared memory? */
diff --git a/common/vmem.c b/common/vmem.c
index a53ce6c..781458a 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -151,19 +151,45 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags)
}
/* 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)
+stat_t alloc_shared_uvmem(struct tcb *s, struct tcb *c,
+ size_t size, vmflags_t sflags, vmflags_t cflags,
+ vm_t *sstart, vm_t *cstart)
{
- hard_assert(t && is_proc(t), ERR_INVAL);
+ hard_assert(sstart, ERR_INVAL);
+ hard_assert(cstart, ERR_INVAL);
+ hard_assert(s && is_proc(s), ERR_INVAL);
+ hard_assert(c && is_proc(c), 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->proc.vmem, v, size, flags, &status);
+ size_t ssize, csize;
+ vm_t sv = alloc_shared_region(&s->sp_r, size, &ssize, sflags, c->rid);
+ vm_t cv = alloc_shared_region(&c->sp_r, size, &csize, cflags, s->rid);
- if (is_rpc(t) && status == INFO_SEFF)
- clone_rpc_maps(t);
+ if (csize != ssize) {
+ /** @todo cleanup, better errors? */
+ return ERR_INVAL;
+ }
- return w;
+ stat_t cstatus = OK, sstatus = OK;
+ size_t osize = order_size(BASE_PAGE);
+ size_t pages = ssize / osize;
+ for (size_t i = 0; i < pages; ++i) {
+ pm_t p = alloc_page(BASE_PAGE);
+ sstatus = map_vpage(s->proc.vmem, p, sv + i * osize, sflags,
+ BASE_PAGE);
+ cstatus = map_vpage(c->proc.vmem, p, cv + i * osize, cflags,
+ BASE_PAGE);
+ }
+
+ if (cstatus == INFO_SEFF)
+ clone_rpc_maps(c);
+
+ if (sstatus == INFO_SEFF)
+ clone_rpc_maps(s);
+
+ *sstart = sv;
+ *cstart = cv;
+
+ return OK;
}
vm_t ref_shared_uvmem(struct tcb *t1, struct tcb *t2, vm_t va, vmflags_t flags)