summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot/entry.S46
-rw-r--r--src/kernel/main.cc56
-rw-r--r--src/kernel/mm/pmm.cc71
-rw-r--r--src/kernel/mm/vm.cc100
4 files changed, 253 insertions, 20 deletions
diff --git a/src/boot/entry.S b/src/boot/entry.S
index 1a6f6b8..0ca3b29 100644
--- a/src/boot/entry.S
+++ b/src/boot/entry.S
@@ -1,28 +1,40 @@
.section .text.entry
-.globl _start
+.global _start
_start:
csrr t0, mhartid
- bnez t0, .L_park_harts
+ bnez t0, .L_park
- la sp, _stack_top
+ li t0, 0x1fffffffffffff
+ csrw pmpaddr0, t0
+ li t0, 0xf
+ csrw pmpcfg0, t0
- la a0, _bss_start
- la a1, _bss_end
- bge a0, a1, .L_call_main
+ li t0, 0
+ li t1, (1 << 11) | (1 << 7)
+ csrw mstatus, t1
-.L_clear_bss:
- sd zero, (a0)
- addi a0, a0, 8
- blt a0, a1, .L_clear_bss
+ csrw satp, zero
-.L_call_main:
- call kernel_main
+ li t0, 0xffff
+ csrw medeleg, t0
+ csrw mideleg, t0
+
+ la t0, kernel_main
+ csrw mepc, t0
-.L_infinite_loop:
- wfi
- j .L_infinite_loop
+ la sp, stack_top
+
+ mret
-.L_park_harts:
+.L_park:
wfi
- j .L_park_harts \ No newline at end of file
+ j .L_park
+
+
+.section .bss
+.align 4
+.global stack_top
+stack_base:
+ .space 4096 * 4
+stack_top: \ No newline at end of file
diff --git a/src/kernel/main.cc b/src/kernel/main.cc
index 49adf2b..beda9dc 100644
--- a/src/kernel/main.cc
+++ b/src/kernel/main.cc
@@ -1,17 +1,67 @@
#include "drivers/uart.h"
+#include "kernel/pmm.h"
+#include "kernel/mm.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);
+}
extern "C" void kernel_main()
{
Drivers::uart_init();
+ 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("[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: ");
+ print_hex((uint64_t)p1);
Drivers::uart_puts("\n");
- Drivers::uart_puts("Modern DOS v1.0 [RISC-V 64]\n");
- Drivers::uart_puts("2025 Richard Qin\n");
+
+ Drivers::uart_puts("Allocated Page 2: ");
+ print_hex((uint64_t)p2);
Drivers::uart_puts("\n");
- Drivers::uart_puts("A:\\> ");
+ Drivers::uart_puts("[Kernel] Freeing Page 1...\n");
+ PMM::free_page(p1);
+
+ void *p3 = PMM::alloc_page();
+ Drivers::uart_puts("Allocated Page 3: ");
+ 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");
+ }
+
+ VM::kvminit();
+ Drivers::uart_puts("[Boot] Kernel page table created.\n");
+ VM::kvminithart();
+ Drivers::uart_puts("[Boot] MMU ENABLED! We are now using virtual addresses.\n");
while (1)
{
diff --git a/src/kernel/mm/pmm.cc b/src/kernel/mm/pmm.cc
new file mode 100644
index 0000000..9b68fcd
--- /dev/null
+++ b/src/kernel/mm/pmm.cc
@@ -0,0 +1,71 @@
+#include "kernel/pmm.h"
+#include "drivers/uart.h"
+
+extern "C" char kernel_end[];
+
+namespace PMM
+{
+ struct Run
+ {
+ struct Run *next;
+ };
+
+ struct
+ {
+ struct Run *freelist;
+ } kmem;
+
+ inline uint64_t PGROUNDUP(uint64_t a)
+ {
+ return (a + PGSIZE - 1) & ~(PGSIZE - 1);
+ }
+
+ void init()
+ {
+ uint64_t start = PGROUNDUP((uint64_t)kernel_end);
+
+ Drivers::uart_puts("PMM: Initializing from");
+
+ for (uint64_t p = start; p + PGSIZE <= PHYSTOP; p += PGSIZE)
+ {
+ free_page((void *)p);
+ }
+ }
+
+ void free_page(void* pa)
+ {
+ struct Run *r;
+ if (((uint64_t)pa % PGSIZE) != 0 || (uint64_t)pa < (uint64_t)kernel_end || (uint64_t)pa >= PHYSTOP)
+ {
+ Drivers::uart_puts("PMM: Error - Invalid free address\n");
+ return;
+ }
+ r = (struct Run*)pa;
+
+ r->next = kmem.freelist;
+ kmem.freelist = r;
+
+ }
+
+ void* alloc_page()
+ {
+ struct Run* r;
+
+ r = kmem.freelist;
+ if (r)
+ {
+ kmem.freelist = r->next;
+
+ uint64_t *p = (uint64_t *)r;
+ for (int i = 0; i < PGSIZE / 8; i++)
+ {
+ p[i] = 0;
+ }
+ }
+ else
+ {
+ Drivers::uart_puts("PMM: Out of memory!\n");
+ }
+ return (void *)r;
+ }
+} \ No newline at end of file
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
new file mode 100644
index 0000000..3c14d40
--- /dev/null
+++ b/src/kernel/mm/vm.cc
@@ -0,0 +1,100 @@
+#include "kernel/mm.h"
+#include "kernel/pmm.h"
+#include "drivers/uart.h"
+#include "common/types.h"
+
+extern "C" char text_start[];
+extern "C" char text_end[];
+extern "C" char rodata_start[];
+extern "C" char rodata_end[];
+extern "C" char data_start[];
+extern "C" char kernel_end[];
+
+namespace VM
+{
+ pagetable_t kernel_pagetable;
+
+ #define PX(level, va) ((((uint64)va) >> (12 + 9 * (level))) & 0x1FF)
+ #define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)
+ #define PTE2PA(pte) (((pte) >> 10) << 12)
+
+ pte_t *walk(pagetable_t pagetable, uint64 va, int alloc)
+ {
+ for (int level = 2; level > 0; level--)
+ {
+ pte_t *pte = &pagetable[PX(level, va)];
+
+ if (*pte & PTE_V)
+ {
+ pagetable = (pagetable_t)PTE2PA(*pte);
+ }
+ else
+ {
+ if (!alloc)
+ return 0;
+
+ pagetable = (pagetable_t)PMM::alloc_page();
+ if (!pagetable)
+ return 0;
+
+ *pte = PA2PTE(pagetable) | PTE_V;
+ }
+ }
+ return &pagetable[PX(0, va)];
+ }
+
+ int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
+ {
+ uint64 a, last;
+ pte_t *pte;
+
+ a = (va / PGSIZE) * PGSIZE;
+ last = ((va + size - 1) / PGSIZE) * PGSIZE;
+
+ for(;;)
+ {
+ if((pte = walk(pagetable, a, 1)) == 0)
+ return -1;
+
+ if (*pte & PTE_V)
+ {
+ Drivers::uart_puts("Remap error\n");
+ return -1;
+ }
+
+ *pte = PA2PTE(pa) | perm | PTE_V;
+
+ if (a == last)
+ break;
+ a += PGSIZE;
+ pa += PGSIZE;
+ }
+ return 0;
+ }
+
+ void kvminit()
+ {
+ kernel_pagetable = (pagetable_t)PMM::alloc_page();
+
+ mappages(kernel_pagetable, 0x10000000, 0x10000, 0x10000000, PTE_R | PTE_W);
+
+ mappages(kernel_pagetable, (uint64)text_start, (uint64)text_end - (uint64)text_start,
+ (uint64)text_start, PTE_R | PTE_X);
+
+ mappages(kernel_pagetable, (uint64)data_start, PHYSTOP - (uint64)data_start,
+ (uint64)data_start, PTE_R | PTE_W);
+
+ mappages(kernel_pagetable, (uint64)rodata_start, (uint64)rodata_end - (uint64)rodata_start,
+ (uint64)rodata_start, PTE_R);
+
+ }
+ void kvminithart()
+ {
+ asm volatile("sfence.vma zero, zero");
+
+ uint64 satp_val = MAKE_SATP(kernel_pagetable);
+ asm volatile("csrw satp, %0" : : "r"(satp_val));
+
+ asm volatile("sfence.vma zero, zero");
+ }
+} \ No newline at end of file