aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-11-13 06:11:43 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-11-13 06:11:43 +0200
commit6d3586aa42409fc720e30856cb5df5284329463a (patch)
tree571136fdb4f6fb333c1bb4b1274a76eb70263de9
parent7da8912c0eee10315dac37cecd4c84f11e5dad59 (diff)
downloadkmi-6d3586aa42409fc720e30856cb5df5284329463a.tar.gz
kmi-6d3586aa42409fc720e30856cb5df5284329463a.zip
~700k ipc requests
+ Eliminated need for save/load_regs, now the register save area is behind a pointer which _slightly_ increases overall syscall delay, but speeds up ipc requests by a fair bit.
-rw-r--r--arch/riscv64/asm/asm-offsets.c5
-rw-r--r--arch/riscv64/include/tcb.h1
-rw-r--r--arch/riscv64/kernel/entry.S19
-rw-r--r--arch/riscv64/kernel/proc.c20
-rw-r--r--common/tcb.c20
-rw-r--r--include/apos/tcb.h2
6 files changed, 39 insertions, 28 deletions
diff --git a/arch/riscv64/asm/asm-offsets.c b/arch/riscv64/asm/asm-offsets.c
index 3619765..1239489 100644
--- a/arch/riscv64/asm/asm-offsets.c
+++ b/arch/riscv64/asm/asm-offsets.c
@@ -83,4 +83,9 @@ void asm_offsets()
OFFSETOF(ar3, struct sys_ret);
OFFSETOF(ar4, struct sys_ret);
SIZEOF(sys_ret, struct sys_ret);
+
+ OFFSETOF(exec, struct tcb);
+ OFFSETOF(regs, struct tcb);
+ OFFSETOF(tcbd, struct tcb);
+ SIZEOF(tcb, struct tcb);
}
diff --git a/arch/riscv64/include/tcb.h b/arch/riscv64/include/tcb.h
index ed2fd71..829ce6a 100644
--- a/arch/riscv64/include/tcb.h
+++ b/arch/riscv64/include/tcb.h
@@ -16,6 +16,7 @@
* saving of something
*/
struct arch_tcbd {
+ long scratch;
};
#endif /* ARCH_RISCV_TCB_H */
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
index 355cd3d..f099065 100644
--- a/arch/riscv64/kernel/entry.S
+++ b/arch/riscv64/kernel/entry.S
@@ -23,13 +23,9 @@ handle_irq:
* now just spin in place */
1: j 1b
_save_context:
- /* store user stack pointer and replace it with kernel stack */
- addi tp, tp,-sizeof_registers
- sr sp, offsetof_sp(tp)
- mv sp, tp
-
- /* move thread pointer back */
- addi tp, tp, sizeof_registers
+ sr sp, offsetof_tcbd(tp)
+ lr sp, offsetof_regs(tp)
+ addi sp, sp, -sizeof_registers
csrrw tp, CSR_SSCRATCH, tp
/* save registers */
@@ -67,6 +63,9 @@ _save_context:
/* get current tcb into tp and set scratch to 0 so we can figure out if
* exception occured in kernel or userspace */
csrrw tp, CSR_SSCRATCH, x0
+ lr s0, offsetof_tcbd(tp)
+ sr s0, offsetof_sp(sp)
+ addi sp, tp, -sizeof_registers
/* load supervisor cause */
csrr s4, CSR_SCAUSE
@@ -85,7 +84,7 @@ handle_exception:
handle_dispatch:
/* store execution continuation point */
csrr s0, CSR_SEPC
- sr s0, 0(tp)
+ sr s0, offsetof_exec(tp)
/* allocate space for sys_ret structure on stack and shift argument
* registers down one to make room for the pointer to this structure */
addi sp, sp, -sizeof_sys_ret
@@ -109,10 +108,10 @@ handle_dispatch:
/* if we had a thread switch, load kernel stack of current thread and
* restore its context */
/* get associated kernel stack */
- mv sp, tp
+ lr sp, offsetof_regs(tp)
addi sp, sp, -sizeof_registers
/* set execution continuation */
- lr s0, 0(tp)
+ lr s0, offsetof_exec(tp)
csrw CSR_SEPC, s0
/* restore system call result */
j restore_noreturn
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index b8f6c5d..4180bf8 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -30,7 +30,7 @@ void run_init(struct tcb *t, void *fdt)
void set_args(struct tcb *t, struct sys_ret a)
{
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
r->a0 = a.s;
r->a1 = a.ar0;
r->a2 = a.ar1;
@@ -41,7 +41,7 @@ void set_args(struct tcb *t, struct sys_ret a)
struct sys_ret get_args(struct tcb *t)
{
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
return SYS_RET6(r->a0, r->a1, r->a2, r->a3, r->a4, r->a5);
}
@@ -49,7 +49,7 @@ void set_thread(struct tcb *t)
{
/* get location of registers in memory */
/** \todo check alignment, should be fine but just to be sure */
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
/* insert important values into register slots */
r->sp = (long)t->thread_stack_top;
@@ -58,28 +58,28 @@ void set_thread(struct tcb *t)
vm_t get_stack(struct tcb *t)
{
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
return r->sp;
}
void save_regs(struct tcb *t, void *p)
{
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
- struct riscv_regs *rp = (struct riscv_regs *)(p);
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
+ struct riscv_regs *rp = (struct riscv_regs *)(p) - 1;
*rp = *r;
}
void load_regs(void *p, struct tcb *t)
{
- struct riscv_regs *r = (struct riscv_regs *)(t) - 1;
- struct riscv_regs *rp = (struct riscv_regs *)(p);
+ struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
+ struct riscv_regs *rp = (struct riscv_regs *)(p) - 1;
*r = *rp;
}
void clone_regs(struct tcb *d, struct tcb *s)
{
- struct riscv_regs *rd = (struct riscv_regs *)(d) - 1;
- struct riscv_regs *rs = (struct riscv_regs *)(s) - 1;
+ struct riscv_regs *rd = (struct riscv_regs *)(d->regs) - 1;
+ struct riscv_regs *rs = (struct riscv_regs *)(s->regs) - 1;
*rd = *rs;
}
diff --git a/common/tcb.c b/common/tcb.c
index 478bd05..f774fbc 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -163,6 +163,8 @@ struct tcb *create_thread(struct tcb *p)
t->rpc.vmem = create_vmem();
__setup_rpc_stack(t, __call_stack_size);
+ t->regs = (vm_t)t;
+
set_canary(t);
return t;
}
@@ -180,7 +182,6 @@ static stat_t __copy_proc(struct tcb *p, struct tcb *n)
/** @todo I think keeping track of userspace stack stuff is unnecessary,
* unless we want unlimited stack size but that sounds dumb. Anycase, we
* need to duplicate stack info, whatever we do. */
- /** @todo should there be in-kernel child tracking? */
n->exec = p->exec;
n->callback = p->callback;
n->thread_stack = p->thread_stack;
@@ -409,6 +410,7 @@ static void mark_rpc_accessible(struct tcb *t, vm_t start, vm_t end)
struct call_ctx {
vm_t exec;
+ vm_t regs;
vm_t rpc_stack;
id_t eid, pid;
};
@@ -420,27 +422,29 @@ void save_context(struct tcb *t)
/** @todo what if user uses their own stack? */
rpc_stack = align_down(get_stack(t), BASE_PAGE_SIZE);
- rpc_stack -= BASE_PAGE_SIZE;
- struct call_ctx *ctx = (struct call_ctx *)rpc_stack;
+ struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
ctx->exec = t->exec;
ctx->pid = t->pid;
ctx->eid = t->eid;
- ctx->rpc_stack = rpc_stack + BASE_PAGE_SIZE;
- save_regs(t, ctx + 1);
+ ctx->regs = t->regs;
+ ctx->rpc_stack = rpc_stack;
+
+ rpc_stack -= BASE_PAGE_SIZE;
mark_rpc_inaccessible(t, rpc_stack, t->rpc_stack);
t->rpc_stack = rpc_stack;
+ t->regs = (vm_t)ctx;
}
void load_context(struct tcb *t)
{
- vm_t rpc_stack = t->rpc_stack;
- struct call_ctx *ctx = (struct call_ctx *)rpc_stack;
+ vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
+ struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
set_return(t, ctx->exec);
mark_rpc_accessible(t, t->rpc_stack, ctx->rpc_stack);
- load_regs(ctx + 1, t);
t->rpc_stack = ctx->rpc_stack;
t->pid = ctx->pid;
t->eid = ctx->eid;
+ t->regs = ctx->regs;
}
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index 9ed916f..23e6451 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -78,6 +78,8 @@ struct tcb {
/** Execution continuation point. Important that it is first. */
vm_t exec;
+ vm_t regs;
+
/** Arch-specific data. */
struct arch_tcbd tcbd;