diff --git a/Makefile b/Makefile index a9c0223..b3642f0 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,7 @@ SRC = $(filter-out kernel/fbos.ld.S, $(wildcard kernel/*.S kernel/*.c lib/*.c OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(SRC))) LINKER = kernel/fbos.ld KRNL = fbos -USR = usr/bin/fizz usr/bin/buzz usr/bin/fizzbuzz +USR = usr/bin/init usr/bin/fizz usr/bin/buzz usr/bin/fizzbuzz INIT = usr/initramfs.cpio TESTS = test/test_dt test/test_initrd diff --git a/include/fbos/sched.h b/include/fbos/sched.h index c2a4b19..e05d0a1 100644 --- a/include/fbos/sched.h +++ b/include/fbos/sched.h @@ -23,10 +23,7 @@ struct task_struct { // Tasks available on this kernel. extern struct task_struct tasks[4]; -// Identifier for the next task to be run. -extern int next_task; - -// Bring the machine to idle mode. -__noreturn __kernel void idle(void); +// Switch execution to the given task id. +void switch_to(int task_id); #endif // __FBOS_SCHED_H_ 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..d2297d2 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"); } /* @@ -47,15 +44,8 @@ __noreturn __kernel void start_kernel(void *dtb) 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..f8e2025 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -59,12 +59,8 @@ __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 +75,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 +86,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 +102,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 +122,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)