From 5890df7bf838a5a912465a1bba02e5d8cf34e33c Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 2 Nov 2024 18:58:13 +0200 Subject: allow skipping some cache flushes in proc --- arch/riscv64/include/tcb.h | 3 ++ arch/riscv64/kernel/proc.c | 58 ++++++++++++++++++++++++++------- arch/riscv64/kernel/pte.h | 78 ++++++++++++++++++++++++++++++++++++++++++++ arch/riscv64/kernel/vmem.c | 81 +++------------------------------------------- 4 files changed, 131 insertions(+), 89 deletions(-) create mode 100644 arch/riscv64/kernel/pte.h (limited to 'arch') diff --git a/arch/riscv64/include/tcb.h b/arch/riscv64/include/tcb.h index f0cce37..b3baf46 100644 --- a/arch/riscv64/include/tcb.h +++ b/arch/riscv64/include/tcb.h @@ -19,6 +19,9 @@ struct arch_tcbd { /** RPC stack page table leaf node. */ struct vmem *rpc_leaf; + /** O1 page that contains the whole stack */ + pm_t rpc_page; + /** Index into \p rpc_leaf with the lowest accessed page so far in a * certain context. */ int rpc_idx; diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c index ba5c8e7..9dd34a0 100644 --- a/arch/riscv64/kernel/proc.c +++ b/arch/riscv64/kernel/proc.c @@ -15,6 +15,7 @@ #include #include "regs.h" +#include "pte.h" #include "csr.h" /** Assembly implementation for actually jumping to the init process, defined in @@ -58,9 +59,35 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) unreachable(); } -void set_ret(struct tcb *t, size_t n, struct sys_ret a) +/** + * Safely calculate where t->regs actually is, so we can access the rpc stack + * even without being in the same address space. Allows us to avoid doing some + * cache flushes in src/uapi/proc.c. + * + * @param t Thread whose registers we want to access. + * @return The physical address of the current registers. + */ +static __inline pm_t __physical_regs(struct tcb *t) +{ + pm_t offset = (vm_t)t->regs - RPC_STACK_BASE; + return t->arch.rpc_page + offset; +} + +void set_ret_fast(struct tcb *t, struct sys_ret a) { struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1; + r->a0 = a.s; + r->a1 = a.id; + r->a2 = a.a0; + r->a3 = a.a1; + r->a4 = a.a2; + r->a5 = a.a3; +} + +void set_ret(struct tcb *t, size_t n, struct sys_ret a) +{ + pm_t regs = __physical_regs(t); + struct riscv_regs *r = (struct riscv_regs *)(regs) - 1; if (n >= 1) r->a0 = a.s; if (n >= 2) r->a1 = a.id; if (n >= 3) r->a2 = a.a0; @@ -71,15 +98,17 @@ void set_ret(struct tcb *t, size_t n, struct sys_ret a) struct sys_ret get_ret(struct tcb *t) { - struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1; + pm_t regs = __physical_regs(t); + struct riscv_regs *r = (struct riscv_regs *)(regs) - 1; return SYS_RET6(r->a0, r->a1, r->a2, r->a3, r->a4, r->a5); } void set_thread(struct tcb *t) { + pm_t regs = __physical_regs(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->regs) - 1; + struct riscv_regs *r = (struct riscv_regs *)(regs) - 1; /* insert important values into register slots */ r->sp = (long)t->rpc_stack - BASE_PAGE_SIZE; @@ -88,27 +117,32 @@ void set_thread(struct tcb *t) void set_stack(struct tcb *t, vm_t s) { /** @todo also set frame pointer on architectures that need it? */ + pm_t regs = __physical_regs(t); + struct riscv_regs *r = (struct riscv_regs *)(regs) - 1; + r->sp = s; +} + +void set_stack_fast(struct tcb *t, vm_t s) +{ 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; + pm_t regs = __physical_regs(t); + struct riscv_regs *r = (struct riscv_regs *)(regs) - 1; return r->sp; } void copy_regs(struct tcb *d, struct tcb *s) { - struct riscv_regs rs = *((struct riscv_regs *)(s->regs) - 1); - /* again, not a fan of this, I guess we could query the underlying - * physical page? Would that be any faster? */ - use_vmem(d->rpc.vmem); - - struct riscv_regs *rd = ((struct riscv_regs *)(d->regs) - 1); - *rd = rs; + pm_t rgs = __physical_regs(s); + pm_t rgd = __physical_regs(d); - use_vmem(s->rpc.vmem); + struct riscv_regs *rs = (struct riscv_regs *)(rgs) - 1; + struct riscv_regs *rd = (struct riscv_regs *)(rgd) - 1; + *rd = *rs; } void adjust_ipi(struct tcb *t) diff --git a/arch/riscv64/kernel/pte.h b/arch/riscv64/kernel/pte.h new file mode 100644 index 0000000..03c3d05 --- /dev/null +++ b/arch/riscv64/kernel/pte.h @@ -0,0 +1,78 @@ +#ifndef KMI_RISCV_PTE_H +#define KMI_RISCV_PTE_H + +/** + * Get page table entry physical page number. + * + * @param pte Page table entry. + * @return Corresponding physical page number. + */ +#define pte_ppn(pte) (((pm_t)(pte)) >> 10) + +/** + * Get page table entry flags. + * + * @param pte Page table entry. + * @return Corresponding flags. + */ +#define pte_flags(pte) (((pm_t)(pte)) & 0xff) + +/** + * Convert physical memory address to page table entry. + * + * @param p Physical memory address. + * @param f Flags to use. + * @return Corresponding page table entry. + */ +#define to_pte(p, f) ((((p) >> page_shift()) << 10) | (f)) + +/** + * Get physical address in page table entry. + * + * @param pte Page table entry. + * @return Corresponding physical address. + */ +#define pte_paddr(pte) (pte_ppn(pte) << page_shift()) + +/** + * Get virtual address in page table entry. + * + * @param pte Page table entry. + * @return Corresponding virtual address. + */ +#define pte_addr(pte) __va(pte_paddr(pte)) + +/** + * Virtual memory address to page order index. + * + * @param a Virtual address. + * @param o Order of page. + * @return Corresponding page index. + */ +#define vm_to_index(a, o) (pm_to_index(a, o)) + +/** + * Check if page table entry is active. + * + * @param pte Page table entry. + * @return \c 0 if entry is not active, non-zero otherwise. + */ +#define is_active(pte) (pte_flags(pte) &VM_V) + +/** + * Check if page table entry is a leaf. + * + * @param pte Page table entry. + * @return \c 0 if entry is not leaf, non-zero otherwise. + */ +#define is_leaf(pte) (is_active(pte) && (pte_flags(pte) & ~VM_V)) + +/** + * Check if page table entry is a branch. + * + * @param pte Page table entry. + * @return \c 0 if entry is not branch, non-zero otherwise. + */ +#define is_branch(pte) (is_active(pte) && !(pte_flags(pte) & ~VM_V)) + +#endif /* KMI_RISCV_PTE_H */ diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 1b70493..2a08854 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -16,82 +16,9 @@ #include #include "pages.h" #include "arch.h" +#include "pte.h" #include "csr.h" -/** - * Get page table entry physical page number. - * - * @param pte Page table entry. - * @return Corresponding physical page number. - */ -#define pte_ppn(pte) (((pm_t)(pte)) >> 10) - -/** - * Get page table entry flags. - * - * @param pte Page table entry. - * @return Corresponding flags. - */ -#define pte_flags(pte) (((pm_t)(pte)) & 0xff) - -/** - * Convert physical memory address to page table entry. - * - * @param p Physical memory address. - * @param f Flags to use. - * @return Corresponding page table entry. - */ -#define to_pte(p, f) ((((p) >> page_shift()) << 10) | (f)) - -/** - * Get physical address in page table entry. - * - * @param pte Page table entry. - * @return Corresponding physical address. - */ -#define pte_paddr(pte) (pte_ppn(pte) << page_shift()) - -/** - * Get virtual address in page table entry. - * - * @param pte Page table entry. - * @return Corresponding virtual address. - */ -#define pte_addr(pte) __va(pte_paddr(pte)) - -/** - * Virtual memory address to page order index. - * - * @param a Virtual address. - * @param o Order of page. - * @return Corresponding page index. - */ -#define vm_to_index(a, o) (pm_to_index(a, o)) - -/** - * Check if page table entry is active. - * - * @param pte Page table entry. - * @return \c 0 if entry is not active, non-zero otherwise. - */ -#define is_active(pte) (pte_flags(pte) &VM_V) - -/** - * Check if page table entry is a leaf. - * - * @param pte Page table entry. - * @return \c 0 if entry is not leaf, non-zero otherwise. - */ -#define is_leaf(pte) (is_active(pte) && (pte_flags(pte) & ~VM_V)) - -/** - * Check if page table entry is a branch. - * - * @param pte Page table entry. - * @return \c 0 if entry is not branch, non-zero otherwise. - */ -#define is_branch(pte) (is_active(pte) && !(pte_flags(pte) & ~VM_V)) - /** * Gravestone marker. * @@ -607,6 +534,8 @@ stat_t setup_rpc_stack(struct tcb *t) if (!page) return ERR_OOMEM; + t->arch.rpc_page = page; + if (map_vpage(t->rpc.vmem, page, RPC_STACK_BASE, flags, BASE_PAGE)) { free_page(MM_O1, page); return ERR_OOMEM; @@ -636,9 +565,7 @@ stat_t setup_rpc_stack(struct tcb *t) void destroy_rpc_stack(struct tcb *t) { - pm_t *pte = (pm_t *)t->arch.rpc_leaf; - pm_t page = (pm_t)pte_addr(*pte); - free_page(MM_O1, page); + free_page(MM_O1, t->arch.rpc_page); } void reset_rpc_stack(struct tcb *t) -- cgit v1.3