aboutsummaryrefslogtreecommitdiff
path: root/kernel/main.c
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2024-11-22 23:00:46 +0100
committerMiquel Sabaté Solà <mikisabate@gmail.com>2024-11-22 23:00:46 +0100
commit7f6b234625a53d2ceb9ec80dc0172aac1cedb358 (patch)
tree4fe10fcbe2d5e90a0e673259dc895f48a76e06cd /kernel/main.c
parent224ed7b13ceadd05d27e61d3a0fdd34beb0c7745 (diff)
downloadfbos-7f6b234625a53d2ceb9ec80dc0172aac1cedb358.tar.gz
fbos-7f6b234625a53d2ceb9ec80dc0172aac1cedb358.zip
Enable exception handling from user mode
This allows us to actually catch system calls and start to run user space programs. That being said, the whole thing is still pretty brittle, and the scheduler is not quite there yet. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/kernel/main.c b/kernel/main.c
index 968c9d5..4ed99b5 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -13,6 +13,19 @@ struct task_struct tasks[4] = {
[TASK_FIZZBUZZ] = { .stack = init_stack[3], .addr = nullptr, .entry_offset = 0, },
};
+int next_task;
+
+// TODO: this feels really brittle
+__kernel void switch_to(int task_id)
+{
+ const char *ddr = (const char *)tasks[task_id].addr + tasks[task_id].entry_offset;
+
+ asm volatile("csrc sstatus, %[mask]" : : [mask] "r"(1 << 8));
+ asm volatile("mv ra, %0" : : "r"(ddr));
+ asm volatile("csrw sepc, ra");
+ asm volatile("sret");
+}
+
/*
* This is the main entry point of the kernel after head.S is done. This
* function can (and will) assume that everything has been reset and that we can
@@ -26,15 +39,23 @@ __noreturn __kernel void start_kernel(void *dtb)
struct initrd_addr addr = find_dt_initrd_addr(dtb);
extract_initrd((unsigned char *)addr.start, addr.end - addr.start);
+ next_task = TASK_UNKNOWN;
+
// At this point everything has already been handled: setup the interrupt
// vector and enable the timer to start ticking and scheduling the three
// tasks at hand.
seconds_elapsed = 0;
setup_interrupts();
+ idle();
+}
+
+__noreturn __kernel void idle(void)
+{
for (;;) {
- // Put the machine on low power consumption since we are not doing
- // anything fancy here.
+ if (next_task != TASK_UNKNOWN && next_task != TASK_INIT) {
+ switch_to(next_task);
+ }
asm volatile("wfi");
}
}