diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-08-25 23:47:08 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2021-08-25 23:47:08 +0300 |
| commit | 5dfac4879ce5f34503ae7537eefd3fc48d6fa750 (patch) | |
| tree | 7ac25f1a14373ae08ea6aa2406d8f83026dba74a /arch/riscv/init/init.c | |
| parent | b235f49f31d11e68019c42f48b6641c37e4c986e (diff) | |
| download | kmi-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/init.c')
| -rw-r--r-- | arch/riscv/init/init.c | 130 |
1 files changed, 31 insertions, 99 deletions
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); */ } |
