diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-11-02 18:58:13 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-11-02 18:58:13 +0200 |
| commit | 5890df7bf838a5a912465a1bba02e5d8cf34e33c (patch) | |
| tree | 48c17acfc5ed2b44bff817b00123288098273ecc /arch | |
| parent | 5531e2eaaa2fd1dd282dba2fb5bc10e09dfec5e0 (diff) | |
| download | kmi-5890df7bf838a5a912465a1bba02e5d8cf34e33c.tar.gz kmi-5890df7bf838a5a912465a1bba02e5d8cf34e33c.zip | |
allow skipping some cache flushes in proc
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/riscv64/include/tcb.h | 3 | ||||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 58 | ||||
| -rw-r--r-- | arch/riscv64/kernel/pte.h | 78 | ||||
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 81 |
4 files changed, 131 insertions, 89 deletions
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 <arch/proc.h> #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,83 +16,10 @@ #include <arch/cpu.h> #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. * * Riscv allows us to have arbitrary data in page entries, as long as they're @@ -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) |
