// This is NEW CODE implementing system calls (however the headers etc. still need to be refactored) #include "syscall.h" #include "types.h" #include "riscv.h" #include "defs.h" #include "param.h" #include "memlayout.h" #include "sched.h" #include "proc.h" #include "drives.h" #include "file.h" #include "stat.h" #include "kprintf.h" //TODO: This is still using the "argfd" defined in sysfile.c for now. int argfd(int n, int *pfd, struct file **pf); void* memcpy(void*, void*, long); // new syscall added by Zak, sets the priority+limit of a process // currently only works on the current process's pid! uint64 sys_prio(void) { int tpid; int newprio; int newlimit; argint(0, &tpid); argint(1, &newprio); argint(2, &newlimit); if (tpid != myproc()->pid) { return 0; } if (newprio >= NPRIO) { newprio = NPRIO-1; } if (newlimit >= NPRIO) { newlimit = NPRIO-1; } //struct proc* p = myproc(); if (newlimit < myproc()->maxprio) { newlimit = myproc()->maxprio; } if (newprio < newlimit) { newprio = newlimit; } myproc()->prio = newprio; myproc()->maxprio = newlimit; yield(); return 1; } uint64 sys_thrd(void) { int frompid; uint64 fnc; uint64 stk; uint64 arg; argint(0, &frompid); argaddr(1, &fnc); argaddr(2, &stk); argaddr(3, &arg); if (stk & 7) { return -1; } if (frompid != myproc()->pid && !(myproc()->mainthread && frompid == myproc()->mainthread->pid)) { return -1; } return thrd(fnc, stk, arg); } uint64 sys_affin(void) { int targetpid; int range; uint64 mask; argint(0, &targetpid); argint(1, &range); argaddr(2, &mask); if (targetpid != myproc()->pid || range != 0) { return -1; } return affin(mask); } uint64 sys_drvinf() { int driveid; uint64 structaddr; argint(0, &driveid); argaddr(1, &structaddr); // The actual information is first retrieved into a structure inside // of kernel memory. struct __syscdefs_driveinfo drvinf; int result = drives_getinfo(myproc()->drives, driveid, &drvinf); // The structure is copied whether the function succeeded or not, it // will zero the structure on failure. copyout(myproc()->pagetable, structaddr, (void*) &drvinf, sizeof(struct __syscdefs_driveinfo)); return result; } int readdirent(struct file* f, uint64 addr, int n) { if (n != sizeof(fsformat_dirent_v1_t)) { return -1; } if (f->type != FD_INODE || f->ip->type != T_DIR) { return -1; } if (f->ip->instance->fsversion == 0) { fsformat_dirent_v0_t dirent_old; fsformat_dirent_v1_t dirent_new; if (fsinstance_inode_read(f->ip, 0, (uint64) ((void*) &dirent_old), f->off, sizeof(fsformat_dirent_v0_t)) != sizeof(fsformat_dirent_v0_t)) { return -1; } else { f->off += sizeof(fsformat_dirent_v0_t); } dirent_new.datainode = dirent_old.inodenumber; dirent_new.metainode = -1; memset(dirent_new.filename, 0, FSFORMAT_NAMESIZE_NEW); memcpy(dirent_new.filename, dirent_old.filename, FSFORMAT_NAMESIZE_OLD); copyout(myproc()->pagetable, addr, (void*) &dirent_new, sizeof(fsformat_dirent_v1_t)); return (int) sizeof(fsformat_dirent_v1_t); } else { if (fsinstance_inode_read(f->ip, 1, addr, f->off, n) != n) { return -1; } f->off += sizeof(fsformat_dirent_v1_t); return (int) sizeof(fsformat_dirent_v1_t); } } uint64 sys_lsdir() { struct file* f; uint64 addr; int size; if (argfd(0, 0, &f) < 0) { return -1; } argaddr(1, &addr); argint(2, &size); return readdirent(f, addr, size); } uint64 sys_kqueue1() { int flags; argint(0, &flags); kprintf_panic("sys_kqueue1: TODO!"); return 0; } uint64 sys_kevent() { kprintf_panic("sys_kevent: TODO!"); return 0; } // Definitions of old syscalls uint64 sys_fork(); uint64 sys_exit(); uint64 sys_wait(); uint64 sys_pipe(); uint64 sys_read(); uint64 sys_kill(); uint64 sys_execve(); uint64 sys_fstat(); uint64 sys_chdir(); uint64 sys_dup(); uint64 sys_getpid(); uint64 sys_sbrk(); uint64 sys_sleep(); uint64 sys_uptime(); uint64 sys_open(); uint64 sys_write(); uint64 sys_mknod(); uint64 sys_unlink(); uint64 sys_link(); uint64 sys_mkdir(); uint64 sys_close(); typedef uint64 (*syscall_t)(); // The system is currently hard-coded to handle a table of exactly 64 syscalls. // This number is convenient for masking in a 64-bit system. syscall_t syscalls[64]; /* This is invoked when the syscall doesn't exist. */ uint64 sys_bad() { printf("ERROR IN PROCESS %d '%s' BAD SYSCALL %d\n", myproc()->pid, myproc()->name, (int) myproc()->trapframe->a7); return -1; } void syscall_init() { int i; for (i = 0 ; i < 64; i++) { syscalls[i] = &sys_bad; } syscalls[SYS_fork] = &sys_fork; syscalls[SYS_exit] = &sys_exit; syscalls[SYS_wait] = &sys_wait; syscalls[SYS_pipe] = &sys_pipe; syscalls[SYS_read] = &sys_read; syscalls[SYS_kill] = &sys_kill; syscalls[SYS_execve] = &sys_execve; syscalls[SYS_fstat] = &sys_fstat; syscalls[SYS_chdir] = &sys_chdir; syscalls[SYS_dup] = &sys_dup; syscalls[SYS_getpid] = &sys_getpid; syscalls[SYS_sbrk] = &sys_sbrk; syscalls[SYS_sleep] = &sys_sleep; syscalls[SYS_uptime] = &sys_uptime; syscalls[SYS_open] = &sys_open; syscalls[SYS_write] = &sys_write; syscalls[SYS_mknod] = &sys_mknod; syscalls[SYS_unlink] = &sys_unlink; syscalls[SYS_link] = &sys_link; syscalls[SYS_mkdir] = &sys_mkdir; syscalls[SYS_close] = &sys_close; // New system calls: syscalls[SYS_prio] = &sys_prio; syscalls[SYS_affin] = &sys_affin; syscalls[SYS_thrd] = &sys_thrd; syscalls[SYS_drvinf] = &sys_drvinf; syscalls[SYS_lsdir] = &sys_lsdir; syscalls[SYS_kqueue1] = &sys_kqueue1; syscalls[SYS_kevent] = &sys_kevent; } // New syscall handling. This will just invoke sys_bad() if the syscall doesn't // exist, this means there's one less error to check for. void syscall() { int x = myproc()->trapframe->a7; //printf("Doing syscall #%d (0x%x)\n", x & 63, x & 63); // TODO: This should be checked against a mask to allow and/or redirect syscalls. syscall_t func = syscalls[x & 63]; //printf("Syscall func is at %p\n", func); myproc()->trapframe->a0 = func(); }