summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2025-12-11 16:34:51 +0800
committerRichard Qin <richard.qin.x@gmail.com>2025-12-11 16:34:51 +0800
commit27fc7bda593c8bd2c24a334a368772b5f15d4e9e (patch)
treecee97c7b0ba2701be3981b587902e03ba8b85e12
parent497e4a1b2f6f9181518e9887991c0464bd8f6bcf (diff)
downloadlume-27fc7bda593c8bd2c24a334a368772b5f15d4e9e.tar.gz
lume-27fc7bda593c8bd2c24a334a368772b5f15d4e9e.tar.xz
feat:Cooperative Multitasking
-rwxr-xr-xbuild/kernel.elfbin19384 -> 20152 bytes
-rw-r--r--build/src/kernel/main.obin7568 -> 7632 bytes
-rw-r--r--build/src/kernel/mm/vm.obin5472 -> 5544 bytes
-rw-r--r--build/src/kernel/proc/proc.obin0 -> 7016 bytes
-rw-r--r--build/src/kernel/proc/swtch.obin0 -> 1072 bytes
-rw-r--r--build/src/kernel/timer.obin0 -> 2048 bytes
-rw-r--r--build/src/kernel/trap/handler.obin11952 -> 12168 bytes
-rw-r--r--include/kernel/proc.h55
-rw-r--r--include/kernel/timer.h7
-rw-r--r--src/kernel/main.cc101
-rw-r--r--src/kernel/mm/vm.cc2
-rw-r--r--src/kernel/proc/proc.cc113
-rw-r--r--src/kernel/proc/swtch.S34
-rw-r--r--src/kernel/timer.cc28
-rw-r--r--src/kernel/trap/handler.cc6
15 files changed, 294 insertions, 52 deletions
diff --git a/build/kernel.elf b/build/kernel.elf
index 9b56c35..e852a9a 100755
--- a/build/kernel.elf
+++ b/build/kernel.elf
Binary files differ
diff --git a/build/src/kernel/main.o b/build/src/kernel/main.o
index f945e0a..d14400a 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 5a94eec..85fdd0a 100644
--- a/build/src/kernel/mm/vm.o
+++ b/build/src/kernel/mm/vm.o
Binary files differ
diff --git a/build/src/kernel/proc/proc.o b/build/src/kernel/proc/proc.o
new file mode 100644
index 0000000..b0e43d0
--- /dev/null
+++ b/build/src/kernel/proc/proc.o
Binary files differ
diff --git a/build/src/kernel/proc/swtch.o b/build/src/kernel/proc/swtch.o
new file mode 100644
index 0000000..f3443f3
--- /dev/null
+++ b/build/src/kernel/proc/swtch.o
Binary files differ
diff --git a/build/src/kernel/timer.o b/build/src/kernel/timer.o
new file mode 100644
index 0000000..de9a347
--- /dev/null
+++ 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 322d37d..8c3c3e5 100644
--- a/build/src/kernel/trap/handler.o
+++ b/build/src/kernel/trap/handler.o
Binary files differ
diff --git a/include/kernel/proc.h b/include/kernel/proc.h
new file mode 100644
index 0000000..89a3db7
--- /dev/null
+++ b/include/kernel/proc.h
@@ -0,0 +1,55 @@
+#pragma once
+#include "common/types.h"
+
+struct Context
+{
+ uint64 ra;
+ uint64 sp;
+
+ uint64 s0;
+ uint64 s1;
+ uint64 s2;
+ uint64 s3;
+ uint64 s4;
+ uint64 s5;
+ uint64 s6;
+ uint64 s7;
+ uint64 s8;
+ uint64 s9;
+ uint64 s10;
+ uint64 s11;
+};
+
+enum ProcState{
+ UNUSED,
+ USED,
+ SLEEPING,
+ RUNNABLE,
+ RUNNING,
+ ZOMBIE,
+};
+
+struct Proc
+{
+ struct Context context;
+
+ enum ProcState state;
+ int pid;
+
+ void* kstack;
+ char name[16];
+
+ //
+};
+
+inline void intr_on() { asm volatile("csrs sstatus, 0x2"); }
+inline void intr_off() { asm volatile("csrc sstatus, 0x2"); }
+
+namespace ProcManager
+{
+ void init();
+ void scheduler();
+ void yield();
+
+ void create_kernel_thread(void (*func)(), const char *name);
+} \ No newline at end of file
diff --git a/include/kernel/timer.h b/include/kernel/timer.h
new file mode 100644
index 0000000..c35e874
--- /dev/null
+++ b/include/kernel/timer.h
@@ -0,0 +1,7 @@
+#include "common/types.h"
+
+namespace Timer{
+ uint64 get_time();
+ void set_next_trigger();
+ void init();
+} \ No newline at end of file
diff --git a/src/kernel/main.cc b/src/kernel/main.cc
index 2fa10a2..5dfba9b 100644
--- a/src/kernel/main.cc
+++ b/src/kernel/main.cc
@@ -2,20 +2,37 @@
#include "kernel/pmm.h"
#include "kernel/mm.h"
#include "kernel/trap.h"
+#include "kernel/proc.h"
+#include "kernel/timer.h"
-// void print_hex(uint64_t val)
-// {
-// char buf[17];
-// buf[16] = 0;
-// const char *digits = "0123456789ABCDEF";
-// for (int i = 15; i >= 0; i--)
-// {
-// buf[i] = digits[val & 0xf];
-// val >>= 4;
-// }
-// Drivers::uart_puts("0x");
-// Drivers::uart_puts(buf);
-// }
+void delay()
+{
+ for(volatile int i = 0; i < 1000000; i++)
+ {
+
+ }
+}
+
+void task_a()
+{
+ while(1)
+ {
+ Drivers::uart_putc('A');
+ delay();
+ ProcManager::yield();
+ }
+}
+
+void task_b()
+{
+ while (1)
+ {
+ Drivers::uart_putc('B');
+ delay();
+ ProcManager::yield();
+ }
+
+}
extern "C" void kernel_main()
{
@@ -24,39 +41,10 @@ extern "C" void kernel_main()
Drivers::uart_puts("\n[Modern DOS Kernel] Booted in S-Mode.\n");
Drivers::uart_puts("2025 Richard Qin\n");
Drivers::uart_puts("\n");
+ Drivers::uart_puts("\n[Boot] Kernel started.\n");
- Drivers::uart_puts("[Kernel] Initializing PMM...\n");
PMM::init();
- Drivers::uart_puts("[Kernel] PMM initialized.\n");
-
- Drivers::uart_puts("[Kernel] Testing alloc_page...\n");
- void *p1 = PMM::alloc_page();
- void *p2 = PMM::alloc_page();
-
- Drivers::uart_puts("Allocated Page 1: ");
- Drivers::print_hex((uint64_t)p1);
- Drivers::uart_puts("\n");
-
- Drivers::uart_puts("Allocated Page 2: ");
- Drivers::print_hex((uint64_t)p2);
- Drivers::uart_puts("\n");
-
- Drivers::uart_puts("[Kernel] Freeing Page 1...\n");
- PMM::free_page(p1);
-
- void *p3 = PMM::alloc_page();
- Drivers::uart_puts("Allocated Page 3: ");
- Drivers::print_hex((uint64_t)p3);
- Drivers::uart_puts("\n");
-
- if (p3 == p1)
- {
- Drivers::uart_puts("[Test Passed] Reuse freed memory successfully.\n");
- }
- else
- {
- Drivers::uart_puts("[Test Failed] Memory leak or logic error.\n");
- }
+ Drivers::uart_puts("[Boot] PMM initialized.\n");
VM::kvminit();
Drivers::uart_puts("[Boot] Kernel page table created.\n");
@@ -67,15 +55,26 @@ extern "C" void kernel_main()
Trap::init();
Drivers::uart_puts("[Boot] Trap Handler Installed.\n");
- Drivers::uart_puts("\n[Test] Triggering Page Fault by reading 0x0...\n");
- volatile int *p = (int *)0x0;
- int crash = *p;
- (void)crash;
+ 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("[Test Failed] Shuold not reach here.\n");
+ ProcManager::create_kernel_thread(task_a, "Task A");
+ ProcManager::create_kernel_thread(task_b, "Task B");
- Drivers::uart_puts("\n[Test] Triggering Store Fault on Text Segment...\n");
- *(int*)0x80000000 = 1234;
+ ProcManager::scheduler();
while (1)
{
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
index 3c14d40..8696fdb 100644
--- a/src/kernel/mm/vm.cc
+++ b/src/kernel/mm/vm.cc
@@ -78,6 +78,8 @@ namespace VM
mappages(kernel_pagetable, 0x10000000, 0x10000, 0x10000000, PTE_R | PTE_W);
+ mappages(kernel_pagetable, 0x2000000, 0x10000, 0x2000000, 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/proc/proc.cc b/src/kernel/proc/proc.cc
new file mode 100644
index 0000000..469b7eb
--- /dev/null
+++ b/src/kernel/proc/proc.cc
@@ -0,0 +1,113 @@
+#include "kernel/proc.h"
+#include "kernel/pmm.h"
+#include "drivers/uart.h"
+
+#define NPROC 10
+
+void str_copy(char *dst, const char *src)
+{
+ while (*src)
+ *dst++ = *src++;
+ *dst = 0;
+}
+
+extern "C" void swtch(struct Context *old_ctx, struct Context *new_ctx);
+
+struct Proc procs[NPROC];
+struct Context main_context;
+
+namespace ProcManager
+{
+ void init()
+ {
+ for (int i = 0; i < NPROC; i++)
+ {
+ procs[i].state = UNUSED;
+ }
+ }
+
+ void create_kernel_thread(void (*func)(), const char *name)
+ {
+ struct Proc *p = nullptr;
+ for(int i = 0; i < NPROC; i++)
+ {
+ if(procs[i].state == UNUSED)
+ {
+ p = &procs[i];
+ p->pid = i + 1;
+ break;
+ }
+ }
+
+ if (!p)
+ {
+ Drivers::uart_puts("Error: No free process slots!\n");
+ return;
+ }
+
+ p->kstack = PMM::alloc_page();
+ if (!p->kstack)
+ {
+ Drivers::uart_puts("Error: Alloc kstack failed!\n");
+ return;
+ }
+
+ p->context.ra = (uint64)func;
+
+ p->context.sp = (uint64)p->kstack + 4096;
+
+ p->state = RUNNABLE;
+ str_copy(p->name, name);
+
+ Drivers::uart_puts("[Proc] Created thread: ");
+ Drivers::uart_puts(name);
+ Drivers::uart_puts("\n");
+ }
+
+ void yield()
+ {
+ struct Proc *p = nullptr;
+ for(int i = 0; i < NPROC; i++)
+ {
+ if (procs[i].state == RUNNING)
+ {
+ p = &procs[i];
+ break;
+ }
+ }
+ if(p)
+ {
+ p->state = RUNNABLE;
+ swtch(&p->context, &main_context);
+ }
+ }
+
+ void scheduler()
+ {
+ struct Proc *p = nullptr;
+ Drivers::uart_puts("[Proc] Scheduler started.\n");
+
+ for (;;)
+ {
+ // int nothing_to_run = 1;
+
+ intr_off();
+
+ for (p = procs; p < &procs[NPROC]; p++)
+ {
+ if (p->state == RUNNABLE)
+ {
+ // nothing_to_run = 0;
+
+ p->state = RUNNING;
+
+ intr_on();
+
+ swtch(&main_context, &p->context);
+
+ intr_off();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/kernel/proc/swtch.S b/src/kernel/proc/swtch.S
new file mode 100644
index 0000000..f59de20
--- /dev/null
+++ b/src/kernel/proc/swtch.S
@@ -0,0 +1,34 @@
+.global swtch
+
+swtch:
+ sd ra, 0(a0)
+ sd sp, 8(a0)
+ sd s0, 16(a0)
+ sd s1, 24(a0)
+ sd s2, 32(a0)
+ sd s3, 40(a0)
+ sd s4, 48(a0)
+ sd s5, 56(a0)
+ sd s6, 64(a0)
+ sd s7, 72(a0)
+ sd s8, 80(a0)
+ sd s9, 88(a0)
+ sd s10, 96(a0)
+ sd s11, 104(a0)
+
+ ld ra, 0(a1)
+ ld sp, 8(a1)
+ ld s0, 16(a1)
+ ld s1, 24(a1)
+ ld s2, 32(a1)
+ ld s3, 40(a1)
+ ld s4, 48(a1)
+ ld s5, 56(a1)
+ ld s6, 64(a1)
+ ld s7, 72(a1)
+ ld s8, 80(a1)
+ ld s9, 88(a1)
+ ld s10, 96(a1)
+ ld s11, 104(a1)
+
+ ret
diff --git a/src/kernel/timer.cc b/src/kernel/timer.cc
new file mode 100644
index 0000000..8cb3b0f
--- /dev/null
+++ b/src/kernel/timer.cc
@@ -0,0 +1,28 @@
+#include "common/types.h"
+#include "kernel/timer.h"
+
+#define CLINT_BASE 0x2000000L
+#define CLINT_MTIMECMP(hartid) (CLINT_BASE + 0x4000 + 8 * (hartid))
+#define CLINT_MTIME (CLINT_BASE + 0xBFF8)
+
+#define INTERVAL 1000000
+
+namespace Timer{
+ uint64 get_time(){
+ return *(volatile uint64*)CLINT_MTIME;
+ }
+
+ void set_next_trigger(){
+ uint64 mtime = get_time();
+
+ *(volatile uint64 *)CLINT_MTIMECMP(0) = mtime + INTERVAL;
+ }
+
+ void init(){
+ set_next_trigger();
+ uint64 sie;
+ asm volatile("csrr %0, sie" : "=r"(sie));
+ sie |= (1L << 5);
+ asm volatile("csrw sie, %0" : : "r"(sie));
+ }
+} \ No newline at end of file
diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc
index 9cc19d1..ecb6652 100644
--- a/src/kernel/trap/handler.cc
+++ b/src/kernel/trap/handler.cc
@@ -1,6 +1,9 @@
#include "kernel/trap.h"
#include "common/types.h"
#include "drivers/uart.h"
+#include "kernel/proc.h"
+#include "kernel/timer.h"
+
void panic(const char *s)
{
@@ -48,7 +51,8 @@ namespace Trap
case 5:
Drivers::uart_puts("[IRQ] Timer Interrupt\n");
-
+ Timer::set_next_trigger();
+ ProcManager::yield();
break;
case 9: