diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-13 23:21:03 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-13 23:21:03 +0800 |
| commit | 28fd88e0dd66728b22cd792deb5a1e8636f36ed3 (patch) | |
| tree | 059cc8350adb68ca994de2c6ccf402895b575d88 | |
| parent | 27fc7bda593c8bd2c24a334a368772b5f15d4e9e (diff) | |
| download | lume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.gz lume-28fd88e0dd66728b22cd792deb5a1e8636f36ed3.tar.xz | |
feat: add preemptive scheduling, SBI timer support and FDT parser.
| -rw-r--r-- | Makefile | 2 | ||||
| -rwxr-xr-x | build/kernel.elf | bin | 20152 -> 20704 bytes | |||
| -rw-r--r-- | build/src/boot/entry.o | bin | 1656 -> 1856 bytes | |||
| -rw-r--r-- | build/src/drivers/uart.o | bin | 3640 -> 4352 bytes | |||
| -rw-r--r-- | build/src/kernel/config.o | bin | 0 -> 1272 bytes | |||
| -rw-r--r-- | build/src/kernel/fdt.o | bin | 0 -> 5424 bytes | |||
| -rw-r--r-- | build/src/kernel/main.o | bin | 7632 -> 7976 bytes | |||
| -rw-r--r-- | build/src/kernel/mm/vm.o | bin | 5544 -> 6288 bytes | |||
| -rw-r--r-- | build/src/kernel/sbi.o | bin | 0 -> 1832 bytes | |||
| -rw-r--r-- | build/src/kernel/timer.o | bin | 2048 -> 2368 bytes | |||
| -rw-r--r-- | build/src/kernel/trap/handler.o | bin | 12168 -> 11992 bytes | |||
| -rw-r--r-- | include/common/types.h | 4 | ||||
| -rw-r--r-- | include/kernel/config.h | 7 | ||||
| -rw-r--r-- | link.ld | 2 | ||||
| -rw-r--r-- | src/boot/entry.S | 33 | ||||
| -rw-r--r-- | src/drivers/uart.cc | 9 | ||||
| -rw-r--r-- | src/kernel/config.cc | 9 | ||||
| -rw-r--r-- | src/kernel/fdt.cc | 134 | ||||
| -rw-r--r-- | src/kernel/main.cc | 28 | ||||
| -rw-r--r-- | src/kernel/mm/vm.cc | 16 | ||||
| -rw-r--r-- | src/kernel/sbi.cc | 34 | ||||
| -rw-r--r-- | src/kernel/timer.cc | 30 | ||||
| -rw-r--r-- | src/kernel/trap/handler.cc | 3 |
23 files changed, 249 insertions, 62 deletions
@@ -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 Binary files differindex e852a9a..56cd68a 100755 --- a/build/kernel.elf +++ b/build/kernel.elf diff --git a/build/src/boot/entry.o b/build/src/boot/entry.o Binary files differindex 586b6e4..d007d4e 100644 --- a/build/src/boot/entry.o +++ b/build/src/boot/entry.o diff --git a/build/src/drivers/uart.o b/build/src/drivers/uart.o Binary files differindex 035b61d..bdbc317 100644 --- a/build/src/drivers/uart.o +++ b/build/src/drivers/uart.o diff --git a/build/src/kernel/config.o b/build/src/kernel/config.o Binary files differnew file mode 100644 index 0000000..eb2108d --- /dev/null +++ b/build/src/kernel/config.o diff --git a/build/src/kernel/fdt.o b/build/src/kernel/fdt.o Binary files differnew file mode 100644 index 0000000..1cc86e9 --- /dev/null +++ b/build/src/kernel/fdt.o diff --git a/build/src/kernel/main.o b/build/src/kernel/main.o Binary files differindex d14400a..44d666e 100644 --- a/build/src/kernel/main.o +++ b/build/src/kernel/main.o diff --git a/build/src/kernel/mm/vm.o b/build/src/kernel/mm/vm.o Binary files differindex 85fdd0a..daf1d06 100644 --- a/build/src/kernel/mm/vm.o +++ b/build/src/kernel/mm/vm.o diff --git a/build/src/kernel/sbi.o b/build/src/kernel/sbi.o Binary files differnew file mode 100644 index 0000000..20dd9de --- /dev/null +++ b/build/src/kernel/sbi.o diff --git a/build/src/kernel/timer.o b/build/src/kernel/timer.o Binary files differindex de9a347..4728b8b 100644 --- a/build/src/kernel/timer.o +++ b/build/src/kernel/timer.o diff --git a/build/src/kernel/trap/handler.o b/build/src/kernel/trap/handler.o Binary files differindex 8c3c3e5..83b27bf 100644 --- a/build/src/kernel/trap/handler.o +++ b/build/src/kernel/trap/handler.o 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 @@ -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 ®(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: |
