diff options
| -rw-r--r-- | include/fbos/printk.h | 2 | ||||
| -rw-r--r-- | include/fbos/sched.h | 22 | ||||
| -rw-r--r-- | kernel/head.S | 6 | ||||
| -rw-r--r-- | kernel/main.c | 8 | ||||
| -rw-r--r-- | kernel/printk.c | 44 | ||||
| -rw-r--r-- | kernel/trap.c | 10 |
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. |
