aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fbos.ld.S5
-rw-r--r--kernel/head.S17
-rw-r--r--kernel/main.c11
-rw-r--r--kernel/printk.c15
4 files changed, 46 insertions, 2 deletions
diff --git a/kernel/fbos.ld.S b/kernel/fbos.ld.S
index 160a5cb..3bda55b 100644
--- a/kernel/fbos.ld.S
+++ b/kernel/fbos.ld.S
@@ -41,13 +41,16 @@ SECTIONS {
.data : {
*(.data)
}
-
. = ALIGN(8);
.rodata : {
*(.rodata)
}
+ . = ALIGN(8);
+ .sdata : {
+ *(.sdata*)
+ }
. = ALIGN(8);
.bss : {
diff --git a/kernel/head.S b/kernel/head.S
index 74f83d8..b175b89 100644
--- a/kernel/head.S
+++ b/kernel/head.S
@@ -63,6 +63,23 @@ _start_kernel:
// Flush the instruction cache
fence.i
+ // Run the hart lottery. If this is not the first time that it happens, then
+ // stall this hart forever: on this simple kernel we only want one hart
+ // available to avoid SMP shenanigans. See explanation on fbos/init.h.
+ la a3, hart_lottery
+ li a2, 1
+ amoadd.w a3, a2, (a3)
+ beqz a3, .Lhart_proceed
+.Lhart_wait:
+ wfi
+ j .Lhart_wait
+
+.Lhart_proceed:
+ // Store the hart id as we will tamper with the 'a0' register later when
+ // performing the call to `start_kernel`.
+ la a3, hart_id
+ sw a0, 0(a3)
+
// Reset all registers except ra, a0, a1.
li sp, 0
li gp, 0
diff --git a/kernel/main.c b/kernel/main.c
index a2e4d13..822d638 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -5,6 +5,12 @@
#include <fbos/string.h>
#include <fbos/dt.h>
+/*
+ * Data related to harts and set by kernel/head.S. Defined in fbos/init.h.
+ */
+atomic32_t hart_lottery __section(".sdata");
+uint32_t hart_id;
+
// Stack to be used by our processes, which is initialized in head.S.
// "Blasphemy!" I hear you say. "How dare you use the same stack for kernel and
// user space?" It's not like this is some sort of utopian system in which
@@ -52,6 +58,11 @@ __noreturn __kernel void start_kernel(void *dtb)
write("\n", 1);
}
+ // And print the hart ID where this is being run.
+ printk("Running on Hart ID: ");
+ print_digit(hart_id);
+ write("\n", 1);
+
// 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.
diff --git a/kernel/printk.c b/kernel/printk.c
index bd2bcab..1cc68db 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -3,7 +3,7 @@
#include <fbos/string.h>
#include <fbos/sbi.h>
-void __noreturn __kernel die(const char *const message)
+__kernel __noreturn void die(const char *const message)
{
if (message) {
printk(message);
@@ -13,6 +13,19 @@ void __noreturn __kernel die(const char *const message)
;
}
+__kernel void print_digit(uint32_t digit)
+{
+ char buffer[2];
+
+ if (digit > 9) {
+ die("We cannot print numbers with two or more digits :D\n");
+ }
+
+ buffer[0] = '0' + digit;
+ buffer[1] = '\0';
+ write(buffer, 2);
+}
+
__kernel void write(const char *const message, size_t n)
{
struct sbi_ret ret = sbi_ecall2(DBCN_EXT, DBCN_WRITE, n, (unsigned long)message);