From e09edb5d54e39bd9509a1dc450df5ab320759f97 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 5 Jul 2024 19:38:11 +0300 Subject: allow booting with Qemu's -kernel flag directly + Took some fairly significant changes, for one the kernel is no longer relocated at the start of a boot, instead it sits wherever the user decides the kernel should sit. Similarly, the initial kernel stack and page table are stored within the binary, slightly bloating the size but making it much safer to boot since there's really no chance of us overwriting the fdt or initrd in memory. --- arch/riscv64/init/init.c | 148 ---------------------------------------------- arch/riscv64/init/start.S | 38 ------------ 2 files changed, 186 deletions(-) delete mode 100644 arch/riscv64/init/init.c delete mode 100644 arch/riscv64/init/start.S (limited to 'arch/riscv64/init') diff --git a/arch/riscv64/init/init.c b/arch/riscv64/init/init.c deleted file mode 100644 index a4fa696..0000000 --- a/arch/riscv64/init/init.c +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: copyleft-next-0.3.1 */ -/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ - -/** - * @file init.c - * riscv64 'bootstrap', move actual kernel into place and jump to virtual - * memory. - */ - -#include -#include -#include -#include -#include -#include - -#include "../kernel/csr.h" - -void flush_tlb_full() -{ - /** @todo could be nice to have a common set of features with kernel, - * but for now this is good enough. */ - __asm__ volatile ("sfence.vma\n" ::: "memory"); -} - -/** - * Create page table entry. - * Copy from \ref arch/riscv64/kernel/vmem.c. - * - * @param a Virtual address. - * @param f PTE flags. - */ -#define to_pte(a, f) (((a) >> 12) << 10 | (f)) - -/** - * Get RAM base address from fdt. - * @todo in case of multiple RAM banks, should try to just find one - * of them and let the kernel figure the rest out. Kernel doesn't currently - * support multiple RAM banks. - * - * @param fdt FDT pointer. - * @return Physical address of ram base. - */ -static pm_t __fdt_ram_base(void *fdt) -{ - int mem_offset = fdt_path_offset(fdt, "/memory"); - const void *mem_reg = fdt_getprop(fdt, mem_offset, "reg", NULL); - - struct cell_info ci = get_cellinfo(fdt, mem_offset); - return (pm_t)fdt_load_int_ptr(ci.addr_cells, mem_reg); -} - -/** - * Jump into virtual memory. - * - * @param load_addr Address where init has been loaded. - * @param ram_base RAM base. - */ -static void init_bootmem(uintptr_t load_addr, uintptr_t ram_base) -{ - /* set all flags on, especially A and D since MMUs are allowed to raise - * exceptions that we're not ready to handle if they're unset. */ - size_t flags = VM_V | VM_X | VM_R | VM_W | VM_D | VM_A; - - extern char *__kernel; - extern char *__kernel_size; - uintptr_t top = load_addr + (uintptr_t)&__kernel + - (uintptr_t)&__kernel_size; - - /* this could be risky, as we might overwrite some bits of initrd or fdt - * if they're allocated too close to the kernel payload. - * @todo Allocate root_branch statically? */ - struct vmem *root_branch = (struct vmem *)align_up(top, SZ_4K); - - /* direct mapping (temp) */ - for (size_t i = 0; i <= CSTACK_PAGE; ++i) - root_branch->leaf[i] = (struct vmem *)to_pte(TOP_PAGE_SIZE * i, - flags); - - /* kernel (also sort of direct mapping) */ - flags |= VM_G; - for (size_t i = KSTART_PAGE; i < IO_PAGE; ++i) - root_branch->leaf[i] = (struct vmem *)to_pte( - ram_base + TOP_PAGE_SIZE * (i - KSTART_PAGE), flags); - - /* kernel IO, map to 0 for now, will be updated in the future */ - root_branch->leaf[IO_PAGE] = (struct vmem *)to_pte(0, flags); - - uintmax_t mode = Sv39; - switch (DEFAULT_Sv_MODE) { - case Sv32: mode = SATP_MODE_Sv32; break; - case Sv39: mode = SATP_MODE_Sv39; break; - case Sv48: mode = SATP_MODE_Sv48; break; - default: break; - }; - - flush_tlb_full(); - csr_write(CSR_SATP, mode | ((uintptr_t)root_branch >> 12)); -} - -/** - * Relocate kernel proper. - * @param load_addr Address to where init has been loaded. - * Used in calculating kernel start address. - */ -static void move_kernel(uintptr_t load_addr) -{ - extern char *__kernel; - extern char *__kernel_size; - - size_t sz = (size_t)&__kernel_size; - char *src = load_addr + (char *)&__kernel; - char *dst = (char *)VM_KERN; - for (size_t i = 0; i < sz; ++i) - dst[i] = src[i]; -} - -/** - * Main driver for the init loader. - * - * @param fdt Global FDT pointer, provided by bootloader. - * @param load_addr Address to where init has been loaded. - */ -void init(void *fdt, pm_t load_addr) -{ - extern void jump_to_kernel(void *fdt, pm_t ram_base, void *k); - - pm_t ram_base = __fdt_ram_base(fdt); - - init_bootmem(load_addr, ram_base); - move_kernel(load_addr); - - jump_to_kernel(fdt, ram_base, (void *)VM_KERN); -} - -#if GENERIC_UBOOT -void init_go(int argc, char **argv, pm_t load_addr) -{ - if (argc != 2) - return; - - void *fdt = (void *)strtouintptr(argv[1]); - - /* fdt is passed as second argument, load address first but since we - * already have it due to our ingenious _start, no need to parse it */ - init(fdt, load_addr); -} -#endif diff --git a/arch/riscv64/init/start.S b/arch/riscv64/init/start.S deleted file mode 100644 index b6394f7..0000000 --- a/arch/riscv64/init/start.S +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: copyleft-next-0.3.1 */ -/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ - -/* generic u-boot passes argc and argv as if we were a regular - * program, so our load address must be placed third. - * If we have a 'custom' u-boot with kmi support, the fdt - * will be passed to us directly, so the load address can go second. - */ -#if GENERIC_UBOOT -# define LOAD_REG a2 -# define INIT init_go -#else -# define LOAD_REG a1 -# define INIT init -#endif - -.section .init -.global _start -/* Entry point to the kernel loader. */ -_start: -/* get load address */ -auipc LOAD_REG, 0 -/* keep using bootloader stack for now */ -//li sp, PM_STACK_TOP -/* make sure there's no garbage in tp, important for id assignment */ -li tp, 0 -call INIT -// INIT shouldn't return, but if we do we might as well just jump back to u-boot -// or wherever -ret - -.section .text -.global jump_to_kernel -jump_to_kernel: -li sp, VM_STACK_TOP // load virtual stack address -li fp, 0 -li gp, 0 -jr a2 // jump to kernel -- cgit v1.3