aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-01-26 15:53:16 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2023-01-26 15:53:16 +0200
commit8a5e4cf53d981e793fca90d9b51bd395265cf4db (patch)
tree245aabe14f45aa717f4f3156bdcfc1afb0388131
parent5dad7c7ecccaa1e11be23f53e3198af6933c9f60 (diff)
downloadkmi-8a5e4cf53d981e793fca90d9b51bd395265cf4db.tar.gz
kmi-8a5e4cf53d981e793fca90d9b51bd395265cf4db.zip
add req_page syscall
-rwxr-xr-xarch/riscv64/conf/initbin6072 -> 3600 bytes
-rw-r--r--arch/riscv64/conf/initrdbin6656 -> 4096 bytes
-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
-rw-r--r--include/apos/mem.h8
-rw-r--r--include/apos/syscalls.h3
-rw-r--r--include/apos/types.h1
-rw-r--r--include/apos/uapi.h26
-rw-r--r--include/apos/vmem.h13
11 files changed, 110 insertions, 0 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index b24a661..c77c048 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd
index 35cf825..fb6f525 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
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);
diff --git a/include/apos/mem.h b/include/apos/mem.h
index 4db7a67..ea61aba 100644
--- a/include/apos/mem.h
+++ b/include/apos/mem.h
@@ -196,6 +196,14 @@ extern size_t __mm_page_shift;
extern enum mm_order __mm_max_order;
/**
+ * Find nearest order to size.
+ *
+ * @param size Size to map to an order.
+ * @return Nearest order larger than \p size.
+ */
+enum mm_order nearest_order(size_t size);
+
+/**
* Initialize memory subsystem data. Populates __mm_* with data given.
*
* @param max_order Maximum order the current system supports.
diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h
index 611765d..40e6504 100644
--- a/include/apos/syscalls.h
+++ b/include/apos/syscalls.h
@@ -38,6 +38,9 @@ enum {
/** Request memory from anywhere. */
SYS_REQ_MEM,
+ /** Request physical page from ram. */
+ SYS_REQ_PAGE,
+
/** Request memory with physical address. */
SYS_REQ_PMEM,
diff --git a/include/apos/types.h b/include/apos/types.h
index 431d551..36e918e 100644
--- a/include/apos/types.h
+++ b/include/apos/types.h
@@ -445,6 +445,7 @@ typedef int_fast8_t stat_t;
* is with pids */
typedef int_fast32_t id_t;
+/** Maximum ID number. */
#define ID_MAX INT_FAST32_MAX
/** Memory region flags. */
diff --git a/include/apos/uapi.h b/include/apos/uapi.h
index dda4391..fefd1bf 100644
--- a/include/apos/uapi.h
+++ b/include/apos/uapi.h
@@ -320,6 +320,32 @@ SYSCALL_DECLARE1(putch, ch);
SYSCALL_DECLARE2(req_mem, size, flags);
/**
+ * Request one page of memory. The nearest fitting size is chosen.
+ *
+ * This might be better implemented as some number of adjacent physical pages,
+ * but the underlying physical page allocator doesn't really handle it very
+ * well. This weird design decision is because I don't know if there are devices
+ * whose drivers need multiple adjacent physical pages, only that at least
+ * virtio devices need to be able to access the physical address of a single
+ * page. Basic adjacent physical pages can be made from higher order pages,
+ * just with a massive overhead. Still, probably good eough for now.
+ *
+ * For example, if you need two adjacent 4K pages, you pass size = 8K and you
+ * get back a 2M page, if one is available.
+ *
+ * @param t Current tcb.
+ * @param size Required size of region.
+ * @param flags Mapping flags to use.
+ * @param c Unused.
+ * @param d Unused.
+ * @param e Unused.
+ *
+ * Returns \ref ERR_OOMEM if no page is available, otherwise \c OK, virtual
+ * address, actual size, physical size in that order.
+ */
+SYSCALL_DECLARE2(req_page, size, flags);
+
+/**
* Request physical memory syscall.
*
* Allocates at least the specified size of allocation which includes the
diff --git a/include/apos/vmem.h b/include/apos/vmem.h
index 38bad16..5cbe7db 100644
--- a/include/apos/vmem.h
+++ b/include/apos/vmem.h
@@ -28,6 +28,19 @@
vm_t alloc_uvmem(struct tcb *r, size_t size, vmflags_t flags);
/**
+ * Allocate one physical page for user virtual memory.
+ *
+ * @param r Process to allocate memory in.
+ * @param size Minimum size of allocation.
+ * @param flags Flags of allocation.
+ * @param asize Where to write actual size of allocation.
+ * @param paddr Where to write physical address of page.
+ * @return Start of allocation when succesful, \c NULL otherwise.
+ */
+vm_t alloc_uvpage(struct tcb *r, size_t size, vmflags_t flags,
+ size_t *asize, pm_t *paddr);
+
+/**
* Allocate fixed user virtual memory.
*
* Virtual memory start address is chosen so that \c start is within the