aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--include/fbos/sched.h7
-rw-r--r--kernel/initrd.c4
-rw-r--r--kernel/main.c16
-rw-r--r--kernel/trap.c19
-rw-r--r--usr/src/init.S8
6 files changed, 26 insertions, 30 deletions
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..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)
diff --git a/usr/src/init.S b/usr/src/init.S
new file mode 100644
index 0000000..6566f20
--- /dev/null
+++ b/usr/src/init.S
@@ -0,0 +1,8 @@
+.global _start
+.text
+
+_start:
+.Loop:
+ // TODO
+ // wfi
+ j .Loop