From 83a6fc687cab3ee87c6cae1324728521f9877ad0 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 5 Jul 2024 20:14:46 +0300 Subject: formatting and documentation --- arch/riscv64/kernel/vmem.c | 10 ++++++++-- include/arch/vmem.h | 24 ++++++++++++++++++++++-- include/kmi/initrd.h | 6 ++++++ include/kmi/mem.h | 18 +++++++++++------- include/kmi/pmem.h | 2 ++ include/kmi/proc.h | 2 ++ include/kmi/vmem.h | 12 ++++++++++++ src/main.c | 26 ++++++++++++++++++++++---- src/mem.c | 2 ++ src/pmem.c | 40 +++++++++++++++++++++++++++++++++++++++- src/proc.c | 4 ++-- src/string.c | 2 +- src/vmem.c | 12 ++++++++++++ 13 files changed, 141 insertions(+), 19 deletions(-) diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index 835f53d..3f29446 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -398,9 +398,15 @@ static void __populate_dmap(struct vmem *branch) /** How many base pages we use for the rpc stack. Used fairly often so calculate * it at the start and then reference it. */ -static size_t rpc_pages; +size_t rpc_pages; + +/** Initial stack used when booting the kernel. Probably way overkill, but 4K is + * such a nice number. */ long riscv_init_stack[4096 / sizeof(long)]; -__attribute__((aligned(4096))) struct vmem bootvmem; + +/** Initial page table used when booting the kernel. Has to be aligned properly, + * and so the kernel itself has to be on a 4K boundary. */ +__aligned(4096) struct vmem bootvmem; struct vmem *direct_mapping() { diff --git a/include/arch/vmem.h b/include/arch/vmem.h index 238b12a..8f94e07 100644 --- a/include/arch/vmem.h +++ b/include/arch/vmem.h @@ -140,6 +140,14 @@ struct vmem *init_vmem(void *fdt); vm_t setup_kernel_io(struct vmem *b, vm_t paddr); #endif +/** + * Create a direct mapping, with 1:1 physical addresses in one half of the + * address space and the kernel address space in the other. + * Called at boot, not allowed to allocate memory. + * + * @return The vmem node used to build the address space. Probably statically + * allocated. + */ struct vmem *direct_mapping(); /** @@ -173,7 +181,19 @@ stat_t destroy_vmem(struct vmem *b); */ void clone_uvmem(struct vmem * restrict r, struct vmem * restrict b); -__noreturn void to_kernelspace(void *fdt, uintptr_t load_addr, - struct vmem *direct_mapping, pm_t ram_base, +/** + * Jump into kernelspace from a physical address space. + * Really only called by main() during boot so the parameters are kind of weird. + * + * @param fdt Flattened devicetree. + * @param load_addr Address where kernel was loaded to. + * @param direct_mapping Direct mapping vmem. + * @param ram_base Physical base address of ram. + * @param dmap \ref VM_DMAP. + */ +__noreturn void to_kernelspace(void *fdt, + uintptr_t load_addr, + struct vmem *direct_mapping, + pm_t ram_base, pm_t dmap); #endif /* KMI_ARCH_PAGES_H */ diff --git a/include/kmi/initrd.h b/include/kmi/initrd.h index 58fafd5..87d76ab 100644 --- a/include/kmi/initrd.h +++ b/include/kmi/initrd.h @@ -45,6 +45,12 @@ pm_t get_initrdtop(const void *fdt); */ pm_t get_initrdbase(const void *fdt); +/** + * Get size of initrd in bytes. + * + * @param fdt Global FDT pointer. + * @return Size of \c initrd. + */ size_t get_initrdsize(const void *fdt); /** diff --git a/include/kmi/mem.h b/include/kmi/mem.h index ec8d2ea..97a85bf 100644 --- a/include/kmi/mem.h +++ b/include/kmi/mem.h @@ -204,14 +204,11 @@ extern enum mm_order __mm_max_order; enum mm_order nearest_order(size_t size); /** - * Initialize memory subsystem data. Populates __mm_* with data given. + * Initialize memory subsystem data. * - * @param max_order Maximum order the current system supports. - * @param shifts Offsets to start of each memory order in address. - * @param page_shift Width in bits of base page size. - * \todo Should likely also be stat_t? + * @param fdt Pointer to flattened device tree. */ -void init_mem(void *mem); +void init_mem(void *fdt); /** * Set RAM base address for global access. @@ -221,6 +218,7 @@ void init_mem(void *mem); */ void set_ram_base(pm_t base); +/** @param size Set RAM size. */ void set_ram_size(size_t size); /** @@ -231,9 +229,15 @@ void set_ram_size(size_t size); */ pm_t get_ram_base(); +/** + * Get RAM size. + * Assumes \ref set_ram_size() has been called beforehand. + * Does not take into account disjoint RAM regions. + * + * @return RAM size. + */ size_t get_ram_size(); - /** Base page size. */ #define BASE_PAGE_SIZE (order_size(BASE_PAGE)) diff --git a/include/kmi/pmem.h b/include/kmi/pmem.h index 96a4447..966f269 100644 --- a/include/kmi/pmem.h +++ b/include/kmi/pmem.h @@ -67,6 +67,8 @@ size_t probe_pmap(pm_t ram_base, size_t ram_size, pm_t cont); * Initialize physical memory subsystem. * * @param fdt Global FDT pointer. + * @param load_addr Where kernel was loaded to. Important for making sure that + * nothing gets accidentally overwritten. */ void init_pmem(void *fdt, uintptr_t load_addr); diff --git a/include/kmi/proc.h b/include/kmi/proc.h index 4b8807f..d8692b1 100644 --- a/include/kmi/proc.h +++ b/include/kmi/proc.h @@ -29,6 +29,8 @@ stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp); * Initialize process handling subsystem and setup \c init program. * * @param fdt Global FDT pointer. + * @param proc_fdt Where in memory the FDT was mapped. + * @param proc_initrd Where in memory the initrd was mapped. * @return \ref ERR_OOMEM when out of memory, \ref ERR_INVAL if loading \c init * failed, \ref OK otherwise. */ diff --git a/include/kmi/vmem.h b/include/kmi/vmem.h index 3205e00..6335959 100644 --- a/include/kmi/vmem.h +++ b/include/kmi/vmem.h @@ -131,6 +131,18 @@ stat_t init_uvmem(struct tcb *r, vm_t base, vm_t top); */ stat_t destroy_uvmem(struct tcb *r); +/** + * Map a fixed physical region (within kernelspace) to somewhere in virtual + * memory. + * + * @param r Thread where memory should be mapped. + * @param base Physical base address to map. + * @param size Size of region to map. + * @param flags Flags to use for mapping. + * @return Address of mapping in virtual memory. Though note that it points to + * the start of \p base, not necessarily the start of the allocation. + * If this should be freed, remember to align down to the base page size. + */ vm_t map_fixed_mem(struct tcb *r, pm_t base, size_t size, vmflags_t flags); /** diff --git a/src/main.c b/src/main.c index 19d52a2..506d7fe 100644 --- a/src/main.c +++ b/src/main.c @@ -19,6 +19,10 @@ #include #include +/** + * @param fdt Flattened devicetree. + * @return Base address of RAM. Does not take into account disjoint RAM. + */ static pm_t __fdt_ram_base(void *fdt) { int mem_offset = fdt_path_offset(fdt, "/memory"); @@ -28,6 +32,10 @@ static pm_t __fdt_ram_base(void *fdt) return (pm_t)fdt_load_reg_addr(ci, mem_reg, 0); } +/** + * @param fdt Flattened devicetree. + * @return RAM size. Does not take into account disjoint RAM. + */ static pm_t __fdt_ram_size(void *fdt) { int mem_offset = fdt_path_offset(fdt, "/memory"); @@ -39,8 +47,17 @@ static pm_t __fdt_ram_size(void *fdt) return (pm_t)fdt_load_reg_size(ci, mem_reg, 0); } -void kernel(void *fdt, uintptr_t load_addr, struct vmem *d) +/** + * 'Actual' kernel, runs in kernelspace and does the heavy lifting during + * booting. + * + * @param fdt Flattened device tree. + * @param load_addr Where in memory the kernel blob was loaded to. + * @param d Direct mapping to use during booting. + */ +__noreturn void kernel(void *fdt, uintptr_t load_addr, struct vmem *d) { + /* we should be in kernelspace, so use the virtual address of our FDT. */ fdt = __va(fdt); /* dbg uses direct mapping at this point */ @@ -73,11 +90,12 @@ void kernel(void *fdt, uintptr_t load_addr, struct vmem *d) * Sets up all kernel subsystems and jumps into \c init program, does not * return. * + * @param hart Hart ID. Technically unused, but makes the signature more fitting + * for booting with different systems, like OpenSBI and u-boot. * @param fdt Global FDT pointer in physical memory. - * @param ram_base RAM base. - * @return Should not. + * @param load_addr To which (physical) address in RAM kernel was loaded to. */ -void main(unsigned long hart, void *fdt, uintptr_t load_addr) +__noreturn void main(unsigned long hart, void *fdt, uintptr_t load_addr) { /* we have our own ways to get the current hart when we need it, but we * have to get the function signature right */ diff --git a/src/mem.c b/src/mem.c index 68d323f..4fb9d5a 100644 --- a/src/mem.c +++ b/src/mem.c @@ -22,6 +22,8 @@ enum mm_order __mm_max_order; * like __mm_*. */ pm_t ram_base; + +/** RAM size. */ size_t ram_size; enum mm_order nearest_order(size_t size) diff --git a/src/pmem.c b/src/pmem.c index bddefa8..dd10768 100644 --- a/src/pmem.c +++ b/src/pmem.c @@ -436,11 +436,23 @@ static void __mark_area_used(pm_t base, pm_t top) mark_used(BASE_PAGE, runner); } +/** Helper for keeping track of which memory regions to avoid placing data into. */ struct avoid_region { + /** Base address of region. */ pm_t base; + + /** Size of region. */ pm_t size; }; +/** + * @param base1 + * @param size1 + * @param base2 + * @param size2 + * @return \ref true if the memory regions indicated have some overlap, + * \ref false otherwise. + */ static bool overlaps(pm_t base1, pm_t size1, pm_t base2, pm_t size2) { bool b = base1 >= base2 && base1 < base2 + size2; @@ -451,7 +463,11 @@ static bool overlaps(pm_t base1, pm_t size1, pm_t base2, pm_t size2) /** * Mark reserved memory region used, to avoid it getting accidentally allocated. * - * @param fdt Global FDT pointer. + * @param ram_base RAM base address in kernelspace. + * @param ram_size RAM size. + * @param avoid_count How many regions to avoid. + * @param avoid Regions to avoid. Should all be in kernelspace, everything + * outside RAM is ignored. */ static void __mark_reserved(pm_t ram_base, pm_t ram_size, size_t avoid_count, struct avoid_region avoid[64]) @@ -469,6 +485,15 @@ static void __mark_reserved(pm_t ram_base, pm_t ram_size, size_t avoid_count, } } +/** + * Figure out what if any regions of RAM are reserved and append them to \p + * avoid. + * + * @param exists How many elements are currently in \p avoid. + * @param avoid Array of regions to avoid, must not be sparse. + * @param fdt Flattened device tree. + * @return Total number of regions avoid. + */ static size_t build_reserved_map(size_t exists, struct avoid_region avoid[64], void *fdt) { @@ -490,6 +515,19 @@ static size_t build_reserved_map(size_t exists, struct avoid_region avoid[64], return exists; } +/** + * Selects a fitting base address for a block of memory of size \p size, while + * avoiding overwriting anything in \p avoid. + * Addresses to be avoided are allowed to be outside of RAM, + * for example in ROM, in which case they are just ignored. + * + * @param ram_base Base address of RAM. + * @param ram_size Size of RAM. + * @param size Size of block to find. + * @param avoid_count How many elements in the \p avoid array. + * @param avoid Which memory regions to avoid. + * @return A suitable base address, aligned on a word boundary. + */ static pm_t select_base(pm_t ram_base, pm_t ram_size, pm_t size, pm_t avoid_count, struct avoid_region avoid[64]) diff --git a/src/proc.c b/src/proc.c index f2d418f..61dd125 100644 --- a/src/proc.c +++ b/src/proc.c @@ -70,7 +70,7 @@ stat_t init_proc(void *fdt, vm_t *proc_fdt, vm_t *proc_initrd) initrd, get_initrdsize(fdt), VM_V | VM_R | VM_U); - info("mapped fdt at %p\n", (void *)*proc_fdt); - info("mapped initrd at %p\n", (void *)*proc_initrd); + info("mapped fdt at %lx\n", *proc_fdt); + info("mapped initrd at %lx\n", *proc_initrd); return OK; } diff --git a/src/string.c b/src/string.c index 4eaaf68..743fd98 100644 --- a/src/string.c +++ b/src/string.c @@ -259,7 +259,7 @@ __weak size_t strnlen(const char *str, size_t num) } #undef memset -__weak void *memset(void *ptr, int value, size_t num) +__weak __used void *memset(void *ptr, int value, size_t num) { char *p = ptr; char c = value; diff --git a/src/vmem.c b/src/vmem.c index d041c80..f1841e4 100644 --- a/src/vmem.c +++ b/src/vmem.c @@ -232,6 +232,18 @@ vm_t alloc_fixed_uvmem(struct tcb *t, vm_t start, size_t size, vmflags_t flags) return w; } +/** + * Helper for \ref map_fixed_mem(). + * Maps some contiguous bit of physical memory to an allocated virtual memory region. + * + * @param b Virtual memory to work in. + * @param v Start of virtual memory region. + * @param p Start of physical memory region. + * @param size Size of virtual memory region. + * @param flags Flags to use for mappings. + * @param status Is written to with the status of this function. + * @return The start of the virtual address mapping. + */ static vm_t map_fixed_region(struct vmem *b, vm_t v, pm_t p, size_t size, vmflags_t flags, stat_t *status) { -- cgit v1.3