aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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?
Diffstat (limited to 'src')
-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
11 files changed, 106 insertions, 53 deletions
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;
}
/**