diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/initrd.c | 4 | ||||
| -rw-r--r-- | kernel/main.c | 16 | ||||
| -rw-r--r-- | kernel/trap.c | 19 |
3 files changed, 15 insertions, 24 deletions
diff --git a/kernel/initrd.c b/kernel/initrd.c index a5c8861..ff1f52b 100644 --- a/kernel/initrd.c +++ b/kernel/initrd.c @@ -53,7 +53,9 @@ __kernel uint64_t strtoul16(const char *str, size_t count) __kernel int get_task_id_from_name(const char *const name) { - if (strcmp(name, "usr/bin/fizz") == 0) { + if (strcmp(name, "usr/bin/init") == 0) { + return TASK_INIT; + } else if (strcmp(name, "usr/bin/fizz") == 0) { return TASK_FIZZ; } else if (strcmp(name, "usr/bin/buzz") == 0) { return TASK_BUZZ; diff --git a/kernel/main.c b/kernel/main.c index 4ed99b5..ba4ada0 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -13,9 +13,7 @@ struct task_struct tasks[4] = { [TASK_FIZZBUZZ] = { .stack = init_stack[3], .addr = nullptr, .entry_offset = 0, }, }; -int next_task; - -// TODO: this feels really brittle +// TODO __kernel void switch_to(int task_id) { const char *ddr = (const char *)tasks[task_id].addr + tasks[task_id].entry_offset; @@ -23,7 +21,6 @@ __kernel void switch_to(int task_id) asm volatile("csrc sstatus, %[mask]" : : [mask] "r"(1 << 8)); asm volatile("mv ra, %0" : : "r"(ddr)); asm volatile("csrw sepc, ra"); - asm volatile("sret"); } /* @@ -39,23 +36,14 @@ __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) -{ + // Loop indefinitely while preserving power. for (;;) { - if (next_task != TASK_UNKNOWN && next_task != TASK_INIT) { - switch_to(next_task); - } asm volatile("wfi"); } } diff --git a/kernel/trap.c b/kernel/trap.c index 84f8398..bf8a89e 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -59,12 +59,7 @@ __kernel __always_inline void exception_handler(uint64_t cause) die("Bad syscall\n"); } - // TODO: acknowledge 'sip' bit? - next_task = TASK_UNKNOWN; write(message, n); - - // TODO: is it safe to jump to idle here? Any preparation to be done? - idle(); } /* @@ -79,6 +74,9 @@ __kernel __always_inline void exception_handler(uint64_t cause) * all registers. It's probably a bit over the top since it also does that for * registers we never care on this kernel (e.g. floating point registers), but * it's convenient. + * + * TODO: once this properly works, switch it to assembly to avoid creepy + * statements like the sad 'goto end' one. */ __aligned(4) __s_interrupt __kernel void interrupt_handler(void) { @@ -87,6 +85,8 @@ __aligned(4) __s_interrupt __kernel void interrupt_handler(void) if (IS_EXCEPTION(cause)) { exception_handler(cause); + switch_to(TASK_INIT); + goto end; } if ((cause & TIMER_SCAUSE_MASK) == TIMER_SCAUSE_MASK) { @@ -101,13 +101,12 @@ __aligned(4) __s_interrupt __kernel void interrupt_handler(void) // BEHOLD! The fizz buzz logic! :D seconds_elapsed += 1; if ((seconds_elapsed % 15) == 0) { - next_task = TASK_FIZZBUZZ; + switch_to(TASK_FIZZBUZZ); } else if ((seconds_elapsed % 5) == 0) { - next_task = TASK_BUZZ; + switch_to(TASK_BUZZ); } else if ((seconds_elapsed % 3) == 0) { - next_task = TASK_FIZZ; + switch_to(TASK_FIZZ); } else { - next_task = TASK_UNKNOWN; } // Re-enable timer interrupts. @@ -122,6 +121,8 @@ __aligned(4) __s_interrupt __kernel void interrupt_handler(void) } else { printk("WARN: unknown interrupt just came in...\n"); } + +end:; } __kernel void setup_interrupts(void) |
