aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-07-05 20:14:46 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-07-05 20:14:46 +0300
commit83a6fc687cab3ee87c6cae1324728521f9877ad0 (patch)
treec94d811e702c7bc517886052b42f4b27309ece98
parente09edb5d54e39bd9509a1dc450df5ab320759f97 (diff)
downloadkmi-83a6fc687cab3ee87c6cae1324728521f9877ad0.tar.gz
kmi-83a6fc687cab3ee87c6cae1324728521f9877ad0.zip
formatting and documentation
-rw-r--r--arch/riscv64/kernel/vmem.c10
-rw-r--r--include/arch/vmem.h24
-rw-r--r--include/kmi/initrd.h6
-rw-r--r--include/kmi/mem.h18
-rw-r--r--include/kmi/pmem.h2
-rw-r--r--include/kmi/proc.h2
-rw-r--r--include/kmi/vmem.h12
-rw-r--r--src/main.c26
-rw-r--r--src/mem.c2
-rw-r--r--src/pmem.c40
-rw-r--r--src/proc.c4
-rw-r--r--src/string.c2
-rw-r--r--src/vmem.c12
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 <arch/smp.h>
#include <libfdt.h>
+/**
+ * @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)
{