diff options
| -rw-r--r-- | arch/riscv64/asm/asm-offsets.c | 5 | ||||
| -rw-r--r-- | arch/riscv64/include/tcb.h | 1 | ||||
| -rw-r--r-- | arch/riscv64/kernel/entry.S | 19 | ||||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 20 | ||||
| -rw-r--r-- | common/tcb.c | 20 | ||||
| -rw-r--r-- | include/apos/tcb.h | 2 |
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; |
