diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-11-01 04:44:50 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-11-01 10:28:11 +0200 |
| commit | 9914b44878ca52cc615d2f4e47fec400dd55ab76 (patch) | |
| tree | 7678216d4049fa5d2a4a9e381daa4d34dc317c22 /arch/riscv64 | |
| parent | 89e162f3916de5a4faef5bd626590d004bdcdc39 (diff) | |
| download | kmi-9914b44878ca52cc615d2f4e47fec400dd55ab76.tar.gz kmi-9914b44878ca52cc615d2f4e47fec400dd55ab76.zip | |
test all ipc variants more-or-less properly
Diffstat (limited to 'arch/riscv64')
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 71 |
1 files changed, 47 insertions, 24 deletions
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index fa3c1c2..4986c1f 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -623,7 +623,7 @@ stat_t setup_rpc_stack(struct tcb *t) NULL); /* we count downward in base pages, the top page is *always* reserved */ t->arch.rpc_idx = rpc_pages - 1; - + /** @todo we could mark the first stack page accessible here already */ /* point registers to stack */ t->regs = t->rpc_stack - sizeof(struct call_ctx); @@ -672,62 +672,85 @@ bool in_rpc_stack(struct tcb *t, vm_t addr) && addr < RPC_STACK_BASE + BASE_PAGE_SIZE * t->arch.rpc_idx; } -void close_rpc(struct tcb *t) +void reuse_rpc(struct tcb *t) { struct vmem *b = t->arch.rpc_leaf; int top_idx = t->arch.rpc_idx; - /* absolute max iter count */ - for (; top_idx < (int)rpc_pages; --top_idx) { - /* mark inaccessible until we reach the first inaccessible - * region */ + const int max = rpc_pages - 1; + for (; top_idx < max; --top_idx) { pm_t *pte = (pm_t *)&b->leaf[top_idx]; if (!(pte_flags(*pte) & VM_U)) break; - /* make page not accessible from userspace */ clear_bits(*pte, vp_flags(VM_U)); } - /* make page following closed region accessible so we can avoid an - * unnecessary page fault */ - pm_t *pte = (pm_t *)&b->leaf[top_idx]; + /* top_idx is our 'current' kernel region, so mark page following it + * user accessible to avoid page fault on entry */ + t->arch.rpc_idx = top_idx + 1; + pm_t *pte = (pm_t *)&b->leaf[t->arch.rpc_idx]; set_bits(*pte, vp_flags(VM_U)); - t->arch.rpc_idx = top_idx; } -void shrink_rpc(struct tcb *t) +void new_rpc(struct tcb *t) { struct vmem *b = t->arch.rpc_leaf; int top_idx = t->arch.rpc_idx; - for (; top_idx > 0; ++top_idx) { + int max = rpc_pages - 1; + for (; top_idx < max; --top_idx) { + /* mark inaccessible until we reach the first inaccessible + * region, which must be our previous kernel data region */ pm_t *pte = (pm_t *)&b->leaf[top_idx]; if (!(pte_flags(*pte) & VM_U)) break; + /* make page not accessible from userspace */ clear_bits(*pte, vp_flags(VM_U)); } - t->arch.rpc_idx = top_idx; + /* kernel region, skip */ + t->arch.rpc_idx--; + + /* user stack start, mark accessible to avoid pagefault on entry */ + t->arch.rpc_idx--; + pm_t *pte = (pm_t *)&b->leaf[t->arch.rpc_idx]; + set_bits(*pte, vp_flags(VM_U)); } -void open_rpc(struct tcb *t, vm_t top) +void destroy_rpc(struct tcb *t) { - assert(is_aligned(top, BASE_PAGE_SIZE)); struct vmem *b = t->arch.rpc_leaf; - int old_idx = t->arch.rpc_idx; - int new_idx = (top - RPC_STACK_BASE) / BASE_PAGE_SIZE; - assert(new_idx >= old_idx); + int top_idx = t->arch.rpc_idx; - /* always stop one before the page index indicated, might be kind of - * easy to mess up */ - for (int i = old_idx; i < new_idx - 1; ++i) { - pm_t *pte = (pm_t *)&b->leaf[i]; + /* first, mark all 'current' accessible pages unaccessible */ + int max = rpc_pages - 1; + for (; top_idx < max; ++top_idx) { + /* mark inaccessible until we reach the first inaccessible + * region, which must be our previous kernel data region */ + pm_t *pte = (pm_t *)&b->leaf[top_idx]; + if (!(pte_flags(*pte) & VM_U)) + break; + + /* make page not accessible from userspace */ + clear_bits(*pte, vp_flags(VM_U)); + } + + /* current kernel data region, skip */ + top_idx++; + + int ctx = (t->rpc_stack - RPC_STACK_BASE) / BASE_PAGE_SIZE; + + /* now mark previous rpc user region accessible again */ + /* prev_ctx is page where our kernel context is, so we need to stop one + * before it */ + for (; top_idx < ctx - 1; ++top_idx) { + pm_t *pte = (pm_t *)&b->leaf[top_idx]; set_bits(*pte, vp_flags(VM_U)); } - t->arch.rpc_idx = new_idx - 1; + t->arch.rpc_idx = ctx - 1; } void grow_rpc(struct tcb *t, vm_t top) |
