aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-07-08 17:43:59 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-07-08 18:04:03 +0300
commite134202611a50b358c147c92bfb8a7f443030b8b (patch)
treeac7c31824adcf41a63e4d2c5e141f5149cc55b1a
parent7e828ec1e1479ff9a8afe845539d08ca0dfada5f (diff)
downloadkmi-e134202611a50b358c147c92bfb8a7f443030b8b.tar.gz
kmi-e134202611a50b358c147c92bfb8a7f443030b8b.zip
fix LLVM
+ Anything extern is right out as LLVM doesn't produce correct code for them. Maybe if I added some extra attributes but I'm skeptical. Replaced with static variables and getters/setters. + Inline ASM is apparently a bit buggy, so use an assembly stub when jumping to init. + Minimize work done in main() to minimize chance of LLVM doing something silly. Still not 100% certain that I shouldn't just write the main() as an assembly stub in arch/riscv64 to be absolutely sure everything works as intended. + Make .kernel.start section SHF_ALLOC, otherwise lld complains about pc-relative addressing Probably some other stuff as well that I'm forgetting right now. But at least with LLVM14 LTO seems to work, which is pretty cool?
-rw-r--r--arch/riscv64/conf/kernel-link.S19
-rw-r--r--arch/riscv64/kernel/arch.c13
-rw-r--r--arch/riscv64/kernel/arch.h16
-rw-r--r--arch/riscv64/kernel/proc.c38
-rw-r--r--arch/riscv64/kernel/smp.c6
-rw-r--r--arch/riscv64/kernel/start.S15
-rw-r--r--arch/riscv64/kernel/vmem.c12
-rw-r--r--arch/riscv64/source.mk8
-rw-r--r--include/arch/vmem.h6
-rw-r--r--include/kmi/bkl.h13
-rw-r--r--include/kmi/conf.h35
-rw-r--r--include/kmi/dmem.h12
-rw-r--r--include/kmi/mem.h110
-rw-r--r--scripts/makefile5
-rw-r--r--src/bkl.c13
-rw-r--r--src/debug.c2
-rw-r--r--src/irq.c4
-rw-r--r--src/main.c30
-rw-r--r--src/mem.c70
-rw-r--r--src/pmem.c9
-rw-r--r--src/regions.c2
-rw-r--r--src/tcb.c4
-rw-r--r--src/timer.c2
-rw-r--r--src/uapi/conf.c21
-rw-r--r--src/uapi/ipc.c2
25 files changed, 255 insertions, 212 deletions
diff --git a/arch/riscv64/conf/kernel-link.S b/arch/riscv64/conf/kernel-link.S
index 88f2e75..e395e4a 100644
--- a/arch/riscv64/conf/kernel-link.S
+++ b/arch/riscv64/conf/kernel-link.S
@@ -5,12 +5,6 @@ OUTPUT_ARCH(riscv)
ENTRY(main)
SECTIONS {
- /* This is apparently necessary. I *think* it is to tell the linker that
- * the kernel should be able to run in the bottom half of the address
- * space, but I don't know for sure and this feels like a fairly major
- * hack.
- * @todo look into this further.
- */
. = ABSOLUTE(VM_KERNEL);
__kernel_start = .;
.text ALIGN(4K) : AT(0) {
@@ -18,6 +12,14 @@ SECTIONS {
*(.text*);
}
+ /* place bss in between different load sections to force objcopy to
+ * output zeroes for it */
+ .bss : {
+ *(.sbss*)
+ *(.bss*)
+ *(COMMON)
+ }
+
.rodata : {
*(.rodata*)
}
@@ -27,12 +29,7 @@ SECTIONS {
*(.sdata*)
}
- .bss : {
- *(.sbss*) *(.bss*) *(COMMON)
- }
-
__kernel_end = .;
- __kernel_size = __kernel_end - __kernel_start;
.garbage : {
*(.note*)
diff --git a/arch/riscv64/kernel/arch.c b/arch/riscv64/kernel/arch.c
index 4561d8b..5dc50cf 100644
--- a/arch/riscv64/kernel/arch.c
+++ b/arch/riscv64/kernel/arch.c
@@ -13,7 +13,18 @@
#include "csr.h"
#include "arch.h"
-id_t __cpuid_to_hartid[MAX_CPUS];
+/** Array where indexing is done with CPU IDs, giving the corresponding hart ID. */
+static id_t __cpuid_to_hartid[MAX_CPUS];
+
+id_t cpuid_to_hartid(id_t cpu)
+{
+ return __cpuid_to_hartid[cpu];
+}
+
+void set_hartid(id_t cpu, id_t hartid)
+{
+ __cpuid_to_hartid[cpu] = hartid;
+}
id_t hartid_to_cpuid(id_t hart)
{
diff --git a/arch/riscv64/kernel/arch.h b/arch/riscv64/kernel/arch.h
index d38dad0..789b416 100644
--- a/arch/riscv64/kernel/arch.h
+++ b/arch/riscv64/kernel/arch.h
@@ -12,9 +12,6 @@
#include <kmi/vmem.h>
-/** Actual map of cpu id to hart id. */
-extern id_t __cpuid_to_hartid[MAX_CPUS];
-
/**
* Map cpu id to hart id.
* Defined as a macro to allow for stuff like
@@ -23,15 +20,24 @@ extern id_t __cpuid_to_hartid[MAX_CPUS];
* @endcode
*
* @param x Hart ID.
+ * @return Corresponding CPU ID.
+ */
+id_t cpuid_to_hartid(id_t x);
+
+/**
+ * Create mapping between \p cpuid and \p hartid.
+ *
+ * @param cpuid CPU ID to map to \p hartid.
+ * @param hartid Hart ID to map to \p CPU ID.
*/
-#define cpuid_to_hartid(x) __cpuid_to_hartid[x]
+void set_hartid(id_t cpuid, id_t hartid);
/**
* Find the cpu id that corresponds to hart id.
*
* @param hart Hart to find corresponding cpu id for.
* @return Corresponding cpu id. 0 if not found, though this should maybe be a
- * panic situation.
+ * panic situation. Currently just sets the core to sleep.
*/
id_t hartid_to_cpuid(id_t hart);
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index 73b0984..19bd52f 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -9,6 +9,7 @@
#include <kmi/tcb.h>
#include <kmi/elf.h>
#include <kmi/bkl.h>
+#include <kmi/debug.h>
#include <kmi/string.h>
#include <arch/proc.h>
@@ -16,6 +17,27 @@
#include "regs.h"
#include "csr.h"
+/** Assembly implementation for actually jumping to the init process, defined in
+ * start.S. Quite a few constants that could be implemented in assembly as well
+ * but this is maybe a bit more convenient.
+ *
+ * @param pid Should always be 0 to indicate that the kernel is the originator.
+ * @param tid Thread ID of the current thread.
+ * @param code Should always be SYS_USER_SPAWNED to indicate that a new core has
+ * come online.
+ * @param fdt Address of flattened device tree within userspace memory.
+ * @param initrd Ditto for initial ramdisk.
+ * @param proc Process ID, should be constant 1.
+ * @param stack_top Stack address.
+ */
+__noreturn void riscv_run_init(sys_arg_t pid,
+ sys_arg_t tid,
+ sys_arg_t code,
+ sys_arg_t fdt,
+ sys_arg_t initrd,
+ sys_arg_t proc, /* not strictly speaking necessary but eh */
+ sys_arg_t stack_top);
+
void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
{
csr_write(CSR_SSCRATCH, t);
@@ -28,20 +50,10 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd)
* works for now.
*/
vm_t stack_top = t->thread_stack + t->thread_stack_size;
+ info("jumping to %lx\n", (long)t->callback);
+
bkl_unlock();
- __asm__ volatile ("mv sp, %0\n"
- "li a0, %1\n"
- "mv a1, %2\n"
- "li a2, %3\n"
- "mv a3, %4\n"
- "mv a4, %5\n"
- "li a5, %6\n"
- "sret\n"
- :
- : "r" (stack_top),
- "K" (0), "r" (t->tid), "K" (SYS_USER_SPAWNED),
- "r" (fdt), "r" (initrd), "K" (1)
- : "memory");
+ riscv_run_init(0, t->tid, SYS_USER_SPAWNED, fdt, initrd, 1, stack_top);
/* we should never reach this */
unreachable();
}
diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c
index e48a216..425d3ce 100644
--- a/arch/riscv64/kernel/smp.c
+++ b/arch/riscv64/kernel/smp.c
@@ -59,7 +59,7 @@ void smp_bringup(struct vmem *b, void *fdt)
extern void riscv_bringup(void);
/* mark first hart available */
- cpuid_to_hartid(0) = -1;
+ set_hartid(0, -1);
/* assume we're in default Sv mode, in the future this will have to be
* fixed if we start implementing Sv48 etc. */
@@ -87,12 +87,12 @@ void smp_bringup(struct vmem *b, void *fdt)
if (r.value == SBI_HART_STARTED) {
/* there should ever only be one started hart */
assert(cpuid_to_hartid(0) == -1);
- cpuid_to_hartid(0) = hartid;
+ set_hartid(0, hartid);
continue;
}
/** @todo should check that cpus doesn't go over MAX_CPUS */
- cpuid_to_hartid(cpus++) = hartid;
+ set_hartid(cpus++, hartid);
/** @todo try to remember to free these as well */
smp_init_stacks[hartid] = (void *)alloc_page(BASE_PAGE) +
diff --git a/arch/riscv64/kernel/start.S b/arch/riscv64/kernel/start.S
index 5a2ed61..3f2b3cb 100644
--- a/arch/riscv64/kernel/start.S
+++ b/arch/riscv64/kernel/start.S
@@ -1,10 +1,12 @@
+#include "asm.h"
+
#if GENERIC_UBOOT
# define MAIN main_go
#else
# define MAIN main
#endif
-.section .kernel.start
+.section ".kernel.start", "ax"
.global _start
_start:
/* get load address */
@@ -15,6 +17,12 @@ lla sp, riscv_init_stack
li t0, 4096
add sp, sp, t0
+lla t0, __kernel_start
+lla t1, __kernel_end
+lla t2, kernel_size
+sub t0, t1, t0
+sr t0, 0(t2)
+
/* set thread pointer to zero so we don't accidentally try to use a tcb */
li tp, 0
@@ -32,3 +40,8 @@ add sp, sp, t1
lui t0, %hi(kernel)
addi t0, t0, %lo(kernel)
jr t0
+
+.global riscv_run_init
+riscv_run_init:
+mv sp, a6
+sret
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index cb1eba0..9473f38 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -148,7 +148,7 @@ static bool __unused(pm_t b)
*/
static pm_t *__find_vmem(struct vmem *b, vm_t v, enum mm_order *o)
{
- enum mm_order top = __mm_max_order;
+ enum mm_order top = max_order();
if (o)
*o = MM_O0;
do {
@@ -287,7 +287,7 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
enum mm_order order)
{
struct vmem *root = branch;
- enum mm_order top = __mm_max_order;
+ enum mm_order top = max_order();
/* eventually we may want to keep track of page accesses,
* but for now they're mainly a nuisance. */
@@ -316,7 +316,7 @@ stat_t map_vpage(struct vmem *branch, pm_t paddr, vm_t vaddr, vmflags_t flags,
branch->leaf[idx] =
(struct vmem *)to_pte((pm_t)__pa(paddr), vp_flags(flags));
- __add_graves(root, vm_to_index(vaddr, __mm_max_order));
+ __add_graves(root, vm_to_index(vaddr, max_order()));
return OK;
}
@@ -351,7 +351,7 @@ stat_t unmap_vpage(struct vmem *branch, vm_t vaddr)
pm_t *pte = __find_vmem(branch, vaddr, 0);
if (pte) {
*pte = GRAVESTONE;
- __remove_graves(branch, vm_to_index(vaddr, __mm_max_order));
+ __remove_graves(branch, vm_to_index(vaddr, max_order()));
return OK;
}
@@ -423,10 +423,10 @@ __aligned(4096) struct vmem kvmem;
/* adding a third page entry would let us map the kernel at any 4KiB boundary
* but eh, Linux seems fine with 2MiB so I guess I shall be as well. */
-struct vmem *init_mapping()
+struct vmem *init_mapping(uintptr_t load_addr)
{
rpc_pages = order_size(MM_O1) / BASE_PAGE_SIZE;
- kvmem.leaf[0] = (struct vmem *)to_pte(get_load_addr(),
+ kvmem.leaf[0] = (struct vmem *)to_pte(load_addr,
VM_A | VM_G | VM_D | VM_R | VM_W |
VM_X | VM_V);
diff --git a/arch/riscv64/source.mk b/arch/riscv64/source.mk
index 6e72c85..0c10bbc 100644
--- a/arch/riscv64/source.mk
+++ b/arch/riscv64/source.mk
@@ -1,15 +1,9 @@
KERNEL_LOCAL != echo $(ARCH_SOURCE)/kernel/*.[cS]
-KERNEL_SOURCES += $(KERNEL_LOCAL)
-INIT_SOURCES += $(ARCH_SOURCE)/init/*.[cS]
+KERNEL_SOURCES := $(KERNEL_SOURCES) $(KERNEL_LOCAL)
# this doesn't work for rv32, but fine for now */
ARCH_CFLAGS := $(ARCH_CFLAGS) -mcmodel=medany
-# oof, LLVM's riscv support has become better since I last looked into
-# it, but for some reason LTO still causes a crash. Meaning it has to be
-# disabled again, though for a different reason than last time
-OPTFLAGS != [ "$(LLVM)" != "0" ] && echo $(OPTFLAGS:-flto=) || echo $(OPTFLAGS)
-
run:
$(ARCH_SOURCE)/conf/mkimage.sh $(ARCH)
diff --git a/include/arch/vmem.h b/include/arch/vmem.h
index e62c112..a19f555 100644
--- a/include/arch/vmem.h
+++ b/include/arch/vmem.h
@@ -148,10 +148,14 @@ vm_t setup_kernel_io(struct vmem *b, vm_t paddr);
* address space and the kernel address space in the other.
* Called at boot, not allowed to allocate memory.
*
+ * @param load_addr Where in physical memory kernel was loaded to. Could in
+ * theory be fetched from \ref get_load_addr(), but the fewer globals are
+ * touched during initialization the better.
+ *
* @return The vmem node used to build the address space. Probably statically
* allocated.
*/
-struct vmem *init_mapping();
+struct vmem *init_mapping(uintptr_t load_addr);
/**
* Create new virtual memory space.
diff --git a/include/kmi/bkl.h b/include/kmi/bkl.h
index 9ea6ccd..39e3ef9 100644
--- a/include/kmi/bkl.h
+++ b/include/kmi/bkl.h
@@ -12,19 +12,10 @@
#include <kmi/lock.h>
-/** Big Kenrel Lock. */
-extern spinlock_t bkl;
-
/** Lock the Big Kernel Lock. */
-static inline void bkl_lock()
-{
- spin_lock(&bkl);
-}
+void bkl_lock();
/** Unlock the Big Kernel Lock. */
-static inline void bkl_unlock()
-{
- spin_unlock(&bkl);
-}
+void bkl_unlock();
#endif /* KMI_BKL_H */
diff --git a/include/kmi/conf.h b/include/kmi/conf.h
index 8e33a5f..02b8c4f 100644
--- a/include/kmi/conf.h
+++ b/include/kmi/conf.h
@@ -14,36 +14,25 @@
/**
* Provides access to the runtime global parameter.
- * \remark Note that runtime parameter passing is not yet implemented, and I might
- * implement per-thread stack sizes as well.
- * \global
- * \todo This should probably be a function instead.
- */
-extern size_t __thread_stack_size;
-
-/**
- * Provides access to the runtime global parameter.
- * Must be at most RPC_STACK_TOP - RPC_STACK_BASE.
- * Essentially, each thread gets allocated this many bytes of total stack space
- * that will be used during thread migrations. Each migration instance may at
- * most take up __rpc_stack_size bytes, and during a thread migration the
- * currently available free stack space is checked.
- *
- * Previous instances are unmapped, making them unaccessible to the current
- * instance.
+ * @remark I might implement per-thread stack sizes at some point.
*
- * \see __thread_stack_size.
- * \global
- * \todo This should probably also be a function instead.
+ * @return Size of a regular thread stack, primarily just used to pass to \ref
+ * alloc_stack().
*/
-extern size_t __call_stack_size;
+size_t thread_stack_size();
/**
* Provides access to the runtime global parameter. This sets the maximum size
* a single rpc stack instance can be.
*
- * \global
+ * @return Size of one RPC stack entry, generally a single RPC shouldn't take
+ * up all of the available RPC stack space so we limit how much each call is
+ * allowed at a maximum, effectively enforcing a minimum number of RPC calls
+ * that a thread must be allowed to execute.
+ *
+ * I feel like this description is overly complicated but I can't think of a way
+ * to say it more clearly at the moment.
*/
-extern size_t __rpc_stack_size;
+size_t rpc_stack_size();
#endif /* KMI_CONF_H */
diff --git a/include/kmi/dmem.h b/include/kmi/dmem.h
index 6fd590f..697e55a 100644
--- a/include/kmi/dmem.h
+++ b/include/kmi/dmem.h
@@ -13,18 +13,6 @@
#include <kmi/types.h>
#include <kmi/vmem.h>
-/** Provides access to the global parameter. \global */
-extern pm_t __pre_base;
-
-/** Provides access to the global parameter. \global */
-extern pm_t __pre_top;
-
-/** Provides access to the global parameter. \global */
-extern pm_t __post_base;
-
-/** Provides access to the global parameter. \global */
-extern pm_t __post_top;
-
/**
* Initialize device memory.
* @note Currently I assume there is only one RAM region. This may not be the
diff --git a/include/kmi/mem.h b/include/kmi/mem.h
index e840683..6c62d31 100644
--- a/include/kmi/mem.h
+++ b/include/kmi/mem.h
@@ -13,6 +13,49 @@
#include <kmi/types.h>
#include <arch/mem.h>
+/** Maximum number of page orders allowed. Likely massively overkill. */
+#define NUM_ORDERS 10
+
+/** Give names to page orders. */
+enum mm_order {
+ /** NULL marker. */
+ MM_MIN = -1,
+
+ /** Base order. */
+ MM_O0 = 0,
+
+ /** Order 1. */
+ MM_O1 = 1,
+
+ /** Order 2. */
+ MM_O2 = 2,
+
+ /** Order 3. */
+ MM_O3 = 3,
+
+ /** Order 4. */
+ MM_O4 = 4,
+
+ /** Order 5. */
+ MM_O5 = 5,
+
+ /** Order 6. */
+ MM_O6 = 6,
+
+ /** Order 7. */
+ MM_O7 = 7,
+
+ /** Order 8. */
+ MM_O8 = 8,
+
+ /** Order 9. */
+ MM_O9 = 9,
+
+ /** Number of orders */
+ MM_NUM,
+};
+
+
/**
* Convert physical memory address \c paddr to index of page order \c order.
*
@@ -37,7 +80,7 @@
* @param order Order to query.
* @return Starting offset of order bits.
*/
-#define order_shift(order) (__mm_shifts[order])
+size_t order_shift(enum mm_order order);
/**
* Get number of order bits in an address.
@@ -45,7 +88,7 @@
* @param order Order to query.
* @return Width in bits of order bits.
*/
-#define order_width(order) (__mm_widths[order])
+size_t order_width(enum mm_order order);
/**
* Get size of order, as in how many pages of one order lower it can contain.
@@ -53,21 +96,21 @@
* @param order Order to query.
* @return Number of pages of one order lower this order can contain.
*/
-#define order_size(order) (__mm_sizes[order])
+size_t order_size(enum mm_order order);
/**
* Get highest order supported by the current configuration.
*
* @return Max supported order.
*/
-#define max_order() (__mm_max_order)
+enum mm_order max_order();
/**
* Get base page shift.
*
* @return Page shift.
*/
-#define page_shift() (__mm_page_shift)
+size_t page_shift();
/**
* Get number of elements needed to represent this order.
@@ -142,63 +185,6 @@
/** @} */
-/** Maximum number of page orders allowed. Likely massively overkill. */
-#define NUM_ORDERS 10
-
-/** Give names to page orders. */
-enum mm_order {
- /** NULL marker. */
- MM_MIN = -1,
-
- /** Base order. */
- MM_O0 = 0,
-
- /** Order 1. */
- MM_O1 = 1,
-
- /** Order 2. */
- MM_O2 = 2,
-
- /** Order 3. */
- MM_O3 = 3,
-
- /** Order 4. */
- MM_O4 = 4,
-
- /** Order 5. */
- MM_O5 = 5,
-
- /** Order 6. */
- MM_O6 = 6,
-
- /** Order 7. */
- MM_O7 = 7,
-
- /** Order 8. */
- MM_O8 = 8,
-
- /** Order 9. */
- MM_O9 = 9,
-
- /** Number of orders */
- MM_NUM,
-};
-
-/** Gives access to global page order shift information. \global */
-extern size_t __mm_shifts[NUM_ORDERS];
-
-/** Gives access to global page order width information. \global */
-extern size_t __mm_widths[NUM_ORDERS];
-
-/** Gives access to global page order size information. \global */
-extern size_t __mm_sizes[NUM_ORDERS];
-
-/** Gives access to global base page shift. \global */
-extern size_t __mm_page_shift;
-
-/** Gives access to global maximum order size. \global */
-extern enum mm_order __mm_max_order;
-
/**
* Find nearest order to size.
*
diff --git a/scripts/makefile b/scripts/makefile
index 26b33ad..aa0bcac 100644
--- a/scripts/makefile
+++ b/scripts/makefile
@@ -47,7 +47,7 @@ COMPILER != [ "$(LLVM)" != "0" ] \
|| echo $(CROSS_COMPILE)gcc
-OBFLAGS = -ffreestanding -nostdlib -static -fno-pie -std=c17 -g
+OBFLAGS = -ffreestanding -nostdlib -static -fpic -fno-pie -std=c17 -g
WARNFLAGS = -Wall -Wextra -Wvla
ARCH_CFLAGS = -D$(ARCH)
@@ -61,8 +61,7 @@ LINK_FLAGS = $(LDFLAGS) $(ARCH_LDFLAGS)
INCLUDE_FLAGS = -I include -include config.h -include arch/$(ARCH)/config.h
# This makes sure .bss is loaded into the binary
-OBJCOPY_FLAGS ?= -Obinary -R .garbage \
- --set-section-flags .bss=alloc,load,contents
+OBJCOPY_FLAGS ?= -Obinary -R .garbage
COMPILE = $(COMPILER) \
$(COMPILE_FLAGS) $(DEPFLAGS) $(INCLUDE_FLAGS)
diff --git a/src/bkl.c b/src/bkl.c
index aa7bd53..6ee58f4 100644
--- a/src/bkl.c
+++ b/src/bkl.c
@@ -9,4 +9,15 @@
* Instanciation of the big kernel lock.
*/
-spinlock_t bkl = 0;
+/** The Big Kernel Lock. */
+static spinlock_t bkl = 0;
+
+void bkl_lock()
+{
+ spin_lock(&bkl);
+}
+
+void bkl_unlock()
+{
+ spin_unlock(&bkl);
+}
diff --git a/src/debug.c b/src/debug.c
index 567911b..d87588d 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -392,7 +392,7 @@ static size_t __print_prefix(size_t base)
case 16: return __puts("0x");
case 8: return __puts("0");
case 2: return __puts("0b");
- default:
+ default: break;
}
return 0;
diff --git a/src/irq.c b/src/irq.c
index 582a06f..1e33623 100644
--- a/src/irq.c
+++ b/src/irq.c
@@ -70,8 +70,8 @@ void handle_irq()
struct tcb *t = get_tcb(tid);
if (!t || orphan(t)) {
info("tcb %llu dead at irq %llu\n",
- (unsigned long long)tid,
- (unsigned long long)id);
+ (unsigned long long)tid,
+ (unsigned long long)id);
/* unregister irq handler */
irq_map[id] = 0;
diff --git a/src/main.c b/src/main.c
index f3c5e17..12d8514 100644
--- a/src/main.c
+++ b/src/main.c
@@ -61,6 +61,15 @@ __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);
+ /** @todo some kind of lottery? */
+ pm_t ram_base = __fdt_ram_base(fdt);
+ pm_t ram_size = __fdt_ram_size(fdt);
+ set_ram_base(ram_base);
+ set_ram_size(ram_size);
+ set_load_addr(load_addr);
+
+ init_dbg(fdt);
+
/* start up debugging in kernel IO */
setup_io_dbg(d);
@@ -102,27 +111,10 @@ __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 */
(void)hart;
-
- /* dbg uses direct mapping at this point, useful for early init asserts
- * and so on */
- init_dbg(fdt);
-
- /** @todo some kind of lottery? */
- pm_t ram_base = __fdt_ram_base(fdt);
- pm_t ram_size = __fdt_ram_size(fdt);
- set_ram_base(ram_base);
- set_ram_size(ram_size);
- set_load_addr(load_addr);
-
init_mem(fdt);
- /* we don't have any debug output just yet but still */
- /* also this is I guess more of an architecture limitation, should the
- * whole of main() just be moved to arch? */
- assert(is_aligned(load_addr, order_size(MM_O1)));
-
- struct vmem *d = init_mapping();
- to_kernelspace(fdt, load_addr, d, ram_base);
+ struct vmem *d = init_mapping(load_addr);
+ to_kernelspace(fdt, load_addr, d, 0);
unreachable();
}
diff --git a/src/mem.c b/src/mem.c
index 89657e8..5512d82 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -11,23 +11,57 @@
#include <kmi/vmem.h>
#include <libfdt.h>
-size_t __mm_shifts[10];
-size_t __mm_widths[10];
-size_t __mm_sizes[10];
-size_t __mm_page_shift;
-enum mm_order __mm_max_order;
+/** Page order shifts. */
+static size_t mm_shifts[10];
+
+/** Page order widths. */
+static size_t mm_widths[10];
+
+/** Page order sizes. */
+static size_t mm_sizes[10];
+
+/** Base page shift, i.e. how many bits are just offsets within a page. */
+static size_t mm_page_shift;
+
+/** Maximum order supported by the current cpu. */
+static enum mm_order mm_max_order;
+
+size_t order_shift(enum mm_order order)
+{
+ return mm_shifts[order];
+}
+
+size_t order_size(enum mm_order order)
+{
+ return mm_sizes[order];
+}
+
+enum mm_order max_order()
+{
+ return mm_max_order;
+}
+
+size_t order_width(enum mm_order order)
+{
+ return mm_widths[order];
+}
+
+size_t page_shift()
+{
+ return mm_page_shift;
+}
/**
* RAM base address. Not sure if it should be provided through a macro
* like __mm_*.
*/
-pm_t ram_base;
+static pm_t ram_base;
/** RAM size. */
-size_t ram_size;
+static size_t ram_size;
/** Load address. */
-pm_t load_addr;
+static pm_t load_addr;
enum mm_order nearest_order(size_t size)
{
@@ -40,22 +74,22 @@ enum mm_order nearest_order(size_t size)
void init_mem(void *fdt)
{
- size_t max_order = 0;
+ size_t top_order = 0;
size_t base_bits = 0;
size_t bits[NUM_ORDERS] = { 0 };
- stat_pmem_conf(fdt, &max_order, &base_bits, bits);
+ stat_pmem_conf(fdt, &top_order, &base_bits, bits);
- __mm_max_order = max_order;
- __mm_page_shift = base_bits;
+ mm_max_order = top_order;
+ mm_page_shift = base_bits;
- __mm_shifts[0] = __mm_page_shift;
- __mm_widths[0] = 1 << bits[0];
- __mm_sizes[0] = 1 << __mm_page_shift;
+ mm_shifts[0] = mm_page_shift;
+ mm_widths[0] = 1 << bits[0];
+ mm_sizes[0] = 1 << mm_page_shift;
for (enum mm_order i = MM_O1; i <= max_order(); ++i) {
- __mm_widths[i] = 1 << bits[i];
- __mm_shifts[i] = __mm_shifts[i - 1] + bits[i - 1];
- __mm_sizes[i] = 1UL << __mm_shifts[i];
+ mm_widths[i] = 1 << bits[i];
+ mm_shifts[i] = mm_shifts[i - 1] + bits[i - 1];
+ mm_sizes[i] = 1UL << mm_shifts[i];
}
}
diff --git a/src/pmem.c b/src/pmem.c
index bed10a4..47bb319 100644
--- a/src/pmem.c
+++ b/src/pmem.c
@@ -612,6 +612,11 @@ retry:
return 0;
}
+/** Actual kernel size in bytes. Populated by `_start`, as I don't think we
+ * have enough control from C to get both LLVM and GCC to output correct code
+ * if this was just a virtual symbol defined in a linker file. */
+size_t kernel_size = 0;
+
void init_pmem(void *fdt, uintptr_t load_addr)
{
/** @todo should I keep the info outputs? I suppose it's nice to see
@@ -650,13 +655,11 @@ void init_pmem(void *fdt, uintptr_t load_addr)
size_t probe_size = probe_pmap(0, ram_size, 0);
info("pmem map probe size returned %lu\n", probe_size);
- /* linker magicry */
- extern char *__kernel_size;
/* avoidance regions, note that stack and so on is included in the
* kernel. Addresses can be outside RAM, in which case they are just
* ignored. */
struct avoid_region avoid[64] = {
- {(pm_t)__va(load_addr), (pm_t)&__kernel_size},
+ {(pm_t)__va(load_addr), kernel_size},
{(pm_t)__va(initrd_base), initrd_size},
{(pm_t)__va(fdt_base), fdt_size}
};
diff --git a/src/regions.c b/src/regions.c
index b57b548..ca99971 100644
--- a/src/regions.c
+++ b/src/regions.c
@@ -259,7 +259,7 @@ static struct mem_region *__create_region(vm_t start, vm_t end,
*/
static size_t po_align(size_t s)
{
- for (size_t o = __mm_max_order; o > 0; --o) {
+ for (size_t o = max_order(); o > 0; --o) {
if (s >= order_size(o))
return order_size(o);
}
diff --git a/src/tcb.c b/src/tcb.c
index ea00d3d..053ea6f 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -102,14 +102,14 @@ stat_t alloc_stack(struct tcb *t)
/* get parent process */
struct tcb *p = get_tcb(t->eid);
- t->thread_stack = __setup_thread_stack(p, __thread_stack_size);
+ t->thread_stack = __setup_thread_stack(p, thread_stack_size());
if (!t->thread_stack)
return ERR_OOMEM;
/** \todo this only allows for a global stack size, what if a user wants
* per thread stack sizes? I guess allocate them yourself in userspace
* or something? */
- t->thread_stack_size = __thread_stack_size;
+ t->thread_stack_size = thread_stack_size();
return OK;
}
diff --git a/src/timer.c b/src/timer.c
index 573ed7b..5583cd3 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -208,7 +208,7 @@ void handle_timer()
struct tcb *r = get_tcb(tid);
if (!r || orphan(r)) {
info("tcb %llu dead at timer\n",
- (unsigned long long)tid);
+ (unsigned long long)tid);
bkl_unlock();
return;
}
diff --git a/src/uapi/conf.c b/src/uapi/conf.c
index be9abfc..3a45d30 100644
--- a/src/uapi/conf.c
+++ b/src/uapi/conf.c
@@ -16,11 +16,24 @@
#include <arch/proc.h>
-/** \todo stack size should really be set on a per-thread basis, and are the
- * conf*-syscalls even necessary? */
-size_t __thread_stack_size = SZ_2M;
-size_t __rpc_stack_size = SZ_512K;
+/** \todo stack size should probably be set on a per-thread basis */
+/** Current global thread stack size. */
+static size_t __thread_stack_size = SZ_2M;
+
+/** Current global RPC stack entry size. */
+static size_t __rpc_stack_size = SZ_512K;
+
+
+size_t thread_stack_size()
+{
+ return __thread_stack_size;
+}
+
+size_t rpc_stack_size()
+{
+ return __rpc_stack_size;
+}
/**
* Configuration parameter read syscall handler.
diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c
index 3ac4727..3a28afa 100644
--- a/src/uapi/ipc.c
+++ b/src/uapi/ipc.c
@@ -133,7 +133,7 @@ static bool __enough_rpc_stack(struct tcb *t)
/* if we can still fit an rpc stack into the call stack, we can safely
* do the migration. */
- return top - BASE_PAGE_SIZE - __rpc_stack_size >= RPC_STACK_BASE;
+ return top - BASE_PAGE_SIZE - rpc_stack_size() >= RPC_STACK_BASE;
}
/**