aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fbos/printk.h2
-rw-r--r--include/fbos/sched.h22
-rw-r--r--kernel/head.S6
-rw-r--r--kernel/main.c8
-rw-r--r--kernel/printk.c44
-rw-r--r--kernel/trap.c10
6 files changed, 72 insertions, 20 deletions
diff --git a/include/fbos/printk.h b/include/fbos/printk.h
index 5a12d7c..d5f4804 100644
--- a/include/fbos/printk.h
+++ b/include/fbos/printk.h
@@ -11,7 +11,7 @@
#ifdef __KERNEL__
extern void die(const char *const message);
extern void printk(const char *const message);
-extern void write(const char *const message, size_t n);
+extern void sys_write(const char *const message, size_t n);
#else
#include <stdio.h>
#include <stdlib.h>
diff --git a/include/fbos/sched.h b/include/fbos/sched.h
index f43b6e5..e8edafd 100644
--- a/include/fbos/sched.h
+++ b/include/fbos/sched.h
@@ -12,6 +12,9 @@ enum task_id {
TASK_FIZZBUZZ = 3,
};
+// Maximum length for the name of the process.
+#define TASK_NAME_LEN 16
+
// All the information we need to grab for processes.
struct task_struct {
// The stack allocated for the process. As you can see when initializing
@@ -20,6 +23,9 @@ struct task_struct {
// for simple `sp` values.
void *stack;
+ // Name of the task to be printed for debugging purposes.
+ const char name[TASK_NAME_LEN];
+
// The address for the binary entry.
const void *entry_addr;
};
@@ -27,14 +33,26 @@ struct task_struct {
// Tasks available on this kernel.
extern struct task_struct tasks[4];
-// Set the return address to U-mode to the given task.
-__kernel __always_inline void set_return_address_to(int task_id)
+// Prepare for switching to the given task. Note that this will not actually
+// jump into the given task, but it will prepare the relevant registers before
+// performing the actual jump.
+__kernel __always_inline void prepare_switch_to(int task_id)
{
+ register struct task_struct *current asm("tp");
+
asm volatile("csrc sstatus, %0\n\t"
"mv t0, %1\n\t"
"csrw sepc, t0" ::"r"(1 << 8),
"r"(tasks[task_id].entry_addr)
: "t0");
+
+ current = &tasks[task_id];
+
+ // Not really unused, but I was getting into lots of petty trouble with GCC
+ // depending if running with/without DEBUG on. Hence, let's set 'tp' in C
+ // instead of with inline assembly, even if the compiler thinks the variable
+ // is set but not used.
+ __unused(current);
}
#endif // __FBOS_SCHED_H_
diff --git a/kernel/head.S b/kernel/head.S
index 31f423e..9a12833 100644
--- a/kernel/head.S
+++ b/kernel/head.S
@@ -94,9 +94,9 @@ _start_kernel:
li t6, 0
csrw sscratch, 0
- // Point tp and sp to the init task. This is not crucial because in the end
- // we are not doing anything with the 'tp' register, and our processes
- // actually don't do anything on the stack.
+ // Point tp and sp to the init task. The 'tp' register will always point to
+ // the current process being executed, and it will be shown on debug when
+ // printing out messages.
la tp, tasks
la sp, tasks + THREAD_SIZE
diff --git a/kernel/main.c b/kernel/main.c
index ecb93da..9c524c4 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -10,10 +10,10 @@ unsigned long stack[4][THREAD_SIZE / sizeof(unsigned long)];
// Initialize the list of structs by providing a fixed stack address and empty
// values everywhere else.
struct task_struct tasks[4] = {
- [TASK_INIT] = { .stack = stack[0], .entry_addr = nullptr, },
- [TASK_FIZZ] = { .stack = stack[1], .entry_addr = nullptr, },
- [TASK_BUZZ] = { .stack = stack[2], .entry_addr = nullptr, },
- [TASK_FIZZBUZZ] = { .stack = stack[3], .entry_addr = nullptr, },
+ [TASK_INIT] = { .stack = stack[0], .name = "init", .entry_addr = nullptr, },
+ [TASK_FIZZ] = { .stack = stack[1], .name = "fizz", .entry_addr = nullptr, },
+ [TASK_BUZZ] = { .stack = stack[2], .name = "buzz", .entry_addr = nullptr, },
+ [TASK_FIZZBUZZ] = { .stack = stack[3], .name = "fizzbuzz", .entry_addr = nullptr, },
};
// Defined in fbos/init.h.
diff --git a/kernel/printk.c b/kernel/printk.c
index b3c925a..bd2bcab 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1,4 +1,5 @@
#include <fbos/printk.h>
+#include <fbos/sched.h>
#include <fbos/string.h>
#include <fbos/sbi.h>
@@ -12,8 +13,40 @@ void __noreturn __kernel die(const char *const message)
;
}
+__kernel void write(const char *const message, size_t n)
+{
+ struct sbi_ret ret = sbi_ecall2(DBCN_EXT, DBCN_WRITE, n, (unsigned long)message);
+ if (ret.error != SBI_SUCCESS) {
+ die(nullptr);
+ }
+}
+
+#ifdef __DEBUG__
+__kernel void print_task_prefix(void)
+{
+ register struct task_struct *current asm("tp");
+
+ if (!current) {
+ return;
+ }
+
+ size_t len = strlen(current->name);
+ if (!len) {
+ return;
+ }
+
+ write("[=> ", 4);
+ write(current->name, len);
+ write("] ", 2);
+}
+#endif
+
__kernel void printk(const char *const message)
{
+#ifdef __DEBUG__
+ print_task_prefix();
+#endif
+
size_t len = strlen(message);
if (!len) {
return;
@@ -22,10 +55,11 @@ __kernel void printk(const char *const message)
write(message, len);
}
-__kernel void write(const char *const message, size_t n)
+__kernel void sys_write(const char *const message, size_t n)
{
- struct sbi_ret ret = sbi_ecall2(DBCN_EXT, DBCN_WRITE, n, (unsigned long)message);
- if (ret.error != SBI_SUCCESS) {
- die(nullptr);
- }
+#ifdef __DEBUG__
+ print_task_prefix();
+#endif
+
+ write(message, n);
}
diff --git a/kernel/trap.c b/kernel/trap.c
index 54bf6aa..29f1c21 100644
--- a/kernel/trap.c
+++ b/kernel/trap.c
@@ -52,7 +52,7 @@ __kernel __always_inline void exception_handler(uint64_t cause)
die("Bad syscall\n");
}
- write(message, n);
+ sys_write(message, n);
}
/*
@@ -75,7 +75,7 @@ __aligned(4) __s_interrupt __kernel void interrupt_handler(void)
if (IS_EXCEPTION(cause)) {
exception_handler(cause);
- set_return_address_to(TASK_INIT);
+ prepare_switch_to(TASK_INIT);
goto end;
}
@@ -91,11 +91,11 @@ __aligned(4) __s_interrupt __kernel void interrupt_handler(void)
// BEHOLD! The fizz buzz logic! :D
seconds_elapsed += 1;
if ((seconds_elapsed % 15) == 0) {
- set_return_address_to(TASK_FIZZBUZZ);
+ prepare_switch_to(TASK_FIZZBUZZ);
} else if ((seconds_elapsed % 5) == 0) {
- set_return_address_to(TASK_BUZZ);
+ prepare_switch_to(TASK_BUZZ);
} else if ((seconds_elapsed % 3) == 0) {
- set_return_address_to(TASK_FIZZ);
+ prepare_switch_to(TASK_FIZZ);
}
// Re-enable timer interrupts.