diff options
Diffstat (limited to 'src/kernel')
| -rw-r--r-- | src/kernel/main.cc | 7 | ||||
| -rw-r--r-- | src/kernel/mm/pmm.cc | 67 | ||||
| -rw-r--r-- | src/kernel/mm/slab.cc | 11 | ||||
| -rw-r--r-- | src/kernel/mm/vm.cc | 3 | ||||
| -rw-r--r-- | src/kernel/proc/proc.cc | 33 | ||||
| -rw-r--r-- | src/kernel/syscall.cc | 53 | ||||
| -rw-r--r-- | src/kernel/trap/handler.cc | 13 |
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; |
