diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-11-22 23:00:46 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-11-22 23:00:46 +0100 |
| commit | 7f6b234625a53d2ceb9ec80dc0172aac1cedb358 (patch) | |
| tree | 4fe10fcbe2d5e90a0e673259dc895f48a76e06cd /kernel/main.c | |
| parent | 224ed7b13ceadd05d27e61d3a0fdd34beb0c7745 (diff) | |
| download | fbos-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.c | 25 |
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"); } } |
