aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-12-01 02:05:19 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-12-01 02:05:19 +0200
commit131af4eec38752a27e6e56579fbf76178e022ec1 (patch)
tree1940634f69a44395fc6945b25c5cbc8b68bba876
parente25f1e7a8f8f2320546ad4950464713d85b47785 (diff)
downloadkmi-131af4eec38752a27e6e56579fbf76178e022ec1.tar.gz
kmi-131af4eec38752a27e6e56579fbf76178e022ec1.zip
start looking into memory handling
+ Now 10M alloc/frees succeed, which totals more memory than the virtual machine has, so no too obvious leaks are occuring. For future debugging speed, changed 10M to 1M. + Also quick fix to rpcs, stacks are now assigned. Not entirely sure why they worked before this, but good that I found it.
-rwxr-xr-xarch/riscv64/conf/initbin2720 -> 5088 bytes
-rw-r--r--arch/riscv64/conf/init.c31
-rw-r--r--arch/riscv64/conf/initrdbin3072 -> 5632 bytes
-rw-r--r--arch/riscv64/kernel/proc.c7
-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
-rw-r--r--include/apos/syscalls.h3
-rw-r--r--include/apos/tcb.h5
-rw-r--r--include/apos/uapi.h8
-rw-r--r--include/arch/proc.h9
13 files changed, 90 insertions, 53 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index eba8186..0d99b80 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c
index de9814e..4cd4cea 100644
--- a/arch/riscv64/conf/init.c
+++ b/arch/riscv64/conf/init.c
@@ -18,6 +18,7 @@
*/
#include <stdint.h>
+#include <stddef.h>
#include "../../../include/apos/syscalls.h"
struct sys_ret {
@@ -184,6 +185,27 @@ static void sys_poweroff(long type)
ecall(r);
}
+static void *sys_req_mem(size_t count)
+{
+ struct sys_ret r = {.a0 = SYS_REQ_MEM, .a1 = count,
+ .a2 = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4)};
+ r = ecall(r);
+
+ if (r.a0)
+ print_value("sys_req_mem() failed with error ", r.a0);
+
+ return (void *)r.a1;
+}
+
+static void sys_free_mem(void *p)
+{
+ struct sys_ret r = {.a0 = SYS_FREE_MEM, .a1 = (long)p};
+ r = ecall(r);
+
+ if (r.a0)
+ print_value("sys_free_mem() failed with error ", r.a0);
+}
+
void callback(long status, long tid, long d0, long d1, long d2, long d3)
{
(void)status;
@@ -244,12 +266,19 @@ void _start()
csr_read(CSR_TIME, i);
start = i; n = 0;
while (i < start + second) {
- sys_ipc_req(1, d0, d1, d2, d3);
+ sys_ipc_req(1, n, d1, d2, d3);
csr_read(CSR_TIME, i);
n++;
}
print_value("IPC requests per second", n);
+ puts("Doing memory allocations...\n");
+ for (i = 0; i < 1000000; ++i) {
+ char *p = sys_req_mem(10);
+ *p = 'c';
+ sys_free_mem(p);
+ }
+
sys_poweroff(0);
}
diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd
index 905bbfe..8d36a5a 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index 0f19789..d58b41b 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -63,6 +63,13 @@ void set_thread(struct tcb *t)
r->tp = (long)t->thread_storage;
}
+void set_stack(struct tcb *t, vm_t s)
+{
+ /** @todo also set frame pointer on architectures that need it? */
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
+ r->sp = s;
+}
+
vm_t get_stack(struct tcb *t)
{
struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
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,
diff --git a/include/apos/syscalls.h b/include/apos/syscalls.h
index a5c805d..611765d 100644
--- a/include/apos/syscalls.h
+++ b/include/apos/syscalls.h
@@ -44,6 +44,9 @@ enum {
/** Request memory at fixed virtual address. */
SYS_REQ_FIXMEM,
+ /** Request shared memory. */
+ SYS_REQ_SHAREDMEM,
+
/** Free memory. */
SYS_FREE_MEM,
/** @} */
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index c56a2b3..9f10e2f 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -391,17 +391,18 @@ bool running(struct tcb *t);
/**
* Save thread context for rpc call.
+ * Assumes t->rpc is pointing to the correct virtual memory.
*
* @param t Thread whose context to save.
*/
-void save_context(struct tcb *t);
+void enter_rpc(struct tcb *t);
/**
* Load thread context from rpc call.
*
* @param t Thread whose context to restore.
*/
-void load_context(struct tcb *t);
+void leave_rpc(struct tcb *t);
/**
* Check that we have enough rpc stack.
diff --git a/include/apos/uapi.h b/include/apos/uapi.h
index 2a0dfcc..7bd00bb 100644
--- a/include/apos/uapi.h
+++ b/include/apos/uapi.h
@@ -363,15 +363,15 @@ SYSCALL_DECLARE3(req_fixmem, start, size, flags);
* (server) frees it.
*
* @param t Current tcb.
+ * @param tid Thread to share memory with.
* @param size Size of allocation.
- * @param flags Flags of allocation.
- * @param c Unused.
- * @param d Unused.
+ * @param sflags Flags of allocation for server, that is \p t.
+ * @param cflags Flags of allocation for client, that is \p tid.
* @param e Unused.
*
* Returns \ref OK and start of memory allocation.
*/
-SYSCALL_DECLARE2(req_sharedmem, size, flags);
+SYSCALL_DECLARE4(req_sharedmem, tid, size, sflags, cflags);
/**
* Reference shared memory syscall.
diff --git a/include/arch/proc.h b/include/arch/proc.h
index 6a2c036..84954c0 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -49,6 +49,15 @@ struct sys_ret get_args(struct tcb *t);
void set_thread(struct tcb *t);
/**
+ * Set userspace stack. I think \ref set_thread() could be replaced with this,
+ * and it's more useful.
+ *
+ * @param t Thread whose stack to set.
+ * @param s Stack to give to thread.
+ */
+void set_stack(struct tcb *t, vm_t s);
+
+/**
* Get current userspace stack.
*
* @param t Thread whose stack to query.