summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2025-12-13 23:21:03 +0800
committerRichard Qin <richard.qin.x@gmail.com>2025-12-13 23:21:03 +0800
commit28fd88e0dd66728b22cd792deb5a1e8636f36ed3 (patch)
tree059cc8350adb68ca994de2c6ccf402895b575d88 /src/kernel
parent27fc7bda593c8bd2c24a334a368772b5f15d4e9e (diff)
downloadlume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.gz
lume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.xz
feat: add preemptive scheduling, SBI timer support and FDT parser.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/config.cc9
-rw-r--r--src/kernel/fdt.cc134
-rw-r--r--src/kernel/main.cc28
-rw-r--r--src/kernel/mm/vm.cc16
-rw-r--r--src/kernel/sbi.cc34
-rw-r--r--src/kernel/timer.cc30
-rw-r--r--src/kernel/trap/handler.cc3
7 files changed, 220 insertions, 34 deletions
diff --git a/src/kernel/config.cc b/src/kernel/config.cc
new file mode 100644
index 0000000..47f7a3e
--- /dev/null
+++ b/src/kernel/config.cc
@@ -0,0 +1,9 @@
+#include "common/types.h"
+
+uint64 g_uart_base = 0;
+// uint64 g_clint_base = 0;
+uint64 g_plic_base = 0;
+uint64 g_ram_start = 0;
+uint64 g_ram_size = 0;
+
+extern "C" uint64 g_dtb_addr; \ No newline at end of file
diff --git a/src/kernel/fdt.cc b/src/kernel/fdt.cc
new file mode 100644
index 0000000..93922a7
--- /dev/null
+++ b/src/kernel/fdt.cc
@@ -0,0 +1,134 @@
+#include "common/types.h"
+#include "drivers/uart.h"
+#include "kernel/config.h"
+
+inline uint32_t bswap(uint32_t x)
+{
+ return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) |
+ ((x & 0xFF0000) >> 8) | ((x >> 24) & 0xFF);
+}
+
+struct fdt_header
+{
+ uint32 magic;
+ uint32 totalsize;
+ uint32 off_dt_struct;
+ uint32 off_dt_strings;
+ uint32 off_mem_rsvmap;
+ uint32 version;
+ uint32 last_comp_version;
+ uint32 boot_cpuid_phys;
+ uint32 size_dt_strings;
+ uint32 size_dt_struct;
+};
+
+#define FDT_MAGIC 0xd00dfeed
+#define FDT_BEGIN_NODE 1
+#define FDT_END_NODE 2
+#define FDT_PROP 3
+#define FDT_NOP 4
+#define FDT_END 9
+
+int strcmp(const char* s1, const char* s2)
+{
+ while (*s1 && (*s1 == *s2))
+ {
+ s1++;
+ s2++;
+ }
+ return *(const unsigned char*)s1 - *(const unsigned char*)s2;
+}
+
+int memcmp(const void *ptr1, const void *ptr2, uint32 num)
+{
+ const unsigned char *p1 = (const unsigned char *)ptr1;
+ const unsigned char *p2 = (const unsigned char *)ptr2;
+ for (uint32 i = 0; i < num; i++)
+ {
+ if (p1[i] != p2[i])
+ return p1[i] - p2[i];
+ }
+ return 0;
+}
+
+void fdt_init(uint64 dtb)
+{
+ if (dtb == 0) return;
+
+ struct fdt_header* header = (struct fdt_header*)dtb;
+ if (bswap(header->magic) != FDT_MAGIC)
+ return;
+
+ uint8* struct_ptr = (uint8*)(dtb + bswap(header->off_dt_struct));
+ char* strings_ptr = (char *)(dtb + bswap(header->off_dt_strings));
+
+ uint64 current_reg_addr = 0;
+
+ while (1)
+ {
+ uint32 token = bswap(*(uint32*)struct_ptr);
+ struct_ptr += 4;
+
+ if(token == FDT_END)break;
+ if(token == FDT_NOP)continue;
+
+ if(token == FDT_BEGIN_NODE)
+ {
+ while (*struct_ptr != 0)struct_ptr++;
+ struct_ptr++;
+ struct_ptr = (uint8*)(((uint64)struct_ptr + 3) & ~3);
+ }
+ else if(token == FDT_END_NODE)
+ {
+
+ }
+ else if (token == FDT_PROP)
+ {
+ uint32 len = bswap(*(uint32*)struct_ptr);
+ struct_ptr += 4;
+ uint32 nameoff = bswap(*(uint32*)struct_ptr);
+ struct_ptr += 4;
+
+ char* name = strings_ptr + nameoff;
+ uint8* data = struct_ptr;
+
+ struct_ptr += len;
+ struct_ptr = (uint8*)(((uint64)struct_ptr + 3) & ~3);
+
+ if(strcmp(name, "reg") == 0 && len >= 8)
+ {
+ uint32 hi = bswap(*(uint32*)data);
+ uint32 lo = bswap(*(uint32*)(data + 4));
+ current_reg_addr = ((uint64)hi << 32) | lo;
+ }
+
+ if(strcmp(name, "compatible") == 0)
+ {
+ if (g_uart_base == 0)
+ {
+ for(uint32 i = 0; i < len; i++)
+ {
+ if (data[i] == 'n' && data[i + 1] == 's' && data[i + 2] == '1')
+ {
+ g_uart_base = current_reg_addr;
+ break;
+ }
+ }
+ }
+
+ // if (g_clint_base == 0)
+ // {
+ // for (uint32 i = 0; i < len; i++)
+ // {
+ // if (data[i] == 'c' && data[i + 1] == 'l' && data[i + 2] == 'i' && data[i + 3] == 'n')
+ // {
+ // g_clint_base = current_reg_addr;
+ // break;
+ // }
+ // }
+ // }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/kernel/main.cc b/src/kernel/main.cc
index 5dfba9b..68c0974 100644
--- a/src/kernel/main.cc
+++ b/src/kernel/main.cc
@@ -4,6 +4,9 @@
#include "kernel/trap.h"
#include "kernel/proc.h"
#include "kernel/timer.h"
+#include "kernel/config.h"
+
+void fdt_init(uint64 dtb);
void delay()
{
@@ -19,7 +22,7 @@ void task_a()
{
Drivers::uart_putc('A');
delay();
- ProcManager::yield();
+ // ProcManager::yield();
}
}
@@ -29,7 +32,7 @@ void task_b()
{
Drivers::uart_putc('B');
delay();
- ProcManager::yield();
+ // ProcManager::yield();
}
}
@@ -37,6 +40,7 @@ void task_b()
extern "C" void kernel_main()
{
+ fdt_init(g_dtb_addr);
Drivers::uart_init();
Drivers::uart_puts("\n[Modern DOS Kernel] Booted in S-Mode.\n");
Drivers::uart_puts("2025 Richard Qin\n");
@@ -58,26 +62,14 @@ extern "C" void kernel_main()
Timer::init();
Drivers::uart_puts("[Boot] Timer Interrupt Enabled.\n");
- // Drivers::uart_puts("\n[Test] Triggering Page Fault by reading 0x0...\n");
- // volatile int *p = (int *)0x0;
- // int crash = *p;
- // (void)crash;
-
- // Drivers::uart_puts("[Test Failed] Shuold not reach here.\n");
-
- // Drivers::uart_puts("\n[Test] Triggering Store Fault on Text Segment...\n");
- // *(int*)0x80000000 = 1234;
-
ProcManager::init();
- Drivers::uart_puts("[Boot] Process Manager initialized.\n");
+ Drivers::uart_puts("[Boot] ProcManager Initialized.\n");
+ void task_a();
+ void task_b();
ProcManager::create_kernel_thread(task_a, "Task A");
ProcManager::create_kernel_thread(task_b, "Task B");
+ Drivers::uart_puts("[Kernel] Scheduler Starting...\n");
ProcManager::scheduler();
-
- while (1)
- {
-
- }
} \ No newline at end of file
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
index 8696fdb..8a7068e 100644
--- a/src/kernel/mm/vm.cc
+++ b/src/kernel/mm/vm.cc
@@ -2,6 +2,7 @@
#include "kernel/pmm.h"
#include "drivers/uart.h"
#include "common/types.h"
+#include "kernel/config.h"
extern "C" char text_start[];
extern "C" char text_end[];
@@ -76,9 +77,20 @@ namespace VM
{
kernel_pagetable = (pagetable_t)PMM::alloc_page();
- mappages(kernel_pagetable, 0x10000000, 0x10000, 0x10000000, PTE_R | PTE_W);
+ if (g_uart_base != 0)
+ {
+ mappages(kernel_pagetable, g_uart_base, PGSIZE, g_uart_base, PTE_R | PTE_W);
+ }
+
+ // if (g_clint_base != 0)
+ // {
+ // mappages(kernel_pagetable, g_clint_base, 0x10000, g_clint_base, PTE_R | PTE_W);
+ // }
- mappages(kernel_pagetable, 0x2000000, 0x10000, 0x2000000, PTE_R | PTE_W);
+ if (g_plic_base != 0)
+ {
+ mappages(kernel_pagetable, g_plic_base, 0x400000, g_plic_base, PTE_R | PTE_W);
+ }
mappages(kernel_pagetable, (uint64)text_start, (uint64)text_end - (uint64)text_start,
(uint64)text_start, PTE_R | PTE_X);
diff --git a/src/kernel/sbi.cc b/src/kernel/sbi.cc
new file mode 100644
index 0000000..442d219
--- /dev/null
+++ b/src/kernel/sbi.cc
@@ -0,0 +1,34 @@
+#include "common/types.h"
+
+namespace SBI
+{
+ struct sbiret
+ {
+ long error;
+ long value;
+ };
+
+ struct sbiret sbi_call(int ext, int fid, uint64 arg0, uint64 arg1, uint64 arg2)
+ {
+ struct sbiret ret;
+ register uint64 a0 asm("a0") = arg0;
+ register uint64 a1 asm("a1") = arg1;
+ register uint64 a2 asm("a2") = arg2;
+ register uint64 a6 asm("a6") = fid;
+ register uint64 a7 asm("a7") = ext;
+
+ asm volatile(
+ "ecall"
+ : "=r"(a0), "=r"(a1)
+ : "r"(a0), "r"(a1), "r"(a2), "r"(a6), "r"(a7)
+ : "memory");
+ ret.error = a0;
+ ret.value = a1;
+ return ret;
+ }
+
+ void set_timer(uint64 stime_value)
+ {
+ sbi_call(0x54494D45, 0, stime_value, 0, 0);
+ }
+} \ No newline at end of file
diff --git a/src/kernel/timer.cc b/src/kernel/timer.cc
index 8cb3b0f..fb871d5 100644
--- a/src/kernel/timer.cc
+++ b/src/kernel/timer.cc
@@ -1,25 +1,31 @@
#include "common/types.h"
-#include "kernel/timer.h"
+#include "kernel/config.h"
-#define CLINT_BASE 0x2000000L
-#define CLINT_MTIMECMP(hartid) (CLINT_BASE + 0x4000 + 8 * (hartid))
-#define CLINT_MTIME (CLINT_BASE + 0xBFF8)
+namespace SBI
+{
+ void set_timer(uint64 stime_value);
+}
#define INTERVAL 1000000
-namespace Timer{
- uint64 get_time(){
- return *(volatile uint64*)CLINT_MTIME;
+namespace Timer
+{
+ uint64 get_time()
+ {
+ uint64 time;
+ asm volatile("rdtime %0" : "=r"(time));
+ return time;
}
- void set_next_trigger(){
- uint64 mtime = get_time();
-
- *(volatile uint64 *)CLINT_MTIMECMP(0) = mtime + INTERVAL;
+ void set_next_trigger()
+ {
+ SBI::set_timer(get_time() + INTERVAL);
}
- void init(){
+ void init()
+ {
set_next_trigger();
+
uint64 sie;
asm volatile("csrr %0, sie" : "=r"(sie));
sie |= (1L << 5);
diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc
index ecb6652..df4f202 100644
--- a/src/kernel/trap/handler.cc
+++ b/src/kernel/trap/handler.cc
@@ -45,8 +45,7 @@ namespace Trap
switch (cause_code)
{
case 1:
- Drivers::uart_puts("[IRQ] Software Interrupt\n");
- asm volatile("csrc sip, %0" : : "r"(1 << 1));
+ Drivers::uart_puts("[IRQ] Software Interrupt (Unexpected)\n");
break;
case 5: