summaryrefslogtreecommitdiff
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
parent27fc7bda593c8bd2c24a334a368772b5f15d4e9e (diff)
downloadlume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.gz
lume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.xz
feat: add preemptive scheduling, SBI timer support and FDT parser.
-rw-r--r--Makefile2
-rwxr-xr-xbuild/kernel.elfbin20152 -> 20704 bytes
-rw-r--r--build/src/boot/entry.obin1656 -> 1856 bytes
-rw-r--r--build/src/drivers/uart.obin3640 -> 4352 bytes
-rw-r--r--build/src/kernel/config.obin0 -> 1272 bytes
-rw-r--r--build/src/kernel/fdt.obin0 -> 5424 bytes
-rw-r--r--build/src/kernel/main.obin7632 -> 7976 bytes
-rw-r--r--build/src/kernel/mm/vm.obin5544 -> 6288 bytes
-rw-r--r--build/src/kernel/sbi.obin0 -> 1832 bytes
-rw-r--r--build/src/kernel/timer.obin2048 -> 2368 bytes
-rw-r--r--build/src/kernel/trap/handler.obin12168 -> 11992 bytes
-rw-r--r--include/common/types.h4
-rw-r--r--include/kernel/config.h7
-rw-r--r--link.ld2
-rw-r--r--src/boot/entry.S33
-rw-r--r--src/drivers/uart.cc9
-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
23 files changed, 249 insertions, 62 deletions
diff --git a/Makefile b/Makefile
index 23a8620..4f89bac 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ $(BUILD_DIR)/%.o: %.cc
run: $(TARGET)
@echo " QEMU Running..."
- @qemu-system-riscv64 -machine virt -nographic -bios none \
+ @qemu-system-riscv64 -machine virt -nographic \
-kernel $(TARGET) -m 128M
clean:
diff --git a/build/kernel.elf b/build/kernel.elf
index e852a9a..56cd68a 100755
--- a/build/kernel.elf
+++ b/build/kernel.elf
Binary files differ
diff --git a/build/src/boot/entry.o b/build/src/boot/entry.o
index 586b6e4..d007d4e 100644
--- a/build/src/boot/entry.o
+++ b/build/src/boot/entry.o
Binary files differ
diff --git a/build/src/drivers/uart.o b/build/src/drivers/uart.o
index 035b61d..bdbc317 100644
--- a/build/src/drivers/uart.o
+++ b/build/src/drivers/uart.o
Binary files differ
diff --git a/build/src/kernel/config.o b/build/src/kernel/config.o
new file mode 100644
index 0000000..eb2108d
--- /dev/null
+++ b/build/src/kernel/config.o
Binary files differ
diff --git a/build/src/kernel/fdt.o b/build/src/kernel/fdt.o
new file mode 100644
index 0000000..1cc86e9
--- /dev/null
+++ b/build/src/kernel/fdt.o
Binary files differ
diff --git a/build/src/kernel/main.o b/build/src/kernel/main.o
index d14400a..44d666e 100644
--- a/build/src/kernel/main.o
+++ b/build/src/kernel/main.o
Binary files differ
diff --git a/build/src/kernel/mm/vm.o b/build/src/kernel/mm/vm.o
index 85fdd0a..daf1d06 100644
--- a/build/src/kernel/mm/vm.o
+++ b/build/src/kernel/mm/vm.o
Binary files differ
diff --git a/build/src/kernel/sbi.o b/build/src/kernel/sbi.o
new file mode 100644
index 0000000..20dd9de
--- /dev/null
+++ b/build/src/kernel/sbi.o
Binary files differ
diff --git a/build/src/kernel/timer.o b/build/src/kernel/timer.o
index de9a347..4728b8b 100644
--- a/build/src/kernel/timer.o
+++ b/build/src/kernel/timer.o
Binary files differ
diff --git a/build/src/kernel/trap/handler.o b/build/src/kernel/trap/handler.o
index 8c3c3e5..83b27bf 100644
--- a/build/src/kernel/trap/handler.o
+++ b/build/src/kernel/trap/handler.o
Binary files differ
diff --git a/include/common/types.h b/include/common/types.h
index 4a22791..f9f01ca 100644
--- a/include/common/types.h
+++ b/include/common/types.h
@@ -13,4 +13,6 @@ typedef signed long long int64_t;
typedef uint64_t size_t;
typedef uint64_t uintptr_t;
-typedef uint64_t uint64; \ No newline at end of file
+typedef uint64_t uint64;
+typedef uint32_t uint32;
+typedef uint8_t uint8; \ No newline at end of file
diff --git a/include/kernel/config.h b/include/kernel/config.h
new file mode 100644
index 0000000..56a1aa6
--- /dev/null
+++ b/include/kernel/config.h
@@ -0,0 +1,7 @@
+#pragma once
+#include "common/types.h"
+
+extern uint64 g_uart_base;
+extern uint64 g_clint_base;
+extern uint64 g_plic_base;
+extern uint64 g_dtb_addr; \ No newline at end of file
diff --git a/link.ld b/link.ld
index 239d244..2029e8c 100644
--- a/link.ld
+++ b/link.ld
@@ -3,7 +3,7 @@ ENTRY(_start)
SECTIONS
{
- . = 0x80000000;
+ . = 0x80200000;
.text : {
PROVIDE(text_start = .);
diff --git a/src/boot/entry.S b/src/boot/entry.S
index 0ca3b29..c0753c4 100644
--- a/src/boot/entry.S
+++ b/src/boot/entry.S
@@ -1,40 +1,27 @@
+# src/boot/entry.S
.section .text.entry
.global _start
_start:
- csrr t0, mhartid
- bnez t0, .L_park
-
- li t0, 0x1fffffffffffff
- csrw pmpaddr0, t0
- li t0, 0xf
- csrw pmpcfg0, t0
-
- li t0, 0
- li t1, (1 << 11) | (1 << 7)
- csrw mstatus, t1
-
- csrw satp, zero
-
- li t0, 0xffff
- csrw medeleg, t0
- csrw mideleg, t0
-
- la t0, kernel_main
- csrw mepc, t0
+ la t0, g_dtb_addr
+ sd a1, 0(t0)
la sp, stack_top
- mret
+ call kernel_main
.L_park:
wfi
j .L_park
-
.section .bss
.align 4
.global stack_top
stack_base:
.space 4096 * 4
-stack_top: \ No newline at end of file
+stack_top:
+
+.align 8
+.global g_dtb_addr
+g_dtb_addr:
+ .space 8 \ No newline at end of file
diff --git a/src/drivers/uart.cc b/src/drivers/uart.cc
index a81ba3f..367f442 100644
--- a/src/drivers/uart.cc
+++ b/src/drivers/uart.cc
@@ -1,7 +1,8 @@
#include "drivers/uart.h"
#include "common/types.h"
+#include "kernel/config.h"
-#define UART0_BASE 0x10000000L
+// #define UART0_BASE 0x10000000L
#define UART_RBR 0x00 // Receiver Buffer Register (Read)
#define UART_THR 0x00 // Transmitter Holding Register (Write)
@@ -16,11 +17,15 @@
namespace Drivers{
inline volatile uint8_t &reg(uint32_t offset)
{
- return *reinterpret_cast<volatile uint8_t *>(UART0_BASE + offset);
+ return *reinterpret_cast<volatile uint8_t *>(g_uart_base + offset);
}
void uart_init()
{
+
+ if (g_uart_base == 0)
+ return;
+
reg(UART_IER) = 0x00;
reg(UART_LCR) = 0x80;
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: