aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/kernel/vmem.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-07-07 07:00:43 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-07-07 07:00:43 +0300
commit122374c362ba8bb9082385da3c82e264ab594f15 (patch)
tree0123fad5464aaf64f522d48f5069b35b90207aae /arch/riscv64/kernel/vmem.c
parent03e12129927b0deba537a11bb5575bef93c57d0f (diff)
downloadkmi-122374c362ba8bb9082385da3c82e264ab594f15.tar.gz
kmi-122374c362ba8bb9082385da3c82e264ab594f15.zip
smp now seems to work
+ Had some minor issues with a wraparound of size_t that effectively meant that some regions were allocated twice. Also, booting should be a bit more reliable now, turned out that the previous iteration of the booting was just accidentally working due to the kernel being placed 'close enough' in RAM to where it was linked to. Fixed by allocating a vmem of O1 that maps the kernel to a 2MiB boundary at boot, pretty nifty.
Diffstat (limited to 'arch/riscv64/kernel/vmem.c')
-rw-r--r--arch/riscv64/kernel/vmem.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index 97b9cce..68869a3 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -416,14 +416,19 @@ long riscv_init_stack[4096 / sizeof(long)];
* and so the kernel itself has to be on a 4K boundary. */
__aligned(4096) struct vmem bootvmem;
-struct vmem *direct_mapping()
+/** Page entry for mapping kernel on a O1 page level, similar to how Linux does
+ * it. */
+__aligned(4096) struct vmem kvmem;
+
+struct vmem *init_mapping()
{
rpc_pages = order_size(MM_O1) / BASE_PAGE_SIZE;
+ kvmem.leaf[0] = (struct vmem *)to_pte(get_load_addr(),
+ VM_A | VM_G | VM_D | VM_R | VM_W | VM_X | VM_V);
__populate_dmap(&bootvmem);
populate_kvmem(&bootvmem);
__use_vmem(&bootvmem, DEFAULT_Sv_MODE);
-
return &bootvmem;
}
@@ -456,16 +461,31 @@ void destroy_vmem(struct vmem *b)
__destroy_branch(b);
}
+static void map_kernel(struct vmem *b)
+{
+ intptr_t addr = (pm_t)&kvmem;
+
+ /* virtual memory is negative, unsure if this applies everywhere but I
+ * guess it's good enough for us */
+ if (addr < 0)
+ addr = addr - VM_KERNEL + get_load_addr();
+
+ b->leaf[KERNEL_PAGE] = (struct vmem *)to_pte((pm_t)addr, VM_V);
+}
+
stat_t populate_kvmem(struct vmem *b)
{
size_t flags = VM_V | VM_R | VM_W | VM_X | VM_G | VM_D | VM_A;
- for (size_t i = KSTART_PAGE; i < IO_PAGE; ++i)
+ for (size_t i = KSTART_PAGE; i < KERNEL_PAGE; ++i)
b->leaf[i] = (struct vmem *)to_pte(
- get_ram_base() + TOP_PAGE_SIZE * (i - KSTART_PAGE),
+ TOP_PAGE_SIZE * (i - KSTART_PAGE),
flags);
- /* map in IO region */
+ /* map in IO region if debugging is specified */
map_io_dbg(b);
+
+ /* map actual kernel */
+ map_kernel(b);
return OK;
}