aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv/init
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2021-08-25 23:47:08 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2021-08-25 23:47:08 +0300
commit5dfac4879ce5f34503ae7537eefd3fc48d6fa750 (patch)
tree7ac25f1a14373ae08ea6aa2406d8f83026dba74a /arch/riscv/init
parentb235f49f31d11e68019c42f48b6641c37e4c986e (diff)
downloadkmi-5dfac4879ce5f34503ae7537eefd3fc48d6fa750.tar.gz
kmi-5dfac4879ce5f34503ae7537eefd3fc48d6fa750.zip
libfdt seems to work
At least as far as reading memory info, cool. One issue I have is that .(ro)data is apparently accessed by absolute addresses, so I need to know at which address the kernel is going to be loaded. I would prefer completely position independent code, but if that's not possible then eh.
Diffstat (limited to 'arch/riscv/init')
-rw-r--r--arch/riscv/init/head.S5
-rw-r--r--arch/riscv/init/init.c130
2 files changed, 32 insertions, 103 deletions
diff --git a/arch/riscv/init/head.S b/arch/riscv/init/head.S
index 703d265..bbd2945 100644
--- a/arch/riscv/init/head.S
+++ b/arch/riscv/init/head.S
@@ -2,9 +2,6 @@
.global _start
.type _start, @function
_start:
- /* store kernel load address */
- auipc a4, 0
- /* stack grows downward */
- mv sp, a4
+ /* stack pointer is whatever? */
/* go to proper init */
j init
diff --git a/arch/riscv/init/init.c b/arch/riscv/init/init.c
index 30c60ac..bb16876 100644
--- a/arch/riscv/init/init.c
+++ b/arch/riscv/init/init.c
@@ -1,118 +1,50 @@
#include <apos/init.h>
#include <apos/sizes.h>
#include <apos/types.h>
+#include <libfdt.h>
#include <pages.h>
#include <csr.h>
#include <vmap.h>
-struct page_ret {
- size_t left;
- size_t num;
- size_t top;
+struct mem_layout {
+ pm_t base;
+ pm_t top;
};
-extern void main(struct mm_pagearr_info *pageinfo);
-
-void __init init_zero(size_t ptr, size_t bytes)
+struct mem_layout get_memlayout(void *fdt)
{
- char *byte_ptr = (char *)ptr;
-
- /* Not entirely sure if it would be faster to use a larget type than
- * char, Linux seems to have memset16/32/64 but I guess I should check
- * the generated assembly.
- */
- while(bytes--)
- *byte_ptr++ = 0;
-}
+ fdt32_t *size_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#size-cells", NULL);
+ fdt32_t *addr_ptr = (fdt32_t *)fdt_getprop(fdt, 0, "#address-cells", NULL);
-struct page_ret __init init_pages(size_t ram_size, size_t ram_top,
- size_t page_size, size_t struct_size)
-{
- size_t num_pages = ram_size / page_size;
- size_t size_pages = num_pages * struct_size;
+ uint32_t size_cells = fdt32_to_cpu(*size_ptr);
+ uint32_t addr_cells = fdt32_to_cpu(*addr_ptr);
- struct page_ret pageret;
- pageret.top = ram_top - size_pages;
- pageret.num = num_pages;
- pageret.left = ram_size - (num_pages * page_size);
+ int mem_offset = fdt_path_offset(fdt, "/memory");
+ uint8_t *mem_reg = (uint8_t *)fdt_getprop(fdt, mem_offset, "reg", NULL);
- init_zero(pageret.top, size_pages);
+ pm_t base;
+ /* if riscv128 comes around we will probably see addr_cells == 4, but
+ * I'm not too concerned about it at the moment */
+ if (addr_cells == 2) {
+ base = fdt64_to_cpu(*(fdt64_t *)mem_reg);
+ mem_reg += sizeof(fdt64_t);
+ } else {
+ base = fdt32_to_cpu(*(fdt32_t *)mem_reg);
+ mem_reg += sizeof(fdt32_t);
+ }
- return pageret;
-};
-
-size_t __init init_align_down(size_t num, size_t a)
-{
- size_t rem = num % a;
- return num - rem;
-}
-
-size_t __init init_align_up(size_t num, size_t a)
-{
- return init_align_down(num, a) + a;
-}
-
-void __init init_enter_vm(unsigned long *root_page)
-{
- asm volatile ("csrw 0x180, %0\n" "sfence.vma\n"
- :
- : "rK" (SATP_MODE_39 | ((unsigned long)root_page >> 12))
- : "memory");
-}
+ pm_t top;
+ if (size_cells == 2)
+ top = fdt64_to_cpu(*(fdt64_t *)mem_reg) + base;
+ else
+ top = fdt32_to_cpu(*(fdt64_t *)mem_reg) + base;
-void __init call_main()
-{
- while(1){};
+ struct mem_layout ret = {base, top};
+ return ret;
}
-void __init init(void *ram_base, void *ram_top, void *initrd, void *fdt, void *boot)
+void init(void *fdt)
{
- size_t ram_size = ram_top - ram_base;
-
- struct mm_pagearr_info pagearr;
- struct page_ret pageret;
-
- /* create crude page status map at the top of physical RAM */
- pageret = init_pages(ram_size, (size_t)ram_top,
- SZ_512G, sizeof(struct terapages));
- pagearr.tera_top = (struct terapages *)pageret.top;
- pagearr.tera_num = pageret.num;
-
- pageret = init_pages(pageret.left, pageret.top,
- SZ_1G, sizeof(struct gigapages));
- pagearr.giga_top = (struct gigapages *)pageret.top;
- pagearr.giga_num = pageret.num;
-
- pageret = init_pages(pageret.left, pageret.top,
- SZ_2M, sizeof(struct megapages));
- pagearr.mega_top = (struct megapages *)pageret.top;
- pagearr.mega_num = pageret.num;
-
- pageret = init_pages(pageret.left, pageret.top,
- SZ_4K, sizeof(struct kilopages));
- pagearr.kilo_top = (struct kilopages *)pageret.top;
- pagearr.kilo_num = pageret.num;
-
- unsigned long *root_page = (unsigned long *)
- (init_align_down((size_t)pagearr.kilo_top, SZ_4K) - SZ_4K);
-
- unsigned long *mid_page = (unsigned long)root_page - SZ_4K;
- unsigned long *bot_page = (unsigned long)mid_page - SZ_4K;
-
- /* TODO: should init insert page data into the created arrays? */
- unsigned long root_addr = (((unsigned long)boot >> 12) >> 18) & 0x1ff;
- unsigned long mid_addr = (((unsigned long)boot >> 12) >> 9) & 0x1ff;
- unsigned long bot_addr = (((unsigned long)boot >> 12) >> 0) & 0x1ff;
-
- root_page[root_addr] = (((unsigned long)mid_page & ~0x3ff) >> 2) | VM_V;
- mid_page[mid_addr] = ((unsigned long)bot_page & ~0x3ff) >> 2 | VM_V;
- bot_page[bot_addr] = (((unsigned long)boot & ~0x3ff) >> 2) | VM_V | VM_R | VM_W | VM_X;
-
- //root_page[0] = (((unsigned long)ram_base & ~0x3ff) >> 2) | VM_V | VM_R | VM_W | VM_X;
-
- /* enter virtual memory */
- init_enter_vm(root_page);
-
- /* enter main */
- call_main();
+ struct mem_layout pmem = get_memlayout(fdt);
+ /* struct mm_ptinfo ptbl = create_pagetable(pmem); */
}