aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/mem.c9
-rw-r--r--common/uapi/dispatch.c1
-rw-r--r--common/uapi/mem.c19
-rw-r--r--common/vmem.c30
4 files changed, 59 insertions, 0 deletions
diff --git a/common/mem.c b/common/mem.c
index 2cf72e3..f4a0919 100644
--- a/common/mem.c
+++ b/common/mem.c
@@ -17,6 +17,15 @@ size_t __mm_sizes[10];
size_t __mm_page_shift;
enum mm_order __mm_max_order;
+enum mm_order nearest_order(size_t size)
+{
+ for (enum mm_order order = max_order(); order >= MM_MIN; --order)
+ if (order_size(order) >= size)
+ return order;
+
+ return MM_O0;
+}
+
void init_mem(size_t max_order, size_t bits[10], size_t page_shift)
{
__mm_max_order = max_order;
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
index d11e02e..b5cd51e 100644
--- a/common/uapi/dispatch.c
+++ b/common/uapi/dispatch.c
@@ -51,6 +51,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_NOOP: sys_noop(t, a, b, c, d, e); break;
case SYS_PUTCH: sys_putch(t, a, b, c, d, e); break;
case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break;
+ case SYS_REQ_PAGE: sys_req_page(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;
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
index 099028e..41ebcca 100644
--- a/common/uapi/mem.c
+++ b/common/uapi/mem.c
@@ -33,6 +33,25 @@ SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
}
/**
+ * Allocate single page to program.
+ *
+ * @param t Current tcb.
+ * @param size Size of the allocation.
+ * @param flags Flags of allocation.
+ * @return \ref ERR_OOMEM if unsucessful, otherwise \ref OK, virtual address,
+ * actual size, physical address, in that order.
+ */
+SYSCALL_DEFINE2(req_page)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
+{
+ struct tcb *r = get_cproc(t);
+ vm_t start = 0; pm_t paddr = 0; size_t asize = size;
+ if (!(start = alloc_uvpage(r, asize, flags, &asize, &paddr)))
+ return_args(t, SYS_RET1(ERR_OOMEM));
+
+ return_args(t, SYS_RET4(OK, start, asize, paddr));
+}
+
+/**
* Fixed memory request syscall handler.
*
* @param t Current tcb.
diff --git a/common/vmem.c b/common/vmem.c
index f1eed83..b28a3d6 100644
--- a/common/vmem.c
+++ b/common/vmem.c
@@ -200,6 +200,36 @@ vm_t alloc_uvmem(struct tcb *t, size_t size, vmflags_t flags)
return w;
}
+vm_t alloc_uvpage(struct tcb *t, size_t size, vmflags_t flags, size_t *asize,
+ pm_t *paddr)
+{
+ hard_assert(t && is_proc(t), ERR_INVAL);
+
+ enum mm_order order = nearest_order(size);
+ size_t actual_size = order_size(order);
+ stat_t status = OK;
+
+ const vm_t v = alloc_region(&t->sp_r, size, &size, flags);
+ const vm_t w = __addr(__page(v));
+
+ pm_t addr = alloc_page(order);
+ /** @todo should free region */
+ if (!addr)
+ return NULL;
+
+ status = map_vpage(t->proc.vmem, addr, w, flags, order);
+ if (is_rpc(t) && status == INFO_SEFF)
+ clone_rpc_maps(t);
+
+ if (asize)
+ *asize = actual_size;
+
+ if (paddr)
+ *paddr = addr;
+
+ return w;
+}
+
vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags)
{
hard_assert(t && is_proc(t), ERR_INVAL);