summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-01-01 15:04:47 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-01-01 15:04:47 +0800
commit2dde56422dcfb94affee2baffc8d240ad16ad4b2 (patch)
treeaeee8a0dad24ceaca22585f773411e386c8019be /src/kernel
parent0a6815b7143a8ffd0e09777b5fbd12098d8884c2 (diff)
downloadlume-2dde56422dcfb94affee2baffc8d240ad16ad4b2.tar.gz
lume-2dde56422dcfb94affee2baffc8d240ad16ad4b2.tar.xz
dev(device): implement VirtIO
See dev log for detail
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/main.cc7
-rw-r--r--src/kernel/mm/pmm.cc67
-rw-r--r--src/kernel/mm/slab.cc11
-rw-r--r--src/kernel/mm/vm.cc3
-rw-r--r--src/kernel/proc/proc.cc33
-rw-r--r--src/kernel/syscall.cc53
-rw-r--r--src/kernel/trap/handler.cc13
7 files changed, 107 insertions, 80 deletions
diff --git a/src/kernel/main.cc b/src/kernel/main.cc
index 081ab3e..6e3bdde 100644
--- a/src/kernel/main.cc
+++ b/src/kernel/main.cc
@@ -1,6 +1,8 @@
#include "common/types.h"
#include "kernel/riscv.h"
#include "drivers/uart.h"
+#include "drivers/plic.h"
+#include "drivers/virtio.h"
#include "kernel/pmm.h"
#include "kernel/mm.h"
#include "kernel/proc.h"
@@ -8,7 +10,6 @@
#include "kernel/timer.h"
#include "kernel/cpu.h"
-// 引用外部 FDT 初始化函数
extern void fdt_init(uint64 dtb);
extern uint64 g_dtb_addr;
@@ -30,6 +31,9 @@ extern "C" void kernel_main(uint64 hartid, uint64 dtb)
VM::kvminithart(); // Enable MMU
Trap::init(); // Trap Management
Trap::inithart();
+ PLIC::init();
+ PLIC::inithart();
+ VirtIO::init();
Timer::init();
ProcManager::init(); // Process Management
ProcManager::user_init(); // Initialize first user process
@@ -45,6 +49,7 @@ extern "C" void kernel_main(uint64 hartid, uint64 dtb)
VM::kvminithart();
Trap::inithart();
+ PLIC::inithart();
Timer::init();
Drivers::uart_puts("[Boot] Hart started.\n");
}
diff --git a/src/kernel/mm/pmm.cc b/src/kernel/mm/pmm.cc
index 09bd65b..3474a49 100644
--- a/src/kernel/mm/pmm.cc
+++ b/src/kernel/mm/pmm.cc
@@ -9,73 +9,6 @@
extern "C" char kernel_end[];
extern uint64 g_dtb_addr;
-// 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;
-// }
-// }
-
namespace PMM
{
// Global metadata array pointer
diff --git a/src/kernel/mm/slab.cc b/src/kernel/mm/slab.cc
index 370074a..702dc5c 100644
--- a/src/kernel/mm/slab.cc
+++ b/src/kernel/mm/slab.cc
@@ -19,6 +19,7 @@ struct SlabHeader
uint16 used_count; // Number of allocated objects
// Followed immediately by object data...
// The free list of objects is embedded in the first 2 bytes of the object itself (stores the index of the next object)
+ uint32 padding;
};
struct KmemCache
@@ -82,6 +83,7 @@ namespace Slab
slab->next = nullptr;
slab->used_count = 0;
slab->free_idx = 0;
+ slab->padding = 0;
// Initialize the free list of objects
// The starting position of each object stores the index of the next object
@@ -186,7 +188,7 @@ namespace Slab
if (!page)
return;
- if (!(page->flags & PG_slab))
+ if (!page || !(page->flags & PG_slab))
{
PMM::free_pages(ptr, page->order);
return;
@@ -204,6 +206,13 @@ namespace Slab
struct SlabHeader *slab = (struct SlabHeader *)PGROUNDDOWN((uint64)ptr);
+ if ((uint64)ptr < (uint64)(slab + 1) || (uint64)ptr >= (uint64)slab + PGSIZE)
+ {
+ Drivers::uart_puts("Slab: kfree invalid pointer\n");
+ c->lock.release();
+ return;
+ }
+
char *base = (char *)(slab + 1);
int obj_idx = ((uint64)ptr - (uint64)base) / c->obj_size;
diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc
index c3c5f01..7057d88 100644
--- a/src/kernel/mm/vm.cc
+++ b/src/kernel/mm/vm.cc
@@ -360,11 +360,10 @@ namespace VM
{
kernel_pagetable = uvmcreate();
- kvmmap(0x10000000, 0x10000000, PGSIZE, PTE_R | PTE_W);
+ kvmmap(0x10000000, 0x10000000, 0x10000, PTE_R | PTE_W);
kvmmap(0x0c000000, 0x0c000000, 0x400000, PTE_R | PTE_W);
kvmmap(0x02000000, 0x02000000, 0x10000, PTE_R | PTE_W); // CLINT
kvmmap(KERNBASE, KERNBASE, PHYSTOP - KERNBASE, PTE_R | PTE_W | PTE_X);
- // kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
}
void kvminithart()
diff --git a/src/kernel/proc/proc.cc b/src/kernel/proc/proc.cc
index e99b83d..c8b6d1d 100644
--- a/src/kernel/proc/proc.cc
+++ b/src/kernel/proc/proc.cc
@@ -471,7 +471,6 @@ namespace ProcManager
int wait(uint64 addr)
{
- (void)addr;
struct Proc *np;
int havekids, pid;
@@ -499,6 +498,11 @@ namespace ProcManager
}
pid = np->pid;
+ if (addr != 0 && VM::copyout(p->pagetable, addr, (char *)&np->xstate, sizeof(np->xstate)) < 0)
+ {
+ proc_mem_lock.release();
+ return -1;
+ }
freeproc(np);
proc_mem_lock.release();
return pid;
@@ -509,8 +513,33 @@ namespace ProcManager
if (!havekids || p->state == ZOMBIE)
return -1;
- sleep(p, nullptr);
+ sleep(p, &proc_mem_lock);
+ }
+ }
+
+ int growproc(int n)
+ {
+ uint64 sz;
+ struct Proc *p = myproc();
+
+ sz = p->sz;
+
+ if (n > 0)
+ {
+ // Call VM::uvmalloc to allocate memory
+ // Parameters: page table, old size, new size, permissions (PTE_W)
+ if ((sz = VM::uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0)
+ {
+ return -1;
+ }
}
+ else if (n < 0)
+ {
+ sz = VM::uvmdealloc(p->pagetable, sz, sz + n);
+ }
+
+ p->sz = sz;
+ return 0;
}
void create_kernel_thread(void (*func)(), const char *name)
diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc
index 1dfec73..837ac2c 100644
--- a/src/kernel/syscall.cc
+++ b/src/kernel/syscall.cc
@@ -3,6 +3,7 @@
#include "kernel/proc.h"
#include "kernel/riscv.h"
#include "drivers/uart.h"
+#include "drivers/virtio.h"
#include "kernel/timer.h"
#include "kernel/mm.h"
#include "kernel/trap.h"
@@ -124,6 +125,42 @@ static uint64_t sys_write()
return static_cast<uint64_t>(-1);
}
+static uint64_t sys_read()
+{
+ int fd;
+ int n;
+ uint64_t p;
+
+ // get param: fd, buf, len
+ if (argint(0, &fd) < 0 || argint(2, &n) < 0)
+ return -1;
+ p = argraw(1);
+
+ if (fd == 0) // stdin
+ {
+ return Drivers::console_read(p, n);
+ }
+ return -1;
+}
+
+static uint64_t sys_sbrk()
+{
+ int n;
+ if (argint(0, &n) < 0)
+ return -1;
+
+ uint64_t addr = myproc()->sz;
+ if (ProcManager::growproc(n) < 0)
+ return -1;
+
+ return addr;
+}
+
+static uint64_t sys_disk_test()
+{
+ VirtIO::test_rw();
+ return 0;
+}
void syscall()
{
@@ -131,15 +168,19 @@ void syscall()
int num = p->tf->a7;
uint64_t ret = static_cast<uint64_t>(-1);
- Drivers::uart_puts("Syscall: ");
- Drivers::print_hex(num);
- Drivers::uart_puts("\n");
+ /* Just For Debug */
+ // Drivers::uart_puts("Syscall: ");
+ // Drivers::print_hex(num);
+ // Drivers::uart_puts("\n");
switch (num)
{
case SYS_write:
ret = sys_write();
break;
+ case SYS_read:
+ ret = sys_read();
+ break;
case SYS_putc:
ret = sys_putc();
break;
@@ -155,6 +196,12 @@ void syscall()
case SYS_getpid:
ret = sys_getpid();
break;
+ case SYS_sbrk:
+ ret = sys_sbrk();
+ break;
+ case SYS_disk_test:
+ ret = sys_disk_test();
+ break;
default:
Drivers::uart_puts("Unknown Syscall ID: ");
Drivers::print_hex(num);
diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc
index d7f78de..c1626cc 100644
--- a/src/kernel/trap/handler.cc
+++ b/src/kernel/trap/handler.cc
@@ -6,6 +6,7 @@
#include "kernel/mm.h"
#include "kernel/timer.h"
#include "drivers/plic.h"
+#include "drivers/virtio.h"
#include "lib/string.h"
@@ -59,20 +60,24 @@ namespace Trap
if (is_interrupt && code == 9)
{
// Supervisor External Interrupt (IRQ 9)
- int irq = PILC::claim();
+ int irq = PLIC::claim();
if (irq == 10)
{
- // uart_intr();
+ Drivers::uart_intr();
+ // Debug
+ // Drivers::uart_puts("[Interrupt] UART Input detected!\n");
}
else if (irq >= 1 && irq <= 8)
{
- // virtio_disk_intr();
+ VirtIO::intr();
+ // Debug
+ // Drivers::uart_puts("[Interrupt] VirtIO disk finished!\n");
}
if (irq > 0)
{
- PILC::complete(irq);
+ PLIC::complete(irq);
}
return 1;