diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-01-04 14:05:49 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-01-04 14:05:49 +0800 |
| commit | d3cf3f08d1343d6b265516d5a79ce2d197b59d26 (patch) | |
| tree | a4bbae6cff94fa69eea30db865267b211eb4c86b /src/kernel | |
| parent | 210025560c80b48af4875af199f183ad709e3bf0 (diff) | |
| download | lume-d3cf3f08d1343d6b265516d5a79ce2d197b59d26.tar.gz lume-d3cf3f08d1343d6b265516d5a79ce2d197b59d26.tar.xz | |
feat(file-system): implement read and write FAT32 File System and basic shell
Diffstat (limited to 'src/kernel')
| -rw-r--r-- | src/kernel/cxx.cc | 6 | ||||
| -rw-r--r-- | src/kernel/proc/proc.cc | 32 | ||||
| -rw-r--r-- | src/kernel/sbi.cc | 14 | ||||
| -rw-r--r-- | src/kernel/syscall.cc | 297 | ||||
| -rw-r--r-- | src/kernel/timer.cc | 38 | ||||
| -rw-r--r-- | src/kernel/trap/handler.cc | 3 |
6 files changed, 373 insertions, 17 deletions
diff --git a/src/kernel/cxx.cc b/src/kernel/cxx.cc index f9541b5..14bfe68 100644 --- a/src/kernel/cxx.cc +++ b/src/kernel/cxx.cc @@ -65,4 +65,10 @@ void operator delete[](void *p, unsigned long size) (void)size; if (p) PMM::free_page(p); +} + +void *operator new(unsigned long size, void *ptr) +{ + (void)size; + return ptr; }
\ No newline at end of file diff --git a/src/kernel/proc/proc.cc b/src/kernel/proc/proc.cc index 5db5f7a..6940a3e 100644 --- a/src/kernel/proc/proc.cc +++ b/src/kernel/proc/proc.cc @@ -152,7 +152,8 @@ void forkret() struct cpu *c = mycpu(); c->runqueue->lock.release(); - Drivers::uart_puts("[Proc] forkret: jumping to user.\n"); + // Debug + // Drivers::uart_puts("[Proc] forkret: jumping to user.\n"); // Enter user mode usertrapret(); @@ -185,6 +186,7 @@ static Proc *allocproc() p->state = USED; p->pid = nextpid++; p->priority = 0; + p->killed = 0; p->cpu = mycpu(); p->cwd = nullptr; for (int i = 0; i < NOFILE; i++) @@ -587,6 +589,34 @@ namespace ProcManager } } + int kill(int pid) + { + Proc* p; + proc_mem_lock.acquire(); + for (p = proc_list_head; p != nullptr; p = p->all_next) + { + if (p->pid == pid) + { + p->killed = 1; + + if (p->state == SLEEPING) + { + p->state = RUNNABLE; + + struct cpu *c = mycpu(); + c->runqueue->lock.acquire(); + c->runqueue->enqueue(p); + c->runqueue->lock.release(); + } + + proc_mem_lock.release(); + return 0; + } + } + proc_mem_lock.release(); + return -1; + } + int growproc(int n) { uint64 sz; diff --git a/src/kernel/sbi.cc b/src/kernel/sbi.cc index 442d219..9570d74 100644 --- a/src/kernel/sbi.cc +++ b/src/kernel/sbi.cc @@ -1,4 +1,5 @@ #include "common/types.h" +#include "kernel/sbi.h" namespace SBI { @@ -31,4 +32,17 @@ namespace SBI { sbi_call(0x54494D45, 0, stime_value, 0, 0); } + + void sbi_shutdown() + { + sbi_call(0x53525354, 0, 0, 0, 0); + sbi_call(0x08, 0, 0, 0, 0); + while (1) + ; + } + + void sbi_reboot() + { + sbi_call(SBI_EID_SRST, SBI_FID_SRST_RESET, SBI_SRST_TYPE_COLD_REBOOT, SBI_SRST_REASON_NONE, 0); + } }
\ No newline at end of file diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc index 6af7730..259a5e6 100644 --- a/src/kernel/syscall.cc +++ b/src/kernel/syscall.cc @@ -9,6 +9,7 @@ #include "kernel/mm.h" #include "kernel/trap.h" #include "kernel/slab.h" +#include "kernel/sbi.h" #include "fs/fat32.h" #include "fs/file.h" #include "lib/string.h" @@ -113,12 +114,38 @@ static uint64 sys_open() if (argstr(0, path, 128) < 0 || argint(1, &omode) < 0) return -1; - ip = VFS::namei(path); + if (omode & O_CREATE) + { + ip = VFS::namei(path); + if (ip == nullptr) + { + char name[128]; + Inode *dp = VFS::nameiparent(path, name); + if (dp) + { + VFS::ilock(dp); + ip = dp->create(name, T_FILE, 0, 0); + VFS::iunlockput(dp); + } + } + } + else + { + ip = VFS::namei(path); + } + if (ip == nullptr) { return -1; } + VFS::ilock(ip); + if ((omode & O_TRUNC) && ip->type == T_FILE) + { + ip->truncate(); + } + VFS::iunlock(ip); + f = FileTable::alloc(); if (f == nullptr) { @@ -144,6 +171,128 @@ static uint64 sys_open() return fd; } +static uint64 sys_mkdir() +{ + char path[128]; + if (argstr(0, path, 128) < 0) + return -1; + + Inode *ip = VFS::namei(path); + if (ip != nullptr) + { + VFS::iput(ip); + return -1; // the dir is exist + } + + char name[128]; + Inode *dp = VFS::nameiparent(path, name); + if (dp == nullptr) + return -1; + + VFS::ilock(dp); + ip = dp->create(name, T_DIR, 0, 0); + VFS::iunlockput(dp); + + if (ip == nullptr) + return -1; + + VFS::iput(ip); + return 0; +} + +static uint64 sys_chdir() +{ + char path[128]; + if (argstr(0, path, 128) < 0) + return -1; + + Inode *ip = VFS::namei(path); + if (ip == nullptr) + return -1; + + VFS::ilock(ip); + if (ip->type != T_DIR) + { + VFS::iunlockput(ip); + return -1; + } + VFS::iunlock(ip); + + struct Proc *p = myproc(); + VFS::iput(p->cwd); // release old cwd + p->cwd = ip; // switch to new cwd + + return 0; +} + +static uint64 sys_dup() +{ + int oldfd; + if (argint(0, &oldfd) < 0) + return -1; + + struct Proc *p = myproc(); + if (oldfd < 0 || oldfd >= NOFILE || p->ofile[oldfd] == nullptr) + return -1; + + struct file *f = FileTable::dup(p->ofile[oldfd]); + int newfd = fdalloc(f); + if (newfd < 0) + { + FileTable::close(f); // fdalloc failed + return -1; + } + return newfd; +} + +static uint64 sys_fstat() +{ + int fd; + uint64 stat_addr; + + if (argint(0, &fd) < 0 || argint(1, (int *)&stat_addr) < 0) + return -1; + + struct Proc *p = myproc(); + if (fd < 0 || fd >= NOFILE || p->ofile[fd] == nullptr) + return -1; + + return FileTable::stat(p->ofile[fd], stat_addr); +} + +static uint64 sys_mknod() +{ + char path[128]; + int major, minor; + + if (argstr(0, path, 128) < 0 || argint(1, &major) < 0 || argint(2, &minor) < 0) + return -1; + + Inode *ip = VFS::namei(path); + if (ip != nullptr) + { + VFS::iput(ip); + return -1; + } + + char name[128]; + Inode *dp = VFS::nameiparent(path, name); + if (dp == nullptr) + return -1; + + VFS::ilock(dp); + ip = dp->create(name, T_DEVICE, major, minor); + VFS::iunlockput(dp); + + if (ip == nullptr) + return -1; + + VFS::iput(ip); + return 0; +} + + + static uint64 sys_close() { int fd; @@ -159,6 +308,63 @@ static uint64 sys_close() return 0; } +static uint64 sys_pipe() +{ + uint64 fdarray; // int fd[2] + struct file *rf, *wf; + int fd0, fd1; + struct Proc *p = myproc(); + + if (argint(0, (int *)&fdarray) < 0) + return -1; + + if(Pipe::create_pair(&rf, &wf) < 0) + return -1; + + if ((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0) + { + if (fd0 >= 0) + p->ofile[fd0] = nullptr; + FileTable::close(rf); + FileTable::close(wf); + return -1; + } + + if (VM::copyout(p->pagetable, fdarray, (char *)&fd0, sizeof(int)) < 0 || + VM::copyout(p->pagetable, fdarray + sizeof(int), (char *)&fd1, sizeof(int)) < 0) + { + p->ofile[fd0] = nullptr; + p->ofile[fd1] = nullptr; + FileTable::close(rf); + FileTable::close(wf); + return -1; + } + return 0; +} + +static uint64 sys_link() +{ + Drivers::uart_puts("Not supported now"); + return -1; +} + +static uint64 sys_unlink() +{ + char path[128], name[128]; + if (argstr(0, path, 128) < 0) + return -1; + + Inode *dp = VFS::nameiparent(path, name); + if (!dp) + return -1; + + VFS::ilock(dp); + int ret = dp->unlink(name); + VFS::iunlockput(dp); + + return ret; +} + static uint64 sys_exec() { char path[128]; @@ -169,10 +375,7 @@ static uint64 sys_exec() return -1; } - if (argint(1, (int *)&uargv_ptr) < 0) - { - return -1; - } + uargv_ptr = argraw(1); KernelArgv kargv; @@ -328,6 +531,48 @@ static uint64 sys_sbrk() return addr; } +static uint64 sys_uptime() +{ + return Timer::get_ticks(); +} + +static uint64 sys_kill() +{ + int pid; + if (argint(0, &pid) < 0) + return -1; + + return ProcManager::kill(pid); +} + +static uint64 sys_sleep() +{ + int n; + uint64 ticks0; + + if (argint(0, &n) < 0) + return -1; + + Spinlock *lk = Timer::get_lock(); + lk->acquire(); + + ticks0 = Timer::get_ticks(); + + while (Timer::get_ticks() - ticks0 < (uint64)n) + { + if (myproc()->killed) + { + lk->release(); + return -1; + } + + ProcManager::sleep(Timer::get_tick_chan(), lk); + } + + lk->release(); + return 0; +} + static uint64 sys_disk_test() { // VirtIO::test_rw(); @@ -349,6 +594,14 @@ static uint64 sys_lseek() return FileTable::lseek(p->ofile[fd], offset, whence); } +static uint64 sys_shutdown() +{ + SBI::sbi_shutdown(); + while (1) + ; + return 0; +} + void syscall() { Proc *p = myproc(); @@ -383,9 +636,7 @@ void syscall() case SYS_exec: ret = sys_exec(); if (ret != static_cast<uint64>(-1)) - { return; - } break; case SYS_exit: ret = sys_exit(); @@ -405,16 +656,42 @@ void syscall() case SYS_lseek: ret = sys_lseek(); break; - case SYS_pipe: case SYS_dup: - case SYS_chdir: + ret = sys_dup(); + break; case SYS_fstat: + ret = sys_fstat(); + break; + case SYS_chdir: + ret = sys_chdir(); + break; case SYS_mkdir: + ret = sys_mkdir(); + break; case SYS_mknod: + ret = sys_mknod(); + break; + case SYS_pipe: + ret = sys_pipe(); + break; case SYS_unlink: + ret = sys_unlink(); + break; case SYS_link: Drivers::uart_puts("Unimplemented syscall\n"); - ret = static_cast<uint64>(-1); + ret = sys_link(); + break; + case SYS_uptime: + ret = sys_uptime(); + break; + case SYS_sleep: + ret = sys_sleep(); + break; + case SYS_kill: + ret = sys_kill(); + break; + case SYS_shutdown: + ret = sys_shutdown(); break; default: Drivers::uart_puts("Unknown Syscall ID: "); diff --git a/src/kernel/timer.cc b/src/kernel/timer.cc index fb871d5..3cbf11e 100644 --- a/src/kernel/timer.cc +++ b/src/kernel/timer.cc @@ -1,15 +1,16 @@ #include "common/types.h" #include "kernel/config.h" - -namespace SBI -{ - void set_timer(uint64 stime_value); -} +#include "kernel/spinlock.h" +#include "kernel/proc.h" +#include "kernel/sbi.h" #define INTERVAL 1000000 namespace Timer { + uint64 ticks; + Spinlock tickslock; + uint64 get_time() { uint64 time; @@ -31,4 +32,31 @@ namespace Timer sie |= (1L << 5); asm volatile("csrw sie, %0" : : "r"(sie)); } + + void tick() + { + tickslock.acquire(); + ticks++; + ProcManager::wakeup(&ticks); + tickslock.release(); + set_next_trigger(); + } + + uint64 get_ticks() + { + tickslock.acquire(); + uint64 t = ticks; + tickslock.release(); + return t; + } + + Spinlock *get_lock() + { + return &tickslock; + } + + void *get_tick_chan() + { + return &ticks; + } }
\ No newline at end of file diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc index 3fb772e..7e4d11e 100644 --- a/src/kernel/trap/handler.cc +++ b/src/kernel/trap/handler.cc @@ -85,7 +85,8 @@ namespace Trap else if (is_interrupt && code == 5) { // Supervisor Timer Interrupt (IRQ 5) - Timer::set_next_trigger(); + // Timer::set_next_trigger(); + Timer::tick(); // w_sip(r_sip() & ~2); return 2; } |
