diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-28 00:48:24 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-28 00:48:24 +0800 |
| commit | a82ab8ad6d277ededc128678aebabf5fbdb01c45 (patch) | |
| tree | 71d1d333d45e7272ba79a1868942dc710f673ff3 | |
| parent | 7ececbe2818510a8acaa2a2e513085c768b14d15 (diff) | |
| download | lume-a82ab8ad6d277ededc128678aebabf5fbdb01c45.tar.gz lume-a82ab8ad6d277ededc128678aebabf5fbdb01c45.tar.xz | |
feat(syscall): Implement syscall dispatch and process lifecycle (exit/wait/sleep)
| -rwxr-xr-x | build/kernel.elf | bin | 38080 -> 39464 bytes | |||
| -rw-r--r-- | build/src/boot/entry.o | bin | 1856 -> 1864 bytes | |||
| -rw-r--r-- | build/src/kernel/fdt.o | bin | 5424 -> 4560 bytes | |||
| -rw-r--r-- | build/src/kernel/mm/vm.o | bin | 21120 -> 20008 bytes | |||
| -rw-r--r-- | build/src/kernel/proc/proc.o | bin | 12968 -> 24808 bytes | |||
| -rw-r--r-- | build/src/kernel/spinlock.o | bin | 0 -> 6968 bytes | |||
| -rw-r--r-- | build/src/kernel/syscall.o | bin | 0 -> 11168 bytes | |||
| -rw-r--r-- | build/src/kernel/trap/handler.o | bin | 14200 -> 13992 bytes | |||
| -rw-r--r-- | build/src/lib/string.o | bin | 0 -> 4136 bytes | |||
| -rw-r--r-- | include/kernel/proc.h | 12 | ||||
| -rw-r--r-- | include/kernel/spinlock.h | 20 | ||||
| -rw-r--r-- | include/kernel/syscall.h | 26 | ||||
| -rw-r--r-- | include/lib/string.h | 13 | ||||
| -rw-r--r-- | src/boot/entry.S | 2 | ||||
| -rw-r--r-- | src/kernel/fdt.cc | 22 | ||||
| -rw-r--r-- | src/kernel/mm/vm.cc | 27 | ||||
| -rw-r--r-- | src/kernel/proc/proc.cc | 293 | ||||
| -rw-r--r-- | src/kernel/spinlock.cc | 107 | ||||
| -rw-r--r-- | src/kernel/syscall.cc | 133 | ||||
| -rw-r--r-- | src/kernel/trap/handler.cc | 35 | ||||
| -rw-r--r-- | src/lib/string.cc | 71 |
21 files changed, 633 insertions, 128 deletions
diff --git a/build/kernel.elf b/build/kernel.elf Binary files differindex 6c0500e..996720e 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 d007d4e..2398fda 100644 --- a/build/src/boot/entry.o +++ b/build/src/boot/entry.o diff --git a/build/src/kernel/fdt.o b/build/src/kernel/fdt.o Binary files differindex 1cc86e9..2dd29e3 100644 --- a/build/src/kernel/fdt.o +++ b/build/src/kernel/fdt.o diff --git a/build/src/kernel/mm/vm.o b/build/src/kernel/mm/vm.o Binary files differindex 0da8294..36c27e4 100644 --- a/build/src/kernel/mm/vm.o +++ b/build/src/kernel/mm/vm.o diff --git a/build/src/kernel/proc/proc.o b/build/src/kernel/proc/proc.o Binary files differindex 2954378..f4bbe8f 100644 --- a/build/src/kernel/proc/proc.o +++ b/build/src/kernel/proc/proc.o diff --git a/build/src/kernel/spinlock.o b/build/src/kernel/spinlock.o Binary files differnew file mode 100644 index 0000000..96b62d9 --- /dev/null +++ b/build/src/kernel/spinlock.o diff --git a/build/src/kernel/syscall.o b/build/src/kernel/syscall.o Binary files differnew file mode 100644 index 0000000..3c89cd0 --- /dev/null +++ b/build/src/kernel/syscall.o diff --git a/build/src/kernel/trap/handler.o b/build/src/kernel/trap/handler.o Binary files differindex 744b920..88daa0e 100644 --- a/build/src/kernel/trap/handler.o +++ b/build/src/kernel/trap/handler.o diff --git a/build/src/lib/string.o b/build/src/lib/string.o Binary files differnew file mode 100644 index 0000000..bceb813 --- /dev/null +++ b/build/src/lib/string.o diff --git a/include/kernel/proc.h b/include/kernel/proc.h index 559b137..b557267 100644 --- a/include/kernel/proc.h +++ b/include/kernel/proc.h @@ -1,6 +1,7 @@ #pragma once #include "common/types.h" #include "kernel/trap.h" +#include "kernel/spinlock.h" struct Context { @@ -44,7 +45,9 @@ struct Proc char name[16]; uint64 sz; - // + struct Proc *parent; + void *chan; + int xstate; }; @@ -57,8 +60,13 @@ namespace ProcManager void create_kernel_thread(void (*func)(), const char *name); void user_init(); + void exit(int status); + int wait(uint64 addr); + void sleep(void *chan, struct spinlock *lk); + void wakeup(void *chan); } void forkret(); struct Proc *myproc(); -void usertrapret();
\ No newline at end of file +void usertrapret(); +int fork();
\ No newline at end of file diff --git a/include/kernel/spinlock.h b/include/kernel/spinlock.h new file mode 100644 index 0000000..aec4b6a --- /dev/null +++ b/include/kernel/spinlock.h @@ -0,0 +1,20 @@ +#pragma once +#include "common/types.h" + +struct spinlock +{ + uint locked; + + char *name; + int cpu_id; +}; + +namespace Spinlock +{ + void init(struct spinlock *lk, char *name); + void acquire(struct spinlock *lk); + void release(struct spinlock *lk); + int holding(struct spinlock *lk); + void push_off(); + void pop_off(); +}
\ No newline at end of file diff --git a/include/kernel/syscall.h b/include/kernel/syscall.h new file mode 100644 index 0000000..571741e --- /dev/null +++ b/include/kernel/syscall.h @@ -0,0 +1,26 @@ +#pragma once + +#define SYS_putc 1 +#define SYS_fork 2 +#define SYS_exit 3 +#define SYS_wait 4 +#define SYS_pipe 5 +#define SYS_read 6 +#define SYS_kill 7 +#define SYS_exec 8 +#define SYS_fstat 9 +#define SYS_chdir 10 +#define SYS_dup 11 +#define SYS_getpid 12 +#define SYS_sbrk 13 +#define SYS_sleep 14 +#define SYS_uptime 15 +#define SYS_open 16 +#define SYS_write 17 +#define SYS_mknod 18 +#define SYS_unlink 19 +#define SYS_link 20 +#define SYS_mkdir 21 +#define SYS_close 22 + +void syscall();
\ No newline at end of file diff --git a/include/lib/string.h b/include/lib/string.h new file mode 100644 index 0000000..aa87489 --- /dev/null +++ b/include/lib/string.h @@ -0,0 +1,13 @@ +#pragma once +#include "common/types.h" + + +void *memset(void *dst, int c, uint n); +int memcmp(const void *v1, const void *v2, uint n); +void *memmove(void *dst, const void *src, uint n); +void *memcpy(void *dst, const void *src, uint n); + + +void strcpy(char *dst, const char *src); +int strlen(const char *s); +int strcmp(const char *s1, const char *s2);
\ No newline at end of file diff --git a/src/boot/entry.S b/src/boot/entry.S index a3c212a..924d7d6 100644 --- a/src/boot/entry.S +++ b/src/boot/entry.S @@ -5,6 +5,8 @@ _start: la t0, g_dtb_addr sd a1, 0(t0) + mv tp, a0 + la sp, stack_top call kernel_main diff --git a/src/kernel/fdt.cc b/src/kernel/fdt.cc index 93922a7..1863086 100644 --- a/src/kernel/fdt.cc +++ b/src/kernel/fdt.cc @@ -1,6 +1,7 @@ #include "common/types.h" #include "drivers/uart.h" #include "kernel/config.h" +#include "lib/string.h" inline uint32_t bswap(uint32_t x) { @@ -29,27 +30,6 @@ struct fdt_header #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) { diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc index a38ee84..735a486 100644 --- a/src/kernel/mm/vm.cc +++ b/src/kernel/mm/vm.cc @@ -4,33 +4,8 @@ #include "drivers/uart.h" #include "common/types.h" #include "kernel/config.h" +#include "lib/string.h" -void *memset(void *dst, int c, uint n) -{ - char *cdst = (char *)dst; - for (uint i = 0; i < n; i++) - cdst[i] = c; - return dst; -} - -void *memmove(void *dst, const void *src, uint n) -{ - const char *s = (const char *)src; - char *d = (char *)dst; - if (s < d && s + n > d) - { - s += n; - d += n; - while (n-- > 0) - *--d = *--s; - } - else - { - while (n-- > 0) - *d++ = *s++; - } - return dst; -} extern char text_start[]; extern char text_end[]; diff --git a/src/kernel/proc/proc.cc b/src/kernel/proc/proc.cc index 1240bee..15a28b4 100644 --- a/src/kernel/proc/proc.cc +++ b/src/kernel/proc/proc.cc @@ -6,6 +6,8 @@ #include "common/types.h" #include "kernel/riscv.h" #include "kernel/config.h" +#include "kernel/spinlock.h" +#include "lib/string.h" #define NPROC 10 @@ -13,18 +15,14 @@ extern "C" void swtch(struct Context *old_ctx, struct Context *new_ctx); extern char uservec[]; extern "C" void userret(uint64, uint64); extern char trampoline[]; -extern void *memset(void *dst, int c, uint n); struct Proc procs[NPROC]; struct Context main_context; struct Proc *current_proc = nullptr; +struct spinlock proc_lock; + +int nextpid = 1; -void str_copy(char *dst, const char *src) -{ - while (*src) - *dst++ = *src++; - *dst = 0; -} uchar initcode[] = { 0x13, 0x05, 0x50, 0x05, // li a0, 85 ('U') @@ -35,6 +33,7 @@ uchar initcode[] = { struct Proc *myproc() { + // 简化处理 return current_proc; } @@ -42,10 +41,10 @@ void usertrapret() { struct Proc *p = myproc(); - asm volatile("csrc sstatus, %0" : : "r"(SSTATUS_SIE)); + intr_off(); uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline); - asm volatile("csrw stvec, %0" : : "r"(trampoline_uservec)); + w_stvec(trampoline_uservec); p->tf->kernel_satp = r_satp(); p->tf->kernel_sp = (uint64)p->kstack + PGSIZE; @@ -68,16 +67,120 @@ void usertrapret() void forkret() { //.... + Spinlock::release(&proc_lock); + Drivers::uart_puts("[Proc] forkret: jumping to user.\n"); + usertrapret(); +} +static Proc *allocproc() +{ + struct Proc* p; + Spinlock::acquire(&proc_lock); + for (p = procs; p < &procs[NPROC]; p++) + { + if (p->state == UNUSED) + { + goto found; + } + } - usertrapret(); + Spinlock::release(&proc_lock); + return 0; + +found: + p->state = USED; + p->pid = nextpid++; + + if ((p->tf = (struct Trapframe *)PMM::alloc_page()) == 0) + { + p->state = UNUSED; + Spinlock::release(&proc_lock); + return 0; + } + if ((p->kstack = PMM::alloc_page()) == 0) + { + PMM::free_page(p->tf); + p->state = UNUSED; + Spinlock::release(&proc_lock); + return 0; + } + memset(p->kstack, 0, PGSIZE); + + memset(&p->context, 0, sizeof(p->context)); + p->context.ra = (uint64)forkret; + p->context.sp = (uint64)p->kstack + PGSIZE; + + Spinlock::release(&proc_lock); + return p; +} + +static void freeproc(struct Proc *p) +{ + if (p->tf) + PMM::free_page(p->tf); + p->tf = 0; + + if (p->kstack) + PMM::free_page(p->kstack); + p->kstack = 0; + + if (p->pagetable) + VM::uvmfree(p->pagetable, p->sz); + p->pagetable = 0; + + p->sz = 0; + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->chan = 0; + p->state = UNUSED; +} + +int fork() +{ + int pid; + struct Proc *np; + struct Proc *p = myproc(); + + if ((np = allocproc()) == 0) + { + return -1; + } + + np->pagetable = VM::uvmcreate(); + if (VM::uvmcopy(p->pagetable, np->pagetable, p->sz) < 0) + { + PMM::free_page(np->kstack); + PMM::free_page(np->tf); + Spinlock::acquire(&proc_lock); + np->state = UNUSED; + Spinlock::release(&proc_lock); + return -1; + } + np->sz = p->sz; + + *(np->tf) = *(p->tf); + + np->tf->a0 = 0; + + strcpy(np->name, p->name); + np->parent = p; + + Spinlock::acquire(&proc_lock); + np->state = RUNNABLE; + pid = np->pid; + Spinlock::release(&proc_lock); + + return pid; } namespace ProcManager { void init() { + Spinlock::init(&proc_lock, "proc"); + for (int i = 0; i < NPROC; i++) { procs[i].state = UNUSED; @@ -116,7 +219,7 @@ namespace ProcManager p->context.sp = (uint64)p->kstack + 4096; p->state = RUNNABLE; - str_copy(p->name, name); + strcpy(p->name, name); Drivers::uart_puts("[Proc] Created thread: "); Drivers::uart_puts(name); @@ -126,11 +229,13 @@ namespace ProcManager void yield() { struct Proc *p = myproc(); + Spinlock::acquire(&proc_lock); if (p && p->state == RUNNING) { p->state = RUNNABLE; swtch(&p->context, &main_context); } + Spinlock::release(&proc_lock); } void scheduler() @@ -140,18 +245,15 @@ namespace ProcManager for (;;) { - int nothing_found = 1; - intr_on(); + Spinlock::acquire(&proc_lock); + for (p = procs; p < &procs[NPROC]; p++) { if (p->state == RUNNABLE) { - nothing_found = 0; - p->state = RUNNING; - current_proc = p; swtch(&main_context, &p->context); @@ -159,80 +261,147 @@ namespace ProcManager current_proc = nullptr; } } - if (nothing_found) - { - asm volatile("wfi"); - } + Spinlock::release(&proc_lock); } } void user_init() { - struct Proc *p = nullptr; - for(int i = 0; i < NPROC; ++i) - { - if(procs[i].state == UNUSED) - { - p = &procs[i]; - p->pid = i + 1; - break; - } - } + struct Proc *p; + p = allocproc(); if (!p) { - Drivers::uart_puts("user_init: no free procs\n"); + Drivers::uart_puts("user_init: failed\n"); return; } - p->kstack = PMM::alloc_page(); - if (p->kstack == 0) + p->pagetable = VM::uvmcreate(); + VM::uvminit(p->pagetable, initcode, sizeof(initcode)); + p->sz = PGSIZE; + + if (VM::mappages(p->pagetable, TRAPFRAME, PGSIZE, + (uint64)p->tf, PTE_R | PTE_W) < 0) { - Drivers::uart_puts("user_init: kstack alloc failed\n"); + Drivers::uart_puts("user_init: map trapframe failed\n"); return; } - p->tf = (struct Trapframe*)PMM::alloc_page(); + + p->tf->epc = 0; + p->tf->sp = PGSIZE; - if (p->tf == 0) + strcpy(p->name, "initcode"); + + + Spinlock::acquire(&proc_lock); + p->state = RUNNABLE; + Spinlock::release(&proc_lock); + + Drivers::uart_puts("[Proc] user_init success. PID: 1\n"); + } + + void sleep(void *chan, struct spinlock *lk) + { + struct Proc *p = myproc(); + if(lk != &proc_lock) { - Drivers::uart_puts("user_init: tf alloc failed\n"); - return; + Drivers::uart_puts("sleep: lock mismatch\n"); + while (1) + ; } - memset(p->tf, 0, PGSIZE); + p->chan = chan; + p->state = SLEEPING; - p->pagetable = VM::uvmcreate(); + swtch(&p->context, &main_context); - // if (VM::mappages(p->pagetable, TRAMPOLINE, PGSIZE, - // (uint64)trampoline, PTE_R | PTE_X) < 0) - // { - // Drivers::uart_puts("user_init: map trampoline failed\n"); - // return; - // } + p->chan = 0; + } - if (VM::mappages(p->pagetable, TRAPFRAME, PGSIZE, - (uint64)p->tf, PTE_R | PTE_W) < 0) + void wakeup(void *chan) + { + for(struct Proc *p = procs; p < &procs[NPROC]; p++) { - Drivers::uart_puts("user_init: map trapframe failed\n"); - return; + if (p->state == SLEEPING && p->chan == chan) + { + p->state = RUNNABLE; + } } + } - VM::uvminit(p->pagetable, initcode, sizeof(initcode)); - p->sz = PGSIZE; + void exit(int status) + { + struct Proc *p = myproc(); + struct Proc *initproc = &procs[0]; - p->tf->epc = 0; - p->tf->sp = PGSIZE; + if (p == initproc) + { + Drivers::uart_puts("init exiting!\n"); + while (1) + ; + } - memset(&p->context, 0, sizeof(p->context)); - p->context.ra = (uint64)forkret; - p->context.sp = (uint64)p->kstack + PGSIZE; + Spinlock::acquire(&proc_lock); - p->state = RUNNABLE; + for (struct Proc *pp = procs; pp < &procs[NPROC]; pp++) + { + if (pp->parent == p) + { + pp->parent = initproc; + wakeup(initproc); + } + } - const char *name = "initcode"; - for (int i = 0; name[i] && i < 15; i++) - p->name[i] = name[i]; + wakeup(p->parent); - Drivers::uart_puts("[Proc] user_init success. PID: 1\n"); + p->xstate = status; + p->state = ZOMBIE; + + swtch(&p->context, &main_context); + + while(1); + } + + int wait(uint64 addr) + { + struct Proc* np; + int havekids, pid; + struct Proc *p = myproc(); + + Spinlock::acquire(&proc_lock); + + for(;;) + { + havekids = 0; + for (np = procs; np < &procs[NPROC]; np++) + { + if (np->parent == p) + { + havekids = 1; + if (np->state == ZOMBIE) + { + // Found one + pid = np->pid; + if (addr != 0) + { + // copyout(p->pagetable, addr, (char*)&np->xstate, sizeof(np->xstate)); + // 暂时不做 copyout + } + freeproc(np); + Spinlock::release(&proc_lock); + return pid; + } + } + } + if (!havekids || p->state == ZOMBIE) + { + Spinlock::release(&proc_lock); + return -1; + } + sleep(p, &proc_lock); + } } + + + }
\ No newline at end of file diff --git a/src/kernel/spinlock.cc b/src/kernel/spinlock.cc new file mode 100644 index 0000000..210e0b9 --- /dev/null +++ b/src/kernel/spinlock.cc @@ -0,0 +1,107 @@ +#include "kernel/spinlock.h" +#include "kernel/riscv.h" +#include "kernel/proc.h" +#include "drivers/uart.h" +#include "common/types.h" + +#define NCPU 8 + +namespace Spinlock +{ + int g_noff[NCPU]; + + int g_intena[NCPU]; + + int cpuid() + { + return r_tp(); + } + + void init(struct spinlock *lk, char* name) + { + lk->name = name; + lk->locked = 0; + lk->cpu_id = -1; + } + + void push_off() + { + int old = intr_get(); + intr_off(); + + int id = cpuid(); + if (g_noff[id] == 0) + { + g_intena[id] = old; + } + g_noff[id] += 1; + } + + void pop_off() + { + int id = cpuid(); + if (intr_get()) + Drivers::uart_puts("pop_off - interruptible\n"); + + if (g_noff[id] < 1) + Drivers::uart_puts("pop_off - count error\n"); + + g_noff[id] -= 1; + + if (g_noff[id] == 0 && g_intena[id]) + { + intr_on(); + } + } + + int holding(struct spinlock *lk) + { + int r; + push_off(); + r = (lk->locked && lk->cpu_id == cpuid()); + pop_off(); + return r; + } + + void acquire(struct spinlock *lk) + { + push_off(); + + if(holding(lk)) + { + Drivers::uart_puts("acquire: panic - recursive lock "); + Drivers::uart_puts(lk->name); + Drivers::uart_puts("\n"); + while (1) + ; + } + + while (__sync_lock_test_and_set(&lk->locked, 1) != 0) + { + // 自旋等待 + } + + __sync_synchronize(); + + lk->cpu_id = cpuid(); + } + + void release(struct spinlock *lk) + { + if (!holding(lk)) + { + Drivers::uart_puts("release: panic - not holding\n"); + while (1) + ; + } + + lk->cpu_id = -1; + + __sync_synchronize(); + + __sync_lock_release(&lk->locked); + + pop_off(); + } + +} // namespace Spinlock diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc new file mode 100644 index 0000000..97b283b --- /dev/null +++ b/src/kernel/syscall.cc @@ -0,0 +1,133 @@ +#include "kernel/syscall.h" +#include "common/types.h" +#include "kernel/proc.h" +#include "kernel/riscv.h" +#include "drivers/uart.h" +#include "kernel/timer.h" + +extern int fork(); + +namespace ProcManager +{ + void exit(int status); + int wait(uint64 addr); +} + +uint64 argraw(int n) +{ + struct Proc *p = myproc(); + switch (n) + { + case 0: + return p->tf->a0; + case 1: + return p->tf->a1; + case 2: + return p->tf->a2; + case 3: + return p->tf->a3; + case 4: + return p->tf->a4; + case 5: + return p->tf->a5; + } + return -1; +} + +int argint(int n, int *ip) +{ + *ip = argraw(n); + return 0; +} + +uint64 sys_exit() +{ + int n; + if (argint(0, &n) < 0) + return -1; + ProcManager::exit(n); + return 0; +} + +uint64 sys_fork() +{ + return fork(); +} + +uint64 sys_wait() +{ + uint64 p; + p = argraw(0); + return ProcManager::wait(p); +} + +uint64 sys_getpid() +{ + return myproc()->pid; +} + +uint64 sys_putc() +{ + char c = (char)argraw(0); + Drivers::uart_putc(c); + return 0; +} + +uint64 sys_write() +{ + // 简单模拟 + int fd; + uint64 p; + int n; + + if (argint(0, &fd) < 0 || argint(2, &n) < 0) + return -1; + p = argraw(1); // buffer address + + if (fd == 1) + { + struct Proc *proc = myproc(); + // 这里应该有 vm copyin 检查,暂时直接访问物理内存 + (void)p; // 消除 unused variable 警告 + + return n; + } + return -1; +} + +void syscall() +{ + struct Proc *p = myproc(); + int num = p->tf->a7; + uint64 ret = -1; + + switch (num) + { + case SYS_putc: + ret = sys_putc(); + break; + case SYS_fork: + ret = sys_fork(); + break; + case SYS_exit: + ret = sys_exit(); + break; + case SYS_wait: + ret = sys_wait(); + break; + case SYS_getpid: + ret = sys_getpid(); + break; + case SYS_write: + ret = sys_write(); + break; + default: + Drivers::uart_puts("Unknown Syscall ID: "); + Drivers::print_hex(num); + Drivers::uart_puts("\n"); + ret = -1; + break; + } + + p->tf->a0 = ret; +}
\ No newline at end of file diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc index 4bb8c06..14ef4c5 100644 --- a/src/kernel/trap/handler.cc +++ b/src/kernel/trap/handler.cc @@ -3,8 +3,11 @@ #include "drivers/uart.h" #include "kernel/proc.h" #include "kernel/timer.h" +#include "kernel/syscall.h" +#include "kernel/riscv.h" extern void usertrapret(); +extern void forkret(); void panic(const char *s) { @@ -71,10 +74,10 @@ namespace Trap switch (scause) { case 8: - Drivers::uart_puts("[Syscall] ecall for User Mode\n"); - tf->epc += 4; + Drivers::uart_puts("[Syscall] ecall from Kernel Mode? Panic.\n"); + panic("Kernel Ecall"); break; - + case 12: case 13: case 15: @@ -136,9 +139,12 @@ extern "C" void usertrap() struct Proc *p = myproc(); extern struct Proc procs[]; - for(int i = 0; i < 10; ++i) - if(procs[i].state == RUNNING) - p = &procs[i]; + if (!p) + { + for (int i = 0; i < 10; ++i) + if (procs[i].state == RUNNING) + p = &procs[i]; + } uint64 sepc; asm volatile("csrr %0, sepc" : "=r"(sepc)); @@ -146,31 +152,26 @@ extern "C" void usertrap() if(scause == 8) { + intr_on(); p->tf->epc += 4; - uint64 syscall_num = p->tf->a7; + syscall(); - if (syscall_num == 1) - { - char c = (char)p->tf->a0; - Drivers::uart_putc(c); - } - else - { - Drivers::uart_puts("Unknown Syscall\n"); - } + intr_off(); } else if ((scause & (1L << 63)) && (scause & 0xF) == 5) { + Drivers::uart_puts("\nTick\n"); Timer::set_next_trigger(); ProcManager::yield(); } else { Drivers::uart_puts("Unexpected User Trap!\n"); + Drivers::print_hex(scause); while (1) ; } - forkret(); + usertrapret(); }
\ No newline at end of file diff --git a/src/lib/string.cc b/src/lib/string.cc new file mode 100644 index 0000000..bbd079d --- /dev/null +++ b/src/lib/string.cc @@ -0,0 +1,71 @@ +#include "lib/string.h" + +void *memset(void *dst, int c, uint n) +{ + char *cdst = (char *)dst; + for (uint i = 0; i < n; i++) + cdst[i] = c; + return dst; +} + +int memcmp(const void *v1, const void *v2, uint n) +{ + const uchar *s1 = (const uchar *)v1; + const uchar *s2 = (const uchar *)v2; + while (n-- > 0) + { + if (*s1 != *s2) + return *s1 - *s2; + s1++, s2++; + } + return 0; +} + +void *memmove(void *dst, const void *src, uint n) +{ + const char *s = (const char *)src; + char *d = (char *)dst; + if (s < d && s + n > d) + { + s += n; + d += n; + while (n-- > 0) + *--d = *--s; + } + else + { + while (n-- > 0) + *d++ = *s++; + } + return dst; +} + +void *memcpy(void *dst, const void *src, uint n) +{ + return memmove(dst, src, n); +} + +void strcpy(char *dst, const char *src) +{ + while (*src) + *dst++ = *src++; + *dst = 0; +} + +int strlen(const char *s) +{ + int n = 0; + while (s[n]) + n++; + return n; +} + +int strcmp(const char *s1, const char *s2) +{ + while (*s1 && (*s1 == *s2)) + { + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; +} |
